summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:22 +0000
commitc21c3b0befeb46a51b6bf3758ffa30813bea0ff0 (patch)
tree9754ff1ca740f6346cf8483ec915d4054bc5da2d /fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common
parentAdding upstream version 1.43.2. (diff)
downloadnetdata-c21c3b0befeb46a51b6bf3758ffa30813bea0ff0.tar.xz
netdata-c21c3b0befeb46a51b6bf3758ffa30813bea0ff0.zip
Adding upstream version 1.44.3.upstream/1.44.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/common')
-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
35 files changed, 16713 insertions, 0 deletions
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 */