Quellcode durchsuchen

Add unit test suites (#3490)

Zhang, Yi vor 1 Jahr
Ursprung
Commit
380cd7b0e7
100 geänderte Dateien mit 7972 neuen und 36 gelöschten Zeilen
  1. 37 36
      tests/unit/CMakeLists.txt
  2. 55 0
      tests/unit/aot-stack-frame/CMakeLists.txt
  3. 288 0
      tests/unit/aot-stack-frame/aot_stack_frame_test.cc
  4. 27 0
      tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt
  5. 36 0
      tests/unit/aot-stack-frame/wasm-apps/test.wast
  6. 59 0
      tests/unit/aot/CMakeLists.txt
  7. 1190 0
      tests/unit/aot/aot_test.cc
  8. 89 0
      tests/unit/common/mock_allocator.h
  9. 325 0
      tests/unit/common/test_helper.h
  10. 72 0
      tests/unit/compilation/CMakeLists.txt
  11. 203 0
      tests/unit/compilation/aot_compiler_test.cc
  12. 104 0
      tests/unit/compilation/aot_emit_aot_file_test.cc
  13. 112 0
      tests/unit/compilation/aot_emit_compare_test.cc
  14. 196 0
      tests/unit/compilation/aot_emit_control_test.cc
  15. 101 0
      tests/unit/compilation/aot_emit_function_test.cc
  16. 335 0
      tests/unit/compilation/aot_emit_memory_test.cc
  17. 119 0
      tests/unit/compilation/aot_emit_numberic_test.cc
  18. 143 0
      tests/unit/compilation/aot_emit_parametric_test.cc
  19. 105 0
      tests/unit/compilation/aot_emit_table_test.cc
  20. 97 0
      tests/unit/compilation/aot_emit_variable_test.cc
  21. 305 0
      tests/unit/compilation/aot_llvm_test.cc
  22. BIN
      tests/unit/compilation/wasm-apps/main.wasm
  23. 65 0
      tests/unit/custom-section/CMakeLists.txt
  24. 161 0
      tests/unit/custom-section/custom_section_test.cc
  25. 14 0
      tests/unit/custom-section/wasm-apps/CMakeLists.txt
  26. 10 0
      tests/unit/custom-section/wasm-apps/app.c
  27. 51 0
      tests/unit/gc/CMakeLists.txt
  28. 102 0
      tests/unit/gc/gc_test.cc
  29. BIN
      tests/unit/gc/wasm-apps/func1.wasm
  30. 35 0
      tests/unit/gc/wasm-apps/func1.wast
  31. BIN
      tests/unit/gc/wasm-apps/func2.wasm
  32. 78 0
      tests/unit/gc/wasm-apps/func2.wast
  33. BIN
      tests/unit/gc/wasm-apps/global1.wasm
  34. 91 0
      tests/unit/gc/wasm-apps/global1.wast
  35. BIN
      tests/unit/gc/wasm-apps/struct1.wasm
  36. 10 0
      tests/unit/gc/wasm-apps/struct1.wast
  37. BIN
      tests/unit/gc/wasm-apps/struct2.wasm
  38. 33 0
      tests/unit/gc/wasm-apps/struct2.wast
  39. BIN
      tests/unit/gc/wasm-apps/struct3.wasm
  40. 9 0
      tests/unit/gc/wasm-apps/struct3.wast
  41. BIN
      tests/unit/gc/wasm-apps/table1.wasm
  42. 108 0
      tests/unit/gc/wasm-apps/table1.wast
  43. BIN
      tests/unit/gc/wasm-apps/test1.wasm
  44. 117 0
      tests/unit/gc/wasm-apps/test1.wast
  45. BIN
      tests/unit/gc/wasm-apps/test2.wasm
  46. 104 0
      tests/unit/gc/wasm-apps/test2.wast
  47. BIN
      tests/unit/gc/wasm-apps/test3.wasm
  48. 146 0
      tests/unit/gc/wasm-apps/test3.wast
  49. BIN
      tests/unit/gc/wasm-apps/test4.wasm
  50. 46 0
      tests/unit/gc/wasm-apps/test4.wast
  51. BIN
      tests/unit/gc/wasm-apps/test5.wasm
  52. 85 0
      tests/unit/gc/wasm-apps/test5.wast
  53. BIN
      tests/unit/gc/wasm-apps/test6.wasm
  54. 27 0
      tests/unit/gc/wasm-apps/test6.wast
  55. 1 0
      tests/unit/interpreter/.gitignore
  56. 42 0
      tests/unit/interpreter/CMakeLists.txt
  57. 50 0
      tests/unit/interpreter/interpreter_test.cc
  58. 32 0
      tests/unit/libc-builtin/CMakeLists.txt
  59. 170 0
      tests/unit/libc-builtin/func_types.h
  60. 1412 0
      tests/unit/libc-builtin/libc_builtin_test.cc
  61. 78 0
      tests/unit/linear-memory-aot/CMakeLists.txt
  62. 45 0
      tests/unit/linear-memory-aot/build_aot.sh
  63. 361 0
      tests/unit/linear-memory-aot/linear_memory_aot_test.cc
  64. 16 0
      tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast
  65. 16 0
      tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast
  66. 1 0
      tests/unit/linear-memory-aot/mem_page_01.wast
  67. 1 0
      tests/unit/linear-memory-aot/mem_page_02.wast
  68. 1 0
      tests/unit/linear-memory-aot/mem_page_03.wast
  69. 1 0
      tests/unit/linear-memory-aot/mem_page_05.wast
  70. 1 0
      tests/unit/linear-memory-aot/mem_page_07.wast
  71. 1 0
      tests/unit/linear-memory-aot/mem_page_08.wast
  72. 1 0
      tests/unit/linear-memory-aot/mem_page_09.wast
  73. 1 0
      tests/unit/linear-memory-aot/mem_page_10.wast
  74. 1 0
      tests/unit/linear-memory-aot/mem_page_12.wast
  75. 1 0
      tests/unit/linear-memory-aot/mem_page_14.wast
  76. 1 0
      tests/unit/linear-memory-aot/mem_page_16.wast
  77. 1 0
      tests/unit/linear-memory-aot/mem_page_20.wast
  78. 10 0
      tests/unit/linear-memory-aot/out_of_bounds.wast
  79. 2 0
      tests/unit/linear-memory-aot/readme
  80. 59 0
      tests/unit/linear-memory-wasm/CMakeLists.txt
  81. 327 0
      tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc
  82. 16 0
      tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast
  83. 16 0
      tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast
  84. 1 0
      tests/unit/linear-memory-wasm/mem_page_01.wast
  85. 1 0
      tests/unit/linear-memory-wasm/mem_page_02.wast
  86. 1 0
      tests/unit/linear-memory-wasm/mem_page_03.wast
  87. 1 0
      tests/unit/linear-memory-wasm/mem_page_04.wast
  88. 1 0
      tests/unit/linear-memory-wasm/mem_page_05.wast
  89. 1 0
      tests/unit/linear-memory-wasm/mem_page_06.wast
  90. 1 0
      tests/unit/linear-memory-wasm/mem_page_07.wast
  91. 1 0
      tests/unit/linear-memory-wasm/mem_page_08.wast
  92. 1 0
      tests/unit/linear-memory-wasm/mem_page_09.wast
  93. 1 0
      tests/unit/linear-memory-wasm/mem_page_10.wast
  94. 1 0
      tests/unit/linear-memory-wasm/mem_page_11.wast
  95. 1 0
      tests/unit/linear-memory-wasm/mem_page_12.wast
  96. 1 0
      tests/unit/linear-memory-wasm/mem_page_13.wast
  97. 1 0
      tests/unit/linear-memory-wasm/mem_page_14.wast
  98. 1 0
      tests/unit/linear-memory-wasm/mem_page_15.wast
  99. 1 0
      tests/unit/linear-memory-wasm/mem_page_16.wast
  100. 1 0
      tests/unit/linear-memory-wasm/mem_page_17.wast

+ 37 - 36
tests/unit/CMakeLists.txt

@@ -1,51 +1,52 @@
-# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-cmake_minimum_required (VERSION 3.14)
+cmake_minimum_required(VERSION 2.9)
 
-project (wamr_unit_tests)
+project(unit-test)
 
-include (CTest)
+SET(CMAKE_BUILD_TYPE Debug)
 
-if (NOT DEFINED WAMR_BUILD_INTERP)
-  # Enable Interpreter by default
-  set (WAMR_BUILD_INTERP 1)
-endif ()
+# add_definitions (-m32)
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
 
-if (NOT DEFINED WAMR_BUILD_PLATFORM)
-  string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
-endif ()
+if(WAMR_BUILD_TARGET STREQUAL "X86_32")
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
+  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
+endif()
 
-set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
-include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
-add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
+# Prevent overriding the parent project's compiler/linker
+# settings on Windows
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
 
+# Fetch Google test
 include (FetchContent)
 FetchContent_Declare (
     googletest
     URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
 )
-# For Windows: Prevent overriding the parent project's compiler/linker settings
-set (gtest_force_shared_crt ON CACHE BOOL "" FORCE)
 FetchContent_MakeAvailable (googletest)
 
-include (GoogleTest)
-
-add_library (wamr_gtest_main main.cpp)
-target_link_libraries (wamr_gtest_main PUBLIC gtest vmlib)
-
-function (create_wamr_unit_test test_name)
-    set (sources ${ARGN})
-    add_executable (${test_name} ${sources})
-    target_link_libraries (
-        ${test_name}
-        wamr_gtest_main
-        vmlib
-        ${LLVM_AVAILABLE_LIBS}
-    )
-    gtest_discover_tests (${test_name})
-    endfunction ()
-
-if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1)
-    include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake)
-endif ()
+SET(GOOGLETEST_INCLUDED 1)
+
+include(GoogleTest)
+enable_testing()
+
+add_subdirectory(wasm-vm)
+add_subdirectory(interpreter)
+add_subdirectory(aot)
+add_subdirectory(wasm-c-api)
+add_subdirectory(libc-builtin)
+add_subdirectory(shared-utils)
+add_subdirectory(running-modes)
+add_subdirectory(runtime-common)
+add_subdirectory(custom-section)
+add_subdirectory(compilation)
+add_subdirectory(linear-memory-wasm)
+add_subdirectory(linear-memory-aot)
+add_subdirectory(aot-stack-frame)
+add_subdirectory(linux-perf)
+add_subdirectory(gc)
+add_subdirectory(memory64)
+add_subdirectory(tid-allocator)

+ 55 - 0
tests/unit/aot-stack-frame/CMakeLists.txt

@@ -0,0 +1,55 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-aot-stack-frame)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_AOT 1)
+set (WAMR_BUILD_INTERP 0)
+set (WAMR_BUILD_JIT 0)
+set (WAMR_BUILD_SIMD 1)
+set (WAMR_BUILD_REF_TYPES 1)
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_LIBC_BUILTIN 0)
+set (WAMR_BUILD_MULTI_MODULE 0)
+set (WAMR_DISABLE_HW_BOUND_CHECK 1)
+set (WAMR_DISABLE_WRITE_GS_BASE 1)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+add_definitions (-DAOT_STACK_FRAME_DEBUG)
+#add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${WASM_APP_LIB_SOURCE_ALL}
+    )
+
+# Automatically build wasm-apps for this test
+add_subdirectory(wasm-apps)
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (aot_stack_frame_test ${unit_test_sources})
+
+add_dependencies (aot_stack_frame_test aot-stack-frame-test-wasm)
+
+target_link_libraries (aot_stack_frame_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+#gtest_discover_tests(aot_stack_frame_test)

+ 288 - 0
tests/unit/aot-stack-frame/aot_stack_frame_test.cc

@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include "wasm_runtime_common.h"
+#include "aot_runtime.h"
+#include "test_helper.h"
+
+#ifndef __aligned
+#define __aligned(n)
+#endif
+#include "wasm-apps/test_aot.h"
+
+typedef struct MyAOTFrame {
+    uintptr_t func_index;
+
+    /* Instruction pointer: offset to the bytecode array */
+    uintptr_t ip_offset;
+
+    /* Operand stack top pointer of the current frame */
+    uint32 *sp;
+
+#if WASM_ENABLE_GC != 0
+    /* Frame ref flags (GC only) */
+    uint8 *frame_ref;
+#endif
+
+    uint32 lp[1];
+} MyAOTFrame;
+
+class AOTStackFrameTest : public testing::Test
+{
+  protected:
+    virtual void SetUp()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
+    }
+
+    virtual void TearDown()
+    {
+        DestroyFrames();
+        wasm_runtime_destroy();
+    }
+
+  public:
+    static void DestroyFrames()
+    {
+        if (my_frames) {
+            for (uint32 i = 0; i < my_frame_num; i++) {
+                if (my_frames[i])
+                    wasm_runtime_free(my_frames[i]);
+            }
+            wasm_runtime_free(my_frames);
+            my_frames = NULL;
+            my_frame_num = 0;
+        }
+    }
+
+  public:
+    RuntimeInitArgs init_args;
+    wasm_module_t module = NULL;
+    wasm_module_inst_t module_inst = NULL;
+    wasm_function_inst_t func_inst = NULL;
+    wasm_exec_env_t exec_env = NULL;
+    static MyAOTFrame **my_frames;
+    static uint32 my_frame_num;
+    char error_buf[128];
+    char global_heap_buf[512 * 1024];
+    unsigned char test_aot_buf[16 * 1024];
+    unsigned argv[8];
+};
+
+MyAOTFrame **AOTStackFrameTest::my_frames = NULL;
+uint32 AOTStackFrameTest::my_frame_num = 0;
+
+extern "C" {
+
+typedef void (*stack_frame_callback_t)(struct WASMExecEnv *exec_env);
+
+void
+aot_set_stack_frame_callback(stack_frame_callback_t callback);
+
+void
+aot_stack_frame_cb(struct WASMExecEnv *exec_env)
+{
+    AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+    AOTModule *module = (AOTModule *)module_inst->module;
+    AOTFrame *frame = (AOTFrame *)exec_env->cur_frame;
+    MyAOTFrame *my_frame, **my_frames;
+    uint32 all_cell_num, max_local_cell_num, max_stack_cell_num;
+    uint32 frame_size_old, frame_size, i, frame_num = 0, aot_func_idx;
+
+    AOTStackFrameTest::DestroyFrames();
+
+    while (frame) {
+        frame_num++;
+        frame = frame->prev_frame;
+    }
+
+    my_frames =
+        (MyAOTFrame **)wasm_runtime_malloc(sizeof(MyAOTFrame *) * frame_num);
+    bh_assert(my_frames);
+
+    frame = (AOTFrame *)exec_env->cur_frame;
+    for (i = 0; i < frame_num; i++) {
+        aot_func_idx = frame->func_index;
+        max_local_cell_num = module->max_local_cell_nums[aot_func_idx];
+        max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx];
+        all_cell_num = max_local_cell_num + max_stack_cell_num;
+
+        frame_size_old = (uint32)offsetof(AOTFrame, lp) + all_cell_num * 4;
+        frame_size = (uint32)offsetof(MyAOTFrame, lp) + all_cell_num * 4;
+
+        my_frames[frame_num - 1 - i] = my_frame =
+            (MyAOTFrame *)wasm_runtime_malloc(frame_size);
+
+        my_frame->func_index = aot_func_idx;
+        my_frame->ip_offset = frame->ip_offset;
+        my_frame->sp = my_frame->lp + (frame->sp - frame->lp);
+#if WASM_ENABLE_GC != 0
+        my_frame->frame_ref =
+            (uint8 *)my_frame->lp + (frame->frame_ref - (uint8 *)frame->lp);
+#endif
+
+        bh_memcpy_s(my_frame->lp, all_cell_num * 4, frame->lp,
+                    all_cell_num * 4);
+
+        frame = frame->prev_frame;
+    }
+
+    AOTStackFrameTest::my_frames = my_frames;
+    AOTStackFrameTest::my_frame_num = frame_num;
+}
+}
+
+TEST_F(AOTStackFrameTest, test1)
+{
+    MyAOTFrame *frame, **frames;
+    uint32 frame_num;
+
+    aot_set_stack_frame_callback(aot_stack_frame_cb);
+
+    bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot));
+
+    module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf,
+                               sizeof(error_buf));
+    ASSERT_TRUE(module != NULL);
+
+    module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf,
+                                           sizeof(error_buf));
+    ASSERT_TRUE(module_inst != NULL);
+
+    exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024);
+    ASSERT_TRUE(exec_env != NULL);
+
+    func_inst = wasm_runtime_lookup_function(module_inst, "test1");
+    ASSERT_TRUE(func_inst != NULL);
+
+    argv[0] = 33;
+    argv[1] = 44;
+    wasm_runtime_call_wasm(exec_env, func_inst, 2, argv);
+    ASSERT_TRUE(wasm_runtime_get_exception(module_inst));
+
+    frames = AOTStackFrameTest::my_frames;
+    frame_num = AOTStackFrameTest::my_frame_num;
+
+    ASSERT_TRUE(frames != NULL);
+    ASSERT_TRUE(frame_num == 1);
+
+    ASSERT_TRUE(frames[0]->lp[0] == 33);
+    ASSERT_TRUE(frames[0]->lp[1] == 44);
+    ASSERT_TRUE(frames[0]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL);
+    ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f);
+    ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322);
+
+    wasm_runtime_destroy_exec_env(exec_env);
+    exec_env = NULL;
+
+    wasm_runtime_deinstantiate(module_inst);
+    module_inst = NULL;
+
+    wasm_runtime_unload(module);
+    module = NULL;
+}
+
+TEST_F(AOTStackFrameTest, test2)
+{
+    MyAOTFrame *frame, **frames;
+    uint32 frame_num;
+
+    aot_set_stack_frame_callback(aot_stack_frame_cb);
+
+    bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot));
+
+    module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf,
+                               sizeof(error_buf));
+    ASSERT_TRUE(module != NULL);
+
+    module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf,
+                                           sizeof(error_buf));
+    ASSERT_TRUE(module_inst != NULL);
+
+    exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024);
+    ASSERT_TRUE(exec_env != NULL);
+
+    func_inst = wasm_runtime_lookup_function(module_inst, "test2");
+    ASSERT_TRUE(func_inst != NULL);
+
+    argv[0] = 1234;
+    argv[1] = 5678;
+    wasm_runtime_call_wasm(exec_env, func_inst, 2, argv);
+    ASSERT_TRUE(wasm_runtime_get_exception(module_inst));
+
+    frames = AOTStackFrameTest::my_frames;
+    frame_num = AOTStackFrameTest::my_frame_num;
+
+    ASSERT_TRUE(frames != NULL);
+    ASSERT_TRUE(frame_num == 1);
+
+    ASSERT_TRUE(frames[0]->lp[0] == 1234);
+    ASSERT_TRUE(frames[0]->lp[1] == 5678);
+    ASSERT_TRUE(frames[0]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL);
+    ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f);
+    ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322);
+    ASSERT_TRUE(frames[0]->lp[8] == 0x1234);
+    ASSERT_TRUE(frames[0]->lp[9] == 0x5678);
+}
+
+TEST_F(AOTStackFrameTest, test3)
+{
+    MyAOTFrame *frame, **frames;
+    uint32 frame_num;
+
+    aot_set_stack_frame_callback(aot_stack_frame_cb);
+
+    bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot));
+
+    module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf,
+                               sizeof(error_buf));
+    ASSERT_TRUE(module != NULL);
+
+    module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf,
+                                           sizeof(error_buf));
+    ASSERT_TRUE(module_inst != NULL);
+
+    exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024);
+    ASSERT_TRUE(exec_env != NULL);
+
+    func_inst = wasm_runtime_lookup_function(module_inst, "test3");
+    ASSERT_TRUE(func_inst != NULL);
+
+    argv[0] = 1234;
+    argv[1] = 5678;
+    wasm_runtime_call_wasm(exec_env, func_inst, 2, argv);
+    ASSERT_TRUE(wasm_runtime_get_exception(module_inst));
+
+    frames = AOTStackFrameTest::my_frames;
+    frame_num = AOTStackFrameTest::my_frame_num;
+
+    ASSERT_TRUE(frames != NULL);
+    ASSERT_TRUE(frame_num == 2);
+
+    ASSERT_TRUE(frames[0]->sp - frames[0]->lp == 5);
+    ASSERT_TRUE(frames[0]->ip_offset == 24);
+
+    ASSERT_TRUE(frames[0]->lp[0] == 1234);
+    ASSERT_TRUE(frames[0]->lp[1] == 5678);
+    ASSERT_TRUE(frames[0]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL);
+
+    ASSERT_TRUE(frames[1]->lp[0] == 0x1234);
+    ASSERT_TRUE(frames[1]->lp[1] == 0x5678);
+    ASSERT_TRUE(frames[1]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[1]->lp + 3) == 0x12345678ABCDEF99LL);
+    ASSERT_TRUE(*(float *)(frames[1]->lp + 5) == 5566.7788f);
+    ASSERT_TRUE(*(double *)(frames[1]->lp + 6) == 99887766.55443322);
+}

+ 27 - 0
tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt

@@ -0,0 +1,27 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project(wasm-apps-aot-stack-frame)
+
+add_custom_target(aot-stack-frame-test-wasm ALL
+    COMMAND cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc
+                  -S ${WAMR_ROOT_DIR}/wamr-compiler
+            && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc
+            && /opt/wabt/bin/wat2wasm
+                  -o ${CMAKE_CURRENT_BINARY_DIR}/test.wasm
+                  ${CMAKE_CURRENT_LIST_DIR}/test.wast
+            && ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc/wamrc
+                  --enable-dump-call-stack --bounds-checks=1
+                  -o ${CMAKE_CURRENT_BINARY_DIR}/test.aot
+                  ${CMAKE_CURRENT_BINARY_DIR}/test.wasm
+            && cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump
+                  -S ${WAMR_ROOT_DIR}/test-tools/binarydump-tool
+            && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump
+            && ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump/binarydump
+                  -o ${CMAKE_CURRENT_LIST_DIR}/test_aot.h -n test_aot
+                  ${CMAKE_CURRENT_BINARY_DIR}/test.aot
+
+)
+

+ 36 - 0
tests/unit/aot-stack-frame/wasm-apps/test.wast

@@ -0,0 +1,36 @@
+(module
+  (func $test1 (export "test1") (param i32 i32) (result i32)
+    i32.const 0x11223344
+    i64.const 0x1234_5678_ABCD_EF99
+    f32.const 5566.7788
+    f64.const 99887766.55443322
+    unreachable
+  )
+
+  (func $test2 (export "test2") (param f32 f32) (result i32)
+    i32.const 0x11223344
+    i64.const 0x1234_5678_ABCD_EF99
+    f32.const 5566.7788
+    f64.const 99887766.55443322
+
+    loop
+      i32.const 0x1234
+      i32.const 0x5678
+      unreachable
+    end
+
+    unreachable
+  )
+
+  (func $test3 (export "test3") (param i32 i32) (result i32)
+    i32.const 0x11223344
+    i64.const 0x1234_5678_ABCD_EF99
+
+    i32.const 0x1234
+    i32.const 0x5678
+    call $test1
+
+    drop
+    drop
+  )
+)

+ 59 - 0
tests/unit/aot/CMakeLists.txt

@@ -0,0 +1,59 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-aot)
+
+add_definitions (-DRUN_ON_LINUX)
+
+add_definitions (-Dattr_container_malloc=malloc)
+add_definitions (-Dattr_container_free=free)
+add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1)
+add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 1)
+
+include (../unit_common.cmake)
+
+set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
+if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
+  message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
+endif ()
+set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
+find_package(LLVM REQUIRED CONFIG)
+include_directories(${LLVM_INCLUDE_DIRS})
+add_definitions(${LLVM_DEFINITIONS})
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+
+include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${LIBC_BUILTIN_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${IWASM_COMPL_SOURCE}
+    )
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (aot_test ${unit_test_sources})
+
+target_link_libraries (aot_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+gtest_discover_tests(aot_test)
+

+ 1190 - 0
tests/unit/aot/aot_test.cc

@@ -0,0 +1,1190 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <limits.h>
+#include "gtest/gtest.h"
+#include "wasm_export.h"
+#include "bh_platform.h"
+#include "aot_llvm.h"
+#include "aot_intrinsic.h"
+#include "aot.h"
+
+#define G_INTRINSIC_COUNT (50u)
+#define CONS(num) ("f##num##.const")
+
+const char *llvm_intrinsic_tmp[G_INTRINSIC_COUNT] = {
+    "llvm.experimental.constrained.fadd.f32",
+    "llvm.experimental.constrained.fadd.f64",
+    "llvm.experimental.constrained.fsub.f32",
+    "llvm.experimental.constrained.fsub.f64",
+    "llvm.experimental.constrained.fmul.f32",
+    "llvm.experimental.constrained.fmul.f64",
+    "llvm.experimental.constrained.fdiv.f32",
+    "llvm.experimental.constrained.fdiv.f64",
+    "llvm.fabs.f32",
+    "llvm.fabs.f64",
+    "llvm.ceil.f32",
+    "llvm.ceil.f64",
+    "llvm.floor.f32",
+    "llvm.floor.f64",
+    "llvm.trunc.f32",
+    "llvm.trunc.f64",
+    "llvm.rint.f32",
+    "llvm.rint.f64",
+    "llvm.sqrt.f32",
+    "llvm.sqrt.f64",
+    "llvm.copysign.f32",
+    "llvm.copysign.f64",
+    "llvm.minnum.f32",
+    "llvm.minnum.f64",
+    "llvm.maxnum.f32",
+    "llvm.maxnum.f64",
+    "llvm.ctlz.i32",
+    "llvm.ctlz.i64",
+    "llvm.cttz.i32",
+    "llvm.cttz.i64",
+    "llvm.ctpop.i32",
+    "llvm.ctpop.i64",
+    "f64_convert_i32_s",
+    "f64_convert_i32_u",
+    "f32_convert_i32_s",
+    "f32_convert_i32_u",
+    "f64_convert_i64_s",
+    "f64_convert_i64_u",
+    "f32_convert_i64_s",
+    "f32_convert_i64_u",
+    "i32_trunc_f32_u",
+    "i32_trunc_f32_s",
+    "i32_trunc_f64_u",
+    "i32_trunc_f64_s",
+    "f32_demote_f64",
+    "f64_promote_f32",
+    "f32_cmp",
+    "f64_cmp",
+    "f32.const",
+    "f64.const",
+};
+
+uint64 g_intrinsic_flag[G_INTRINSIC_COUNT] = {
+    AOT_INTRINSIC_FLAG_F32_FADD,     AOT_INTRINSIC_FLAG_F64_FADD,
+    AOT_INTRINSIC_FLAG_F32_FSUB,     AOT_INTRINSIC_FLAG_F64_FSUB,
+    AOT_INTRINSIC_FLAG_F32_FMUL,     AOT_INTRINSIC_FLAG_F64_FMUL,
+    AOT_INTRINSIC_FLAG_F32_FDIV,     AOT_INTRINSIC_FLAG_F64_FDIV,
+    AOT_INTRINSIC_FLAG_F32_FABS,     AOT_INTRINSIC_FLAG_F64_FABS,
+    AOT_INTRINSIC_FLAG_F32_CEIL,     AOT_INTRINSIC_FLAG_F64_CEIL,
+    AOT_INTRINSIC_FLAG_F32_FLOOR,    AOT_INTRINSIC_FLAG_F64_FLOOR,
+    AOT_INTRINSIC_FLAG_F32_TRUNC,    AOT_INTRINSIC_FLAG_F64_TRUNC,
+    AOT_INTRINSIC_FLAG_F32_RINT,     AOT_INTRINSIC_FLAG_F64_RINT,
+    AOT_INTRINSIC_FLAG_F32_SQRT,     AOT_INTRINSIC_FLAG_F64_SQRT,
+    AOT_INTRINSIC_FLAG_F32_COPYSIGN, AOT_INTRINSIC_FLAG_F64_COPYSIGN,
+    AOT_INTRINSIC_FLAG_F32_MIN,      AOT_INTRINSIC_FLAG_F64_MIN,
+    AOT_INTRINSIC_FLAG_F32_MAX,      AOT_INTRINSIC_FLAG_F64_MAX,
+    AOT_INTRINSIC_FLAG_I32_CLZ,      AOT_INTRINSIC_FLAG_I64_CLZ,
+    AOT_INTRINSIC_FLAG_I32_CTZ,      AOT_INTRINSIC_FLAG_I64_CTZ,
+    AOT_INTRINSIC_FLAG_I32_POPCNT,   AOT_INTRINSIC_FLAG_I64_POPCNT,
+    AOT_INTRINSIC_FLAG_I32_TO_F64,   AOT_INTRINSIC_FLAG_U32_TO_F64,
+    AOT_INTRINSIC_FLAG_I32_TO_F32,   AOT_INTRINSIC_FLAG_U32_TO_F32,
+    AOT_INTRINSIC_FLAG_I32_TO_F64,   AOT_INTRINSIC_FLAG_U64_TO_F64,
+    AOT_INTRINSIC_FLAG_I64_TO_F32,   AOT_INTRINSIC_FLAG_U64_TO_F32,
+    AOT_INTRINSIC_FLAG_F32_TO_U32,   AOT_INTRINSIC_FLAG_F32_TO_I32,
+    AOT_INTRINSIC_FLAG_F64_TO_U32,   AOT_INTRINSIC_FLAG_F64_TO_I32,
+    AOT_INTRINSIC_FLAG_F64_TO_F32,   AOT_INTRINSIC_FLAG_F32_TO_F64,
+    AOT_INTRINSIC_FLAG_F32_CMP,      AOT_INTRINSIC_FLAG_F64_CMP,
+    AOT_INTRINSIC_FLAG_F32_CONST,    AOT_INTRINSIC_FLAG_F64_CONST,
+};
+
+// To use a test fixture, derive a class from testing::Test.
+class AOTTest : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() { wasm_runtime_destroy(); }
+
+  public:
+    char global_heap_buf[512 * 1024];
+    RuntimeInitArgs init_args;
+};
+
+TEST_F(AOTTest, aot_value_stack_push_pop)
+{
+    AOTValueStack *stack;
+    AOTValue *value1, *value2, *value3;
+    AOTCompContext comp_ctx = { 0 };
+
+    stack = (AOTValueStack *)wasm_runtime_malloc(sizeof(AOTValueStack));
+    EXPECT_TRUE(stack != NULL);
+
+    memset(stack, 0, sizeof(AOTValueStack));
+
+    value1 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue));
+    EXPECT_TRUE(value1 != NULL);
+
+    memset(value1, 0, sizeof(AOTValue));
+    value1->type = VALUE_TYPE_I32;
+
+    aot_value_stack_push(&comp_ctx, stack, value1);
+    EXPECT_EQ(stack->value_list_head, value1);
+    EXPECT_EQ(stack->value_list_end, value1);
+
+    value2 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue));
+    EXPECT_TRUE(value2 != NULL);
+
+    memset(value2, 0, sizeof(AOTValue));
+    value2->type = VALUE_TYPE_I64;
+
+    aot_value_stack_push(&comp_ctx, stack, value2);
+    EXPECT_EQ(stack->value_list_head, value1);
+    EXPECT_EQ(stack->value_list_end, value2);
+    EXPECT_EQ(value2->prev, value1);
+
+    value3 = aot_value_stack_pop(&comp_ctx, stack);
+    EXPECT_EQ(value3, value2);
+    EXPECT_EQ(stack->value_list_head, value1);
+    EXPECT_EQ(stack->value_list_end, value1);
+    EXPECT_TRUE(value3->prev == NULL);
+
+    aot_value_stack_destroy(&comp_ctx, stack);
+    wasm_runtime_free(value3);
+    wasm_runtime_free(stack);
+}
+
+TEST_F(AOTTest, aot_block_stack_push_pop)
+{
+    AOTBlockStack *stack;
+    AOTBlock *block1, *block2, *block3;
+    AOTCompContext comp_ctx = { 0 };
+
+    stack = (AOTBlockStack *)wasm_runtime_malloc(sizeof(AOTBlockStack));
+    EXPECT_TRUE(stack != NULL);
+
+    memset(stack, 0, sizeof(AOTBlockStack));
+
+    block1 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock));
+    EXPECT_TRUE(block1 != NULL);
+
+    memset(block1, 0, sizeof(AOTBlock));
+    block1->label_type = LABEL_TYPE_LOOP;
+
+    aot_block_stack_push(stack, block1);
+    EXPECT_EQ(stack->block_list_head, block1);
+    EXPECT_EQ(stack->block_list_end, block1);
+
+    block2 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock));
+    EXPECT_TRUE(block2 != NULL);
+
+    memset(block2, 0, sizeof(AOTBlock));
+    block2->label_type = LABEL_TYPE_IF;
+
+    aot_block_stack_push(stack, block2);
+    EXPECT_EQ(stack->block_list_head, block1);
+    EXPECT_EQ(stack->block_list_end, block2);
+    EXPECT_EQ(block2->prev, block1);
+
+    block3 = aot_block_stack_pop(stack);
+    EXPECT_EQ(block3, block2);
+    EXPECT_EQ(stack->block_list_head, block1);
+    EXPECT_EQ(stack->block_list_end, block1);
+    EXPECT_TRUE(block3->prev == NULL);
+
+    aot_block_stack_destroy(&comp_ctx, stack);
+    wasm_runtime_free(block3);
+    wasm_runtime_free(stack);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fadd_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fadd_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fsub_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fsub_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmul_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmul_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fdiv_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b));
+
+    a = -1.0;
+    b = 0.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fdiv_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b));
+
+    a = -1.0;
+    b = 0.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fabs_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a));
+
+    a = -1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a));
+
+    a = -1.5;
+    EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fabs_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a));
+
+    a = -1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a));
+
+    a = -1.5;
+    EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_ceil_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), ceilf(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_ceil_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), ceil(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_floor_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), floorf(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_floor_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), floor(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_trunc_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), trunc(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_trunc_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), trunc(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_rint_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), rint(a));
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), 1);
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_rint_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), rint(a));
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), 1);
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_sqrt_f32)
+{
+    float32 a = 2.0;
+    EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a));
+
+    a = 2;
+    EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_sqrt_f64)
+{
+    float64 a = 2.0;
+    EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a));
+
+    a = 2;
+    EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_copysign_f32)
+{
+    float32 a = 20.0;
+    float32 b = 2.0;
+
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a));
+
+    b = 1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a));
+
+    b = -2.0;
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a));
+
+    a = -20.0;
+    b = -1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_copysign_f64)
+{
+    float64 a = 20.0;
+    float64 b = 2.0;
+
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a));
+
+    b = 1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a));
+
+    b = -2.0;
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a));
+
+    a = -20.0;
+    b = -1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmin_f32)
+{
+    float32 a = 1.2;
+    float32 b = 2.5;
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a);
+
+    a = -3;
+    b = -1;
+    EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a);
+
+    b = 1;
+    EXPECT_EQ(aot_intrinsic_fmin_f32('a', b), b);
+
+    a = 3;
+    EXPECT_EQ(aot_intrinsic_fmin_f32(a, 'b'), a);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32('a', 'b'), 'a');
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32('b', 'c'), 'b');
+    EXPECT_EQ(aot_intrinsic_fmin_f32('c', 'b'), 'b');
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32(true, 2.5), 1);
+    EXPECT_EQ(aot_intrinsic_fmin_f32(1.0, false), 0);
+
+    EXPECT_NE(aot_intrinsic_fmin_f32(sqrt(-1), 3), 3);
+    EXPECT_NE(aot_intrinsic_fmin_f32(3, sqrt(-1)), 3);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmin_f64)
+{
+    float64 a = 1.00000000;
+    float64 b = 3.00000000;
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(a, b), a);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(-a, b), -a);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -b), -b);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(a, -b), -b);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(a, a), a);
+
+    a = 0.0000;
+    EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -a), -a);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmax_f32)
+{
+    float32 a = 1.2;
+    float32 b = 2.5;
+
+    EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b);
+
+    a = -3;
+    b = -1;
+    EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b);
+
+    b = 1;
+    EXPECT_EQ(aot_intrinsic_fmax_f32('a', b), 'a');
+
+    a = 3;
+    EXPECT_EQ(aot_intrinsic_fmax_f32(a, 'b'), 'b');
+
+    EXPECT_EQ(aot_intrinsic_fmax_f32('a', 'b'), 'b');
+
+    EXPECT_EQ(aot_intrinsic_fmax_f32(' ', 'b'), 'b');
+    EXPECT_EQ(aot_intrinsic_fmax_f32('a', ' '), 'a');
+
+    EXPECT_NE(aot_intrinsic_fmax_f32(sqrt(-1), 3), 3);
+    EXPECT_NE(aot_intrinsic_fmax_f32(3, sqrt(-1)), 3);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmax_f64)
+{
+    float64 a = 1.00000000;
+    float64 b = 3.00000000;
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(a, b), b);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-a, b), b);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -b), -a);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(a, -b), a);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(a, a), a);
+
+    a = 0.0000;
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -a), -a);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-0, -0), -0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_clz_i32)
+{
+    uint32 type = 0;
+    uint32 data = 0;
+    uint32 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_clz_i32(0), 32);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        /* Generate random numbers [1,0xFFFFFFFF] */
+        type = 1 + (rand() % (0xFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 0x80000000)) {
+            num++;
+            type <<= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_clz_i32(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_clz_i32(0xFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_clz_i64)
+{
+    uint64 type = 0;
+    uint64 data = 0;
+    uint64 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_clz_i64(0), 64);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        /* Generate random numbers [1,0xFFFFFFFFFFFFFFFF] */
+        type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 0x8000000000000000LL)) {
+            num++;
+            type <<= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_clz_i64(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_clz_i64(0xFFFFFFFFFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, ast_intrinsic_ctz_i32)
+{
+    uint32 type = 0;
+    uint32 data = 0;
+    uint32 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_ctz_i32(0), 32);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        type = 1 + (rand() % (0xFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 1)) {
+            num++;
+            type >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_ctz_i32(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_ctz_i32(0xFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, ast_intrinsic_ctz_i64)
+{
+    uint64 type = 0;
+    uint64 data = 0;
+    uint64 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_ctz_i64(0), 64);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 1)) {
+            num++;
+            type >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_ctz_i64(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_ctz_i64(0xFFFFFFFFFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_popcnt_i32)
+{
+    uint32 data = 0;
+    uint32 num = 0;
+    uint32 temp = 0;
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i32(0), 0);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        temp = 1 + (rand() % (0x100000000 - 1 + 1));
+        data = temp;
+
+        while (temp) {
+            if (temp & 0x01)
+                num++;
+            temp >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_popcnt_i32(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i32(0xFFFFFFFF), 32);
+}
+
+TEST_F(AOTTest, aot_intrinsic_popcnt_i64)
+{
+    uint64 data = 0;
+    uint64 num = 0;
+    uint64 temp = 0;
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i64(0x00), 0);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        temp = 1 + (rand() % (0xFFFFFFFFFFFFFFFFLL - 1 + 1));
+        data = temp;
+
+        while (temp) {
+            if (temp & 0x01)
+                num++;
+            temp >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_popcnt_i64(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i64(0xFFFFFFFFFFFFFFFF), 64);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i32_to_f32)
+{
+    int32 idata = 0;
+
+    EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata);
+    }
+
+    idata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u32_to_f32)
+{
+    uint32 udata = 0;
+
+    EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata);
+    }
+
+    udata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i32_to_f64)
+{
+    int32 idata = 0;
+
+    EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata);
+    }
+
+    idata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u32_to_f64)
+{
+    uint32 udata = 0;
+
+    EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata);
+    }
+
+    udata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i64_to_f32)
+{
+    int64 idata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        idata = (int64)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata);
+    }
+
+    idata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u64_to_f32)
+{
+    uint64 udata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        udata = (uint64)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata);
+    }
+
+    udata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i64_to_f64)
+{
+    int64 idata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), float64(idata));
+
+    for (uint32_t i = 0; i < 0xFFFFF; i++) {
+        idata = (int64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata);
+    }
+
+    idata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u64_to_f64)
+{
+    uint64 udata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), float64(udata));
+
+    for (uint32_t i = 0; i < 0xFFFFF; i++) {
+        udata = (uint64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata);
+    }
+
+    udata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_i32)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (100 - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_u32)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_i64)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_u64)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_i32)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_u32)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_i64)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_u64)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_f64)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_f32)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_f32(data), (float32)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.06);
+        EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_cmp)
+{
+    float32 lhs = 0.0;
+    float32 rhs = 0.0;
+    AOTFloatCond index = FLOAT_EQ;
+    uint32 res = 0;
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1)));
+        lhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        rhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+
+        /* cond : 0 */
+        EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_EQ, lhs, rhs),
+                  lhs == rhs ? 1 : 0);
+
+        /* cond : 1-6 */
+        switch (index) {
+            case FLOAT_LT: // 2
+                res = (lhs < rhs ? 1 : 0);
+                break;
+            case FLOAT_GT: // 3
+                res = (lhs > rhs ? 1 : 0);
+                break;
+            case FLOAT_LE: // 4
+                res = (lhs <= rhs ? 1 : 0);
+                break;
+            case FLOAT_GE: // 5
+                res = (lhs >= rhs ? 1 : 0);
+                break;
+            case FLOAT_NE: // 1
+                res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
+                break;
+            case FLOAT_UNO: // 6
+                res = (isnan(lhs) || isnan(rhs)) ? 1 : 0;
+                break;
+
+            default:
+                break;
+        }
+
+        EXPECT_EQ(aot_intrinsic_f32_cmp(index, lhs, rhs), res);
+        index = FLOAT_EQ;
+
+        /* cond : > 6 */
+        EXPECT_EQ(aot_intrinsic_f32_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0);
+    }
+
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, false), 1);
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, false), 0);
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, 'a', 'b'), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_cmp)
+{
+    float64 lhs = 0.0;
+    float64 rhs = 0.0;
+    AOTFloatCond index = FLOAT_EQ;
+    uint32 res = 0;
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1)));
+        lhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05);
+        rhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05);
+
+        /* cond : 0 */
+        EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_EQ, lhs, rhs),
+                  lhs == rhs ? 1 : 0);
+
+        /* cond : 1-6 */
+        switch (index) {
+            case FLOAT_LT: // 2
+                res = (lhs < rhs ? 1 : 0);
+                break;
+            case FLOAT_GT: // 3
+                res = (lhs > rhs ? 1 : 0);
+                break;
+            case FLOAT_LE: // 4
+                res = (lhs <= rhs ? 1 : 0);
+                break;
+            case FLOAT_GE: // 5
+                res = (lhs >= rhs ? 1 : 0);
+                break;
+            case FLOAT_NE: // 1
+                res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
+                break;
+            case FLOAT_UNO: // 6
+                res = (isnan(lhs) || isnan(rhs)) ? 1 : 0;
+                break;
+
+            default:
+                break;
+        }
+
+        EXPECT_EQ(aot_intrinsic_f64_cmp(index, lhs, rhs), res);
+        index = FLOAT_EQ;
+
+        /* cond : > 6 */
+        EXPECT_EQ(aot_intrinsic_f64_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0);
+    }
+
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, false), 1);
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, false), 0);
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, 'a', 'b'), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_get_symbol)
+{
+    const char *llvm_intrinsic_t = NULL;
+
+    for (int i = 0; i < 2; i++) {
+        if (i == 0)
+            llvm_intrinsic_t = CONS(32);
+        else
+            llvm_intrinsic_t = CONS(64);
+
+        EXPECT_EQ((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_t),
+                  (const char *)NULL);
+    }
+
+    for (int i = 0; i < G_INTRINSIC_COUNT - 2; i++) {
+        EXPECT_NE((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_tmp[i]),
+                  (const char *)NULL);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_check_capability)
+{
+    AOTCompContext *comp_ctx = NULL;
+    AOTCompContext scomp_ctx = { 0 };
+    const char *llvm_intrinsic_t = "f64_cmp";
+    bool res = false;
+    uint64 flag = 0;
+    uint64 group = 0;
+
+    comp_ctx = &scomp_ctx;
+    memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags));
+
+    /*
+        EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, (const char
+       *)NULL)); EXPECT_FALSE(aot_intrinsic_check_capability((const
+       AOTCompContext *)NULL, llvm_intrinsic_t));
+    */
+
+    EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t));
+    for (int i = 0; i < G_INTRINSIC_COUNT; i++) {
+        EXPECT_FALSE(
+            aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i]));
+    }
+
+    memset(comp_ctx->flags, 1, sizeof(comp_ctx->flags));
+    EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t));
+    for (int i = 0; i < G_INTRINSIC_COUNT; i++) {
+        flag = g_intrinsic_flag[i];
+        group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
+        flag &= AOT_INTRINSIC_FLAG_MASK;
+
+        res = aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i]);
+        if ((flag & 0x01) || (flag & 0x100) || (flag & 0x10000)
+            || (flag & 0x1000000))
+            EXPECT_TRUE(res);
+        else
+            EXPECT_FALSE(res);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_fill_capability_flags)
+{
+    // AOTCompContext *comp_ctx = NULL;
+    AOTCompContext scomp_ctx = { 0 };
+
+    // comp_ctx = &scomp_ctx;
+    aot_intrinsic_fill_capability_flags(&scomp_ctx);
+
+    AOTCompContext scomp_ctx_1{
+        .target_cpu = (char *)"cortex-m7",
+    };
+    strncpy(scomp_ctx_1.target_arch, "thumb", strlen("thumb"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_1);
+
+    AOTCompContext scomp_ctx_2{
+        .target_cpu = (char *)"cortex-m4",
+    };
+    strncpy(scomp_ctx_2.target_arch, "thumb", strlen("thumb"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_2);
+
+    AOTCompContext scomp_ctx_3{
+        .target_cpu = (char *)"cortex-m4",
+    };
+    strncpy(scomp_ctx_3.target_arch, "riscv", strlen("riscv"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_3);
+
+    AOTCompContext scomp_ctx_4{
+        .target_cpu = (char *)"cortex-m4",
+    };
+    strncpy(scomp_ctx_4.target_arch, "intrinsic", strlen("intrinsic"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_4);
+}

+ 89 - 0
tests/unit/common/mock_allocator.h

@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#pragma once
+
+#include "wasm_export.h"
+#include <functional>
+
+template<int MaxAllocCount>
+class MockAllocator
+{
+  private:
+    RuntimeInitArgs init_args;
+
+  public:
+    MockAllocator()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Allocator;
+        init_args.mem_alloc_option.allocator.malloc_func = (void *)my_malloc;
+        init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc;
+        init_args.mem_alloc_option.allocator.free_func = (void *)free;
+
+        /* Set count to INT32_MIN so the initialization will not fail */
+        alloc_count = INT32_MIN;
+
+        wasm_runtime_full_init(&init_args);
+        reset_count();
+    }
+
+    ~MockAllocator() { wasm_runtime_destroy(); }
+
+    void reset_count() { alloc_count = 0; }
+
+  protected:
+    static int32_t alloc_count;
+    static void *my_malloc(int32_t size)
+    {
+        if (alloc_count >= MaxAllocCount) {
+            return nullptr;
+        }
+
+        alloc_count++;
+
+        return malloc(size);
+    }
+};
+
+template<int MaxAllocCount>
+int32_t MockAllocator<MaxAllocCount>::alloc_count = 0;
+
+class DumpAllocUsage : public MockAllocator<INT32_MAX>
+{
+  public:
+    DumpAllocUsage()
+      : MockAllocator<INT32_MAX>()
+    {}
+
+    ~DumpAllocUsage()
+    {
+        std::cout << "Alloc usage count: " << alloc_count << std::endl;
+    }
+};
+
+template<int AllocRequired>
+void
+LIMIT_MALLOC_COUNT(std::function<void()> func)
+{
+    {
+        MockAllocator<AllocRequired> allocator;
+        func();
+    }
+
+    if (AllocRequired > 1)
+        LIMIT_MALLOC_COUNT<AllocRequired - 1>(func);
+}
+
+template<>
+void
+LIMIT_MALLOC_COUNT<0>(std::function<void()> func)
+{
+    {
+        MockAllocator<0> allocator;
+        func();
+    }
+}

+ 325 - 0
tests/unit/common/test_helper.h

@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#pragma once
+
+#include "wasm_export.h"
+#include "gtest/gtest.h"
+
+#include <iostream>
+#include <memory>
+#include <fstream>
+
+template<int Size = 512 * 1024>
+class WAMRRuntimeRAII
+{
+  private:
+    char global_heap_buf[Size];
+    RuntimeInitArgs init_args;
+
+  public:
+    WAMRRuntimeRAII()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        wasm_runtime_full_init(&init_args);
+    }
+
+    ~WAMRRuntimeRAII() { wasm_runtime_destroy(); }
+};
+
+class WAMRModule
+{
+  private:
+    wasm_module_t module_;
+
+  public:
+    WAMRModule(uint8_t *buffer, uint32_t size)
+    {
+        module_ = wasm_runtime_load(buffer, size, NULL, 0);
+    }
+
+    ~WAMRModule() { wasm_runtime_unload(module_); }
+
+    wasm_module_t get() const { return module_; }
+};
+
+class WAMRInstance
+{
+  private:
+    wasm_module_inst_t module_inst_;
+
+  public:
+    WAMRInstance(WAMRModule &module, uint32_t stack_size = 8192,
+                 uint32_t heap_size = 8192)
+    {
+        module_inst_ = wasm_runtime_instantiate(module.get(), stack_size,
+                                                heap_size, NULL, 0);
+    }
+
+    ~WAMRInstance() { wasm_runtime_deinstantiate(module_inst_); }
+
+    wasm_module_inst_t get() const { return module_inst_; }
+};
+
+class WAMRExecEnv
+{
+  private:
+    wasm_exec_env_t exec_env_;
+
+  public:
+    WAMRExecEnv(WAMRInstance &instance, uint32_t stack_size = 8192)
+    {
+        exec_env_ = wasm_runtime_create_exec_env(instance.get(), stack_size);
+    }
+
+    ~WAMRExecEnv() { wasm_runtime_destroy_exec_env(exec_env_); }
+
+    wasm_exec_env_t get() const { return exec_env_; }
+    wasm_module_inst_t get_inst() const
+    {
+        return wasm_runtime_get_module_inst(exec_env_);
+    }
+};
+
+static uint8_t dummy_wasm_buffer[] = {
+    0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00,
+    0x02, 0x06, 0x08, 0x01, 0x7F, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0B, 0x07,
+    0x0A, 0x01, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x00,
+    0x19, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x07, 0x12, 0x01, 0x00, 0x0F, 0x5F,
+    0x5F, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74,
+    0x65, 0x72, 0x00, 0x76, 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65,
+    0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65,
+    0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56,
+    0x31, 0x33, 0x2E, 0x30, 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
+    0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
+    0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D,
+    0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x66, 0x64, 0x31,
+    0x64, 0x38, 0x63, 0x32, 0x66, 0x30, 0x34, 0x64, 0x64, 0x65, 0x32, 0x33,
+    0x62, 0x65, 0x65, 0x30, 0x66, 0x62, 0x33, 0x61, 0x37, 0x64, 0x30, 0x36,
+    0x39, 0x61, 0x39, 0x62, 0x31, 0x30, 0x34, 0x36, 0x64, 0x61, 0x39, 0x37,
+    0x39, 0x29
+};
+
+class DummyExecEnv
+{
+  private:
+    std::shared_ptr<WAMRExecEnv> dummy_exec_env_;
+    std::shared_ptr<WAMRInstance> inst_;
+    std::shared_ptr<WAMRModule> mod_;
+    std::vector<uint8_t> my_wasm_buffer;
+
+  private:
+    void construct(uint8_t *buf, uint32_t len)
+    {
+        std::vector<uint8_t> buffer(buf, buf + len);
+        my_wasm_buffer = buffer;
+
+        mod_ = std::make_shared<WAMRModule>(my_wasm_buffer.data(),
+                                            my_wasm_buffer.size());
+        EXPECT_NE(mod_.get(), nullptr);
+        inst_ = std::make_shared<WAMRInstance>(*mod_);
+        EXPECT_NE(inst_.get(), nullptr);
+        dummy_exec_env_ = std::make_shared<WAMRExecEnv>(*inst_);
+        EXPECT_NE(dummy_exec_env_.get(), nullptr);
+    }
+
+  public:
+    DummyExecEnv() { construct(dummy_wasm_buffer, sizeof(dummy_wasm_buffer)); }
+
+    DummyExecEnv(uint8_t *buf, uint32_t len) { construct(buf, len); }
+
+    DummyExecEnv(std::string filename)
+    {
+        std::ifstream wasm_file(filename, std::ios::binary);
+        std::vector<uint8_t> buffer(std::istreambuf_iterator<char>(wasm_file),
+                                    {});
+
+        construct(buffer.data(), buffer.size());
+    }
+
+    ~DummyExecEnv() {}
+
+    wasm_exec_env_t get() const { return dummy_exec_env_->get(); }
+
+    void *app_to_native(uint32_t app_addr) const
+    {
+        return wasm_runtime_addr_app_to_native(inst_->get(), app_addr);
+    }
+
+    uint32_t native_to_app(void *ptr) const
+    {
+        return wasm_runtime_addr_native_to_app(inst_->get(), ptr);
+    }
+
+    const char *get_exception() const
+    {
+        return wasm_runtime_get_exception(inst_->get());
+    }
+
+    void set_exception(std::string str) const
+    {
+        wasm_runtime_set_exception(inst_->get(), str.c_str());
+    }
+
+    void clear_exception() const { wasm_runtime_clear_exception(inst_->get()); }
+
+    bool execute(const char *func_name, uint32_t argc, uint32_t argv[])
+    {
+        wasm_function_inst_t func;
+
+        if (!(func = wasm_runtime_lookup_function(inst_->get(), func_name))) {
+            return false;
+        }
+
+        return wasm_runtime_call_wasm(dummy_exec_env_->get(), func, argc, argv);
+    }
+};
+
+class WAMRVaList
+{
+  private:
+    void *buffer_;
+    uint32_t current_loc_;
+    uint32_t capacity_;
+    wasm_exec_env_t exec_env_;
+
+    void _append(void *ptr, uint32_t size)
+    {
+        if (current_loc_ + size >= capacity_) {
+            capacity_ *= 2;
+            buffer_ = realloc(buffer_, capacity_);
+            ASSERT_NE(buffer_, nullptr);
+        }
+
+        memcpy((void *)((uintptr_t)buffer_ + current_loc_), ptr, size);
+        current_loc_ += size;
+    }
+
+  public:
+    explicit WAMRVaList(wasm_exec_env_t exec_env)
+      : exec_env_(exec_env)
+    {
+        capacity_ = 64;
+        buffer_ = malloc(capacity_);
+        EXPECT_NE(buffer_, nullptr);
+        current_loc_ = 0;
+    }
+
+    ~WAMRVaList()
+    {
+        current_loc_ = 0;
+        free(buffer_);
+    }
+
+    template<typename T>
+    void add(T arg)
+    {
+        if (std::is_floating_point<T>::value) {
+            /* float data should be 8 bytes aligned */
+            current_loc_ = ((current_loc_ + 7) & ~7);
+            _append(&arg, sizeof(T));
+        }
+        else if (std::is_integral<T>::value) {
+            if (sizeof(T) > 4) {
+                current_loc_ = ((current_loc_ + 7) & ~7);
+            }
+            _append(&arg, sizeof(T));
+        }
+    }
+
+    void add(std::string arg)
+    {
+        void *native_addr;
+        auto inst = wasm_runtime_get_module_inst(exec_env_);
+        uint32_t addr =
+            wasm_runtime_module_malloc(inst, arg.size() + 1, &native_addr);
+        ASSERT_NE(addr, 0);
+        memcpy(native_addr, arg.data(), arg.size());
+        *(char *)((uintptr_t)native_addr + arg.size()) = 0;
+        _append(&addr, sizeof(uint32_t));
+    }
+
+    void add(const char *arg) { add(std::string(arg)); }
+
+    char *get() const
+    {
+        auto inst = wasm_runtime_get_module_inst(exec_env_);
+        uint32_t addr = wasm_runtime_module_dup_data(
+            inst, (const char *)buffer_, current_loc_);
+        EXPECT_NE(addr, 0);
+        return (char *)wasm_runtime_addr_app_to_native(inst, addr);
+    }
+};
+
+/* Get memory space in app */
+class AppMemory
+{
+  private:
+    wasm_exec_env_t exec_env_;
+    void *native_addr_;
+    uint32_t app_addr_;
+
+  public:
+    AppMemory(wasm_exec_env_t exec_env, uint32_t size)
+      : exec_env_(exec_env)
+    {
+        app_addr_ = wasm_runtime_module_malloc(get_module_inst(exec_env_), size,
+                                               &native_addr_);
+    }
+
+    ~AppMemory()
+    {
+        wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_);
+    }
+
+    void *get_native_addr() const
+    {
+        return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_),
+                                               app_addr_);
+    }
+    uint32_t get_app_addr() const { return app_addr_; }
+};
+
+/* Put the data to app */
+class AppData
+{
+  private:
+    wasm_exec_env_t exec_env_;
+    void *native_addr_;
+    uint32_t app_addr_;
+
+  public:
+    AppData(wasm_exec_env_t exec_env, void *data, uint32_t size)
+      : exec_env_(exec_env)
+    {
+        app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_),
+                                                 (const char *)data, size);
+    }
+
+    AppData(wasm_exec_env_t exec_env, std::string str)
+      : exec_env_(exec_env)
+    {
+        app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_),
+                                                 (const char *)str.c_str(),
+                                                 str.size() + 1);
+    }
+
+    ~AppData()
+    {
+        wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_);
+    }
+
+    void *get_native_addr() const
+    {
+        return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_),
+                                               app_addr_);
+    }
+    uint32_t get_app_addr() const { return app_addr_; }
+};

+ 72 - 0
tests/unit/compilation/CMakeLists.txt

@@ -0,0 +1,72 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-compilation)
+
+add_definitions (-DRUN_ON_LINUX)
+
+add_definitions (-Dattr_container_malloc=malloc)
+add_definitions (-Dattr_container_free=free)
+add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1)
+add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 0)
+set (WAMR_BUILD_THREAD_MGR 1)
+set (WAMR_BUILD_AOT 1)
+
+include (../unit_common.cmake)
+
+set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
+if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
+  message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
+endif ()
+set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
+find_package(LLVM REQUIRED CONFIG)
+include_directories(${LLVM_INCLUDE_DIRS})
+add_definitions(${LLVM_DEFINITIONS})
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+
+include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${WAMR_RUNTIME_LIB_SOURCE}
+     ${UNCOMMON_SHARED_SOURCE}
+     ${SRC_LIST}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${LIB_HOST_AGENT_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${LIBC_BUILTIN_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${IWASM_COMPL_SOURCE}
+     ${WASM_APP_LIB_SOURCE_ALL}
+    )
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (compilation_test ${unit_test_sources})
+
+target_link_libraries (compilation_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+add_custom_command(TARGET compilation_test POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy
+  ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm
+  ${CMAKE_CURRENT_BINARY_DIR}
+  COMMENT "Copy main.wasm to the directory: build/compilation."
+)
+
+gtest_discover_tests(compilation_test)

+ 203 - 0
tests/unit/compilation/aot_compiler_test.cc

@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "wasm_export.h"
+#include "aot_export.h"
+#include "bh_read_file.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+extern "C" {
+char *
+aot_generate_tempfile_name(const char *prefix, const char *extension,
+                           char *buffer, uint32 len);
+}
+
+class aot_compiler_test_suit : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+void
+test_aot_emit_object_file_with_option(AOTCompOption *option_ptr)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+    aot_comp_data_t comp_data = nullptr;
+    aot_comp_context_t comp_ctx = nullptr;
+    char out_file_name[] = "test.aot";
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data(wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+
+    comp_ctx = aot_create_comp_context(comp_data, option_ptr);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_STREQ(aot_get_last_error(), "");
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    EXPECT_TRUE(aot_emit_object_file(comp_ctx, out_file_name));
+}
+
+TEST_F(aot_compiler_test_suit, aot_emit_object_file)
+{
+    AOTCompOption option = { 0 };
+    uint32_t i = 0;
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    // Test opt_level in range from 0 to 3.
+    for (i = 0; i <= 3; i++) {
+        option.opt_level = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test size_level in range from 0 to 3.
+    option.opt_level = 3;
+    for (i = 0; i <= 3; i++) {
+        option.size_level = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test output_format in range from AOT_FORMAT_FILE to AOT_LLVMIR_OPT_FILE.
+    option.size_level = 3;
+    for (i = AOT_FORMAT_FILE; i <= AOT_LLVMIR_OPT_FILE; i++) {
+        option.output_format = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test bounds_checks in range 0 to 2.
+    option.output_format = AOT_FORMAT_FILE;
+    for (i = 0; i <= 2; i++) {
+        option.bounds_checks = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test all enable option is false.
+    option.bounds_checks = 2;
+    option.enable_simd = false;
+    option.enable_aux_stack_check = false;
+    option.enable_bulk_memory = false;
+    option.enable_ref_types = false;
+    test_aot_emit_object_file_with_option(&option);
+}
+
+TEST_F(aot_compiler_test_suit, aot_emit_llvm_file)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+    aot_comp_data_t comp_data = nullptr;
+    aot_comp_context_t comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data(wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_STREQ(aot_get_last_error(), "");
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    EXPECT_EQ(true, aot_emit_llvm_file(comp_ctx, out_file_name));
+}
+
+TEST_F(aot_compiler_test_suit, aot_generate_tempfile_name)
+{
+    char obj_file_name[64];
+
+    // Test common case.
+    aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name,
+                               sizeof(obj_file_name));
+    EXPECT_NE(nullptr, strstr(obj_file_name, ".o"));
+
+    // Test abnormal cases.
+    EXPECT_EQ(nullptr,
+              aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, 0));
+    char obj_file_name_1[20];
+    EXPECT_EQ(nullptr, aot_generate_tempfile_name(
+                           "wamrc-obj", "12345678901234567890", obj_file_name_1,
+                           sizeof(obj_file_name_1)));
+}

+ 104 - 0
tests/unit/compilation/aot_emit_aot_file_test.cc

@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "wasm_export.h"
+#include "aot_export.h"
+#include "bh_read_file.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+extern "C" {
+uint8 *
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                      uint32 *p_aot_file_size);
+}
+
+class aot_emit_aot_file_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_aot_file_test_suite, aot_emit_aot_file)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+    aot_comp_data_t comp_data = nullptr;
+    aot_comp_context_t comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "test.aot";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = false;
+    option.enable_aux_stack_check = false;
+    option.enable_bulk_memory = false;
+    option.enable_ref_types = false;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data(wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    EXPECT_EQ(false, aot_emit_aot_file(comp_ctx, comp_data, nullptr));
+}

+ 112 - 0
tests/unit/compilation/aot_emit_compare_test.cc

@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "aot_emit_compare.h"
+
+class compilation_aot_emit_compare_test : public testing::Test
+{
+  protected:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+
+  public:
+};
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i32_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    IntCond cond = INT_EQZ;
+    IntCond cond1 = INT_EQZ;
+
+    /* false cond = 0 */
+    EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_i32_compare(&comp_ctx, &func_ctx, (IntCond)(-1)));
+
+    /* false cond = [1:10] || [11:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1)));
+        cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i64_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    IntCond cond = INT_EQZ;
+    IntCond cond1 = INT_EQZ;
+
+    /* false cond = 0 */
+    // EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_i64_compare(&comp_ctx, &func_ctx, (IntCond)(-1)));
+
+    /* false cond = [1:10] || [11:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1)));
+        cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f32_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    FloatCond cond = FLOAT_EQ;
+    FloatCond cond1 = FLOAT_EQ;
+
+    /* false cond = 0 */
+    EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_f32_compare(&comp_ctx, &func_ctx, (FloatCond)(-1)));
+
+    /* false cond = [1:10] || [7:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1)));
+        cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f64_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    FloatCond cond = FLOAT_EQ;
+    FloatCond cond1 = FLOAT_EQ;
+
+    /* false cond = 0 */
+    EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_f64_compare(&comp_ctx, &func_ctx, (FloatCond)(-1)));
+
+    /* false cond = [1:10] || [7:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1)));
+        cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}

+ 196 - 0
tests/unit/compilation/aot_emit_control_test.cc

@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot.h"
+#include "aot_llvm.h"
+#include "aot_emit_control.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_control_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_control_test_suite, check_suspend_flags)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    EXPECT_EQ(true, check_suspend_flags(comp_ctx, func_ctx, false));
+}
+
+TEST_F(aot_emit_control_test_suite, aot_compile_op_block)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    func_ctx->block_stack.block_list_end = nullptr;
+    EXPECT_EQ(false, aot_compile_op_block(comp_ctx, func_ctx, nullptr, nullptr,
+                                          0, 0, nullptr, 0, nullptr));
+}
+
+TEST_F(aot_emit_control_test_suite, aot_compile_op_else)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    func_ctx->block_stack.block_list_end = nullptr;
+    EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr));
+
+    AOTBlock block_list_end_test;
+    block_list_end_test.label_type = LABEL_TYPE_FUNCTION;
+    func_ctx->block_stack.block_list_end = &block_list_end_test;
+    EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr));
+
+    block_list_end_test.label_type = LABEL_TYPE_IF;
+    block_list_end_test.llvm_else_block = nullptr;
+    EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr));
+}

+ 101 - 0
tests/unit/compilation/aot_emit_function_test.cc

@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_emit_control.h"
+#include "aot_emit_function.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_function_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_function_test_suite, aot_compile_op_call)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    EXPECT_EQ(false, aot_compile_op_call(comp_ctx, func_ctx, 9999, true));
+}

+ 335 - 0
tests/unit/compilation/aot_emit_memory_test.cc

@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include "bh_read_file.h"
+#include "aot_emit_memory.h"
+#include "test_helper.h"
+
+#define DEFAULT_CYCLE_TIMES 0xFFFF
+#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class compilation_aot_emit_memory_test : public testing::Test
+{
+  protected:
+    void SetUp() override
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+        AOTCompOption option = { 0 };
+
+        option.opt_level = 3;
+        option.size_level = 3;
+        option.output_format = AOT_FORMAT_FILE;
+        /* default value, enable or disable depends on the platform */
+        option.bounds_checks = 2;
+        /* default value, enable or disable depends on the platform */
+        option.stack_bounds_checks = 2;
+        option.enable_simd = true;
+        option.enable_aux_stack_check = true;
+        option.enable_bulk_memory = true;
+        option.enable_ref_types = true;
+
+        const char *wasm_file = WASM_FILE;
+        unsigned int wasm_file_size = 0;
+        unsigned char *wasm_file_buf = nullptr;
+        char error_buf[128] = { 0 };
+
+        wasm_file_buf =
+            (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+        EXPECT_NE(wasm_file_buf, nullptr);
+        wasm_module = reinterpret_cast<WASMModule *>(wasm_runtime_load(
+            wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)));
+        EXPECT_NE(wasm_module, nullptr);
+        comp_data = aot_create_comp_data(wasm_module, NULL, false);
+        EXPECT_NE(comp_data, nullptr);
+
+        // properly init compilation and function context, to do that,
+        // use as a dummy module(instead of compile the function in it, simply
+        // test the APIs)
+        comp_ctx = aot_create_comp_context(comp_data, &option);
+        EXPECT_NE(comp_ctx, nullptr);
+        func_ctx = comp_ctx->func_ctxes[0];
+        EXPECT_NE(func_ctx, nullptr);
+    }
+
+    void TearDown() override
+    {
+        aot_destroy_comp_context(comp_ctx);
+        aot_destroy_comp_data(comp_data);
+        wasm_runtime_unload(reinterpret_cast<WASMModuleCommon *>(wasm_module));
+    }
+
+  public:
+    WASMModule *wasm_module = nullptr;
+    AOTCompData *comp_data = nullptr;
+    AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(compilation_aot_emit_memory_test, aot_check_memory_overflow)
+{
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes, false);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_load)
+{
+    uint32 align = 0;
+    uint32 offset = 1024;
+    uint32 bytes = 0;
+    bool sign = false;
+    bool atomic = false;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        bytes = (1 + (rand() % (4 - 1 + 1)));
+        printf("---%d", aot_compile_op_i32_load(comp_ctx, func_ctx, align,
+                                                offset, bytes, sign, atomic));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_load)
+{
+    uint32 align = 0;
+    uint32 offset = 1024;
+    uint32 bytes = 0;
+    bool sign = false;
+    bool atomic = false;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        bytes = (1 + (rand() % (4 - 1 + 1)));
+        sign = !sign;
+        atomic = !atomic;
+        aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, bytes, sign,
+                                atomic);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_load)
+{
+    uint32 align = 10;
+    uint32 offset = 10;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_load)
+{
+    uint32 align = 10;
+    uint32 offset = 10;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+    uint32 bytes = 0;
+    bool atomic = false;
+
+    EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset,
+                                          bytes, atomic));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        bytes = (1 + (rand() % (4 - 1 + 1)));
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        atomic = !atomic;
+
+        EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset,
+                                              bytes, atomic));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+    uint32 bytes = 0;
+    bool atomic = false;
+
+    EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset,
+                                          bytes, atomic));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        bytes = (1 + (rand() % (8 - 1 + 1)));
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        atomic = !atomic;
+
+        EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset,
+                                              bytes, atomic));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+
+    EXPECT_FALSE(aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+
+        EXPECT_FALSE(
+            aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+
+    EXPECT_FALSE(aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+
+        EXPECT_FALSE(
+            aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_size)
+{
+    aot_compile_op_memory_size(comp_ctx, func_ctx);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_grow)
+{
+    aot_compile_op_memory_grow(comp_ctx, func_ctx);
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_init)
+{
+    uint32 seg_index = 0;
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        aot_compile_op_memory_init(comp_ctx, func_ctx, seg_index);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_data_drop)
+{
+    uint32 seg_index = 0;
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        aot_compile_op_data_drop(comp_ctx, func_ctx, seg_index);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_copy)
+{
+    aot_compile_op_memory_copy(comp_ctx, func_ctx);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_fill)
+{
+    aot_compile_op_memory_fill(comp_ctx, func_ctx);
+}
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_rmw)
+{
+    uint8 atomic_op = LLVMAtomicRMWBinOpAdd;
+    uint8 op_type = VALUE_TYPE_I32;
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compile_op_atomic_rmw(comp_ctx, func_ctx, atomic_op, op_type, align,
+                              offset, bytes);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_cmpxchg)
+{
+
+    uint8 op_type = VALUE_TYPE_I32;
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx, op_type, align, offset,
+                                  bytes);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_wait)
+{
+
+    uint8 op_type = VALUE_TYPE_I32;
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compile_op_atomic_wait(comp_ctx, func_ctx, op_type, align, offset,
+                               bytes);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compiler_op_atomic_notify)
+{
+
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compiler_op_atomic_notify(comp_ctx, func_ctx, align, offset, bytes);
+}
+#endif

+ 119 - 0
tests/unit/compilation/aot_emit_numberic_test.cc

@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_emit_numberic.h"
+#include "aot_compiler.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_numberic_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_numberic_test_suite, aot_compile_op_functions)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    EXPECT_EQ(false,
+              aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, FLOAT_SUB));
+    EXPECT_EQ(false, aot_compile_op_f32_copysign(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_f32_math(comp_ctx, func_ctx, FLOAT_NEG));
+    EXPECT_EQ(false,
+              aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_SUB));
+    EXPECT_EQ(false, aot_compile_op_f64_copysign(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_f64_math(comp_ctx, func_ctx, FLOAT_NEG));
+    EXPECT_EQ(false, aot_compile_op_i32_clz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i32_ctz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i32_popcnt(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i32_shift(comp_ctx, func_ctx, INT_SHR_S));
+    EXPECT_EQ(false, aot_compile_op_i64_arithmetic(comp_ctx, func_ctx, INT_SUB,
+                                                   nullptr));
+    EXPECT_EQ(false, aot_compile_op_i64_bitwise(comp_ctx, func_ctx, INT_OR));
+    EXPECT_EQ(false, aot_compile_op_i64_clz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i64_ctz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i64_popcnt(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i64_shift(comp_ctx, func_ctx, INT_SHR_S));
+}

+ 143 - 0
tests/unit/compilation/aot_emit_parametric_test.cc

@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_emit_parametric.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_parametric_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_parametric_test_suite, aot_compile_op_select)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, true));
+    EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, false));
+}
+
+TEST_F(aot_emit_parametric_test_suite, aot_compile_op_drop)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+    func_ctx->block_stack.block_list_end = nullptr;
+
+    EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, true));
+    EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, false));
+}

+ 105 - 0
tests/unit/compilation/aot_emit_table_test.cc

@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_emit_table.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_table_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_table_test_suite, get_tbl_inst_offset)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6));
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 1));
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 0));
+    ((AOTCompData *)comp_ctx->comp_data)->import_table_count = 1;
+    AOTImportTable import_tables_test;
+    ((AOTCompData *)comp_ctx->comp_data)->import_tables = &import_tables_test;
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6));
+}

+ 97 - 0
tests/unit/compilation/aot_emit_variable_test.cc

@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "aot_emit_variable.h"
+
+#define DEFAULT_CYCLE_TIMES 0xFFFF
+#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF
+
+class compilation_aot_emit_variable_test : public testing::Test
+{
+  protected:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+
+  public:
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+};
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_local)
+{
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 local_idx = 0;
+
+    // aot_compile_op_get_local(NULL, pfunc_ctx, local_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_get_local(pcomp_ctx, pfunc_ctx, local_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_local)
+{
+
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 local_idx = 0;
+
+    // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_tee_local)
+{
+
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 local_idx = 0;
+
+    // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_global)
+{
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 global_idx = 0;
+
+    // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_global)
+{
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 global_idx = 0;
+    bool is_aux_stack = false;
+
+    // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, global_idx,
+    // is_aux_stack);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     is_aux_stack = is_aux_stack ? false : ture;
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_set_global(pcomp_ctx, pfunc_ctx,
+    //     global_idx,is_aux_stack);
+    // }
+}

+ 305 - 0
tests/unit/compilation/aot_llvm_test.cc

@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_compiler.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_llvm_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_llvm_test_suite, aot_functions)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    AOTFuncContext *func_ctx = nullptr;
+    WASMValue wasm_value;
+    LLVMTypeRef param_types[1];
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    param_types[0] = F64_TYPE;
+    EXPECT_TRUE(aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64",
+                                        F32_TYPE, param_types, 0));
+
+    /* Test function aot_get_native_symbol_index. */
+    AOTNativeSymbol elem_insert_1;
+    elem_insert_1.index = -1;
+    bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1);
+
+    AOTNativeSymbol elem_insert_2;
+    strcpy(elem_insert_2.symbol, "f64#_test");
+    elem_insert_2.index = -1;
+    bh_list_insert(&comp_ctx->native_symbols, &elem_insert_2);
+    comp_ctx->pointer_size = sizeof(uint32);
+    strcpy(comp_ctx->target_arch, "i386");
+    EXPECT_NE(-1, aot_get_native_symbol_index(comp_ctx, "f64#_test"));
+}
+
+TEST_F(aot_llvm_test_suite, wasm_type_to_llvm_type) {}
+
+TEST_F(aot_llvm_test_suite, aot_build_zero_function_ret)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    AOTFuncContext *func_ctx = nullptr;
+    AOTFuncType func_type;
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = false;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    func_type.result_count = 1;
+    func_type.param_count = 0;
+    func_type.types[func_type.param_count] = VALUE_TYPE_I32;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_I64;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_F32;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_F64;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_V128;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    /* THe current optimization, if not actually use ref_types in wasm module,
+     * it will set to false, so test false condition */
+    func_type.types[func_type.param_count] = VALUE_TYPE_FUNCREF;
+    EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type),
+                 ".*");
+    func_type.types[func_type.param_count] = VALUE_TYPE_EXTERNREF;
+    EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type),
+                 ".*");
+    func_type.types[func_type.param_count] = 0xFF;
+    EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type),
+                 ".*");
+}
+
+TEST_F(aot_llvm_test_suite, aot_destroy_comp_context)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    AOTFuncContext *func_ctx = nullptr;
+    AOTFuncType func_type;
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    AOTNativeSymbol elem_insert_1;
+    elem_insert_1.index = -1;
+    bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1);
+    aot_destroy_comp_context(comp_ctx);
+
+    aot_destroy_comp_context(nullptr);
+}
+
+TEST_F(aot_llvm_test_suite, aot_create_comp_context)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+
+    option.enable_thread_mgr = true;
+    option.enable_tail_call = true;
+    option.is_indirect_mode = true;
+    option.disable_llvm_intrinsics = true;
+    option.disable_llvm_lto = true;
+    option.is_jit_mode = true;
+
+    option.target_arch = (char *)"arm";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    option.output_format = 100;
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+
+    // Test every target_arch.
+    option.is_jit_mode = false;
+    option.target_arch = (char *)"arm";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"armeb";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"thumb";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"thumbeb";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"aarch64";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"aarch64_be";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"help";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+
+    // Test every target_abi.
+    option.target_arch = (char *)"arm";
+    option.target_abi = (char *)"test";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_abi = (char *)"help";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_abi = (char *)"msvc";
+    option.target_arch = (char *)"i386";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+
+    option.cpu_features = (char *)"test";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.is_sgx_platform = true;
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    comp_data->func_count = 0;
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+}

BIN
tests/unit/compilation/wasm-apps/main.wasm


+ 65 - 0
tests/unit/custom-section/CMakeLists.txt

@@ -0,0 +1,65 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-custom-section)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_LIBC_BUILTIN 0)
+set (WAMR_BUILD_JIT 0)
+set (WAMR_BUILD_LAZY_JIT 0)
+set (WAMR_BUILD_AOT 1)
+
+add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1)
+add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+
+# Feature to test
+set (WAMR_BUILD_LOAD_CUSTOM_SECTION 1)
+
+include (../unit_common.cmake)
+
+set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
+if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
+  message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
+endif ()
+set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
+find_package(LLVM REQUIRED CONFIG)
+include_directories(${LLVM_INCLUDE_DIRS})
+add_definitions(${LLVM_DEFINITIONS})
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+
+include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${IWASM_COMPL_SOURCE}
+     ${WASM_APP_LIB_SOURCE_ALL}
+    )
+
+# Automatically build wasm-apps for this test
+add_subdirectory(wasm-apps)
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (custom_section_test ${unit_test_sources})
+
+target_link_libraries (custom_section_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+gtest_discover_tests(custom_section_test)

+ 161 - 0
tests/unit/custom-section/custom_section_test.cc

@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include <fstream>
+#include "test_helper.h"
+#include "aot_export.h"
+
+class CustomSectionTest : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+  public:
+    WAMRRuntimeRAII<1 * 1024 * 1024> runtime;
+};
+
+TEST_F(CustomSectionTest, get_custom_section_from_wasm_module_t)
+{
+    uint32_t length, len_from_aot;
+    const uint8_t *content, *content_from_aot;
+    std::ifstream wasm_file("wasm-apps/app.wasm", std::ios::binary);
+    std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(wasm_file),
+                                      {});
+    {
+        WAMRModule module(buffer.data(), buffer.size());
+        aot_comp_data_t comp_data = NULL;
+        aot_comp_context_t comp_ctx = NULL;
+        std::vector<const char *> sections_to_emit{
+            "name",
+            ".debug_info",
+            ".debug_abbrev",
+            /* skip ".debug_line" section in AoT module */
+            ".debug_str",
+            "producers",
+        };
+
+        AOTCompOption option = { 0 };
+        option.custom_sections = (char **)sections_to_emit.data();
+        option.custom_sections_count = 5;
+
+        {
+            /* Compile an AoT module */
+            comp_data = aot_create_comp_data(module.get(), NULL, false);
+            EXPECT_NE(comp_data, nullptr);
+
+            comp_ctx = aot_create_comp_context(comp_data, &option);
+            EXPECT_NE(comp_ctx, nullptr);
+
+            EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+            EXPECT_TRUE(aot_emit_aot_file(comp_ctx, comp_data, "temp.aot"));
+        }
+
+        std::ifstream aot_file("temp.aot", std::ios::binary);
+        std::vector<unsigned char> aot_buffer(
+            std::istreambuf_iterator<char>(aot_file), {});
+        WAMRModule aot_module(aot_buffer.data(), aot_buffer.size());
+
+        /* name */
+        content =
+            wasm_runtime_get_custom_section(module.get(), "name", &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        /* TODO: aot_emit_name_section don't 
+           EMIT_U32(AOT_CUSTOM_SECTION_RAW);*
+           EMIT_STR("name");
+           but instead
+           EMIT_U32(AOT_CUSTOM_SECTION_NAME);
+           can't use get_custom_section to get it
+        */
+        // content_from_aot = wasm_runtime_get_custom_section(
+        //     aot_module.get(), "name", &len_from_aot);
+        // EXPECT_NE(content_from_aot, nullptr);
+        // EXPECT_EQ(len_from_aot, length);
+        // EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* .debug_info */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_info",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_info", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* .debug_abbrev */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_abbrev",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_abbrev", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* .debug_line */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_line",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_line", &len_from_aot);
+        EXPECT_EQ(content_from_aot, nullptr);
+
+        /* .debug_str */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_str",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_str", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* producers */
+        content =
+            wasm_runtime_get_custom_section(module.get(), "producers", &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), "producers", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* Not exist */
+        content = wasm_runtime_get_custom_section(module.get(), "producers1",
+                                                  &length);
+        EXPECT_EQ(content, nullptr);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), "producers1", &len_from_aot);
+        EXPECT_EQ(content_from_aot, nullptr);
+    }
+}

+ 14 - 0
tests/unit/custom-section/wasm-apps/CMakeLists.txt

@@ -0,0 +1,14 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project(wasm-apps-custom-section)
+
+# Add -g option so there will be debugger related custom sections
+add_custom_target(app.wasm ALL
+    COMMAND /opt/wasi-sdk/bin/clang -g -nostdlib
+            -Wl,--no-entry,--export-all
+            -o ${CMAKE_CURRENT_BINARY_DIR}/app.wasm
+            ${CMAKE_CURRENT_LIST_DIR}/app.c
+)

+ 10 - 0
tests/unit/custom-section/wasm-apps/app.c

@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+int
+main(int argc, char const *argv[])
+{
+    return 0;
+}

+ 51 - 0
tests/unit/gc/CMakeLists.txt

@@ -0,0 +1,51 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-wamr-gc)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_GC 1)
+set (WAMR_BUILD_INTERP 1)
+set (WAMR_BUILD_AOT 0)
+set (WAMR_BUILD_APP_FRAMEWORK 0)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+    ${UNIT_SOURCE}
+    ${WAMR_RUNTIME_LIB_SOURCE}
+    ${UNCOMMON_SHARED_SOURCE}
+    ${SRC_LIST}
+    ${PLATFORM_SHARED_SOURCE}
+    ${UTILS_SHARED_SOURCE}
+    ${MEM_ALLOC_SHARED_SOURCE}
+    ${LIB_HOST_AGENT_SOURCE}
+    ${NATIVE_INTERFACE_SOURCE}
+    ${LIBC_BUILTIN_SOURCE}
+    ${IWASM_COMMON_SOURCE}
+    ${IWASM_INTERP_SOURCE}
+    ${IWASM_AOT_SOURCE}
+    ${IWASM_COMPL_SOURCE}
+    ${WASM_APP_LIB_SOURCE_ALL}
+)
+
+add_executable (gc_test ${unit_test_sources})
+target_link_libraries (gc_test gtest_main)
+
+add_custom_command(TARGET gc_test POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy
+  ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/*.was*
+  ${CMAKE_CURRENT_BINARY_DIR}
+  COMMENT "Copy wasm files to directory ${CMAKE_CURRENT_BINARY_DIR}"
+)
+
+#gtest_discover_tests(gc_test)

+ 102 - 0
tests/unit/gc/gc_test.cc

@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include "bh_read_file.h"
+#include "wasm_export.h"
+
+class WasmGCTest : public testing::Test
+{
+  private:
+    std::string get_binary_path()
+    {
+        char cwd[1024] = { 0 };
+
+        if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+            return NULL;
+        }
+
+        char *path_end = strrchr(cwd, '/');
+        if (path_end != NULL) {
+            *path_end = '\0';
+        }
+
+        return std::string(cwd);
+    }
+
+  protected:
+    void SetUp()
+    {
+        CWD = get_binary_path();
+
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
+
+        cleanup = true;
+    }
+
+    void TearDown()
+    {
+        if (cleanup) {
+            wasm_runtime_destroy();
+        }
+    }
+
+  public:
+    bool load_wasm_file(const char *wasm_file)
+    {
+        const char *file;
+        unsigned char *wasm_file_buf;
+        uint32 wasm_file_size;
+
+        file = strdup((CWD + "/" + wasm_file).c_str());
+
+        wasm_file_buf =
+            (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size);
+        if (!wasm_file_buf)
+            return false;
+
+        module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                   sizeof(error_buf));
+        if (!module)
+            return false;
+
+        return true;
+    }
+
+  public:
+    std::string CWD;
+    RuntimeInitArgs init_args;
+    wasm_module_t module = NULL;
+    wasm_module_inst_t module_inst = NULL;
+    wasm_function_inst_t func_inst = NULL;
+    wasm_exec_env_t exec_env = NULL;
+    char error_buf[128];
+    char global_heap_buf[512 * 1024];
+    bool cleanup = true;
+};
+
+TEST_F(WasmGCTest, Test_app1)
+{
+    ASSERT_TRUE(load_wasm_file("test1.wasm"));
+    ASSERT_TRUE(load_wasm_file("test2.wasm"));
+    ASSERT_TRUE(load_wasm_file("test3.wasm"));
+    ASSERT_TRUE(load_wasm_file("test4.wasm"));
+    ASSERT_TRUE(load_wasm_file("test5.wasm"));
+    ASSERT_TRUE(load_wasm_file("test6.wasm"));
+
+    ASSERT_TRUE(load_wasm_file("struct1.wasm"));
+    ASSERT_TRUE(load_wasm_file("struct2.wasm"));
+    ASSERT_TRUE(load_wasm_file("struct3.wasm"));
+
+    ASSERT_TRUE(load_wasm_file("func1.wasm"));
+    ASSERT_TRUE(load_wasm_file("func2.wasm"));
+}

BIN
tests/unit/gc/wasm-apps/func1.wasm


+ 35 - 0
tests/unit/gc/wasm-apps/func1.wast

@@ -0,0 +1,35 @@
+(module
+  (type $t (func))
+
+  (func (export "test") (param structref i31ref)
+    (local funcref)
+    (local funcref)
+    (local funcref)
+    (local externref)
+    (local externref)
+    (local externref)
+    (local anyref)
+    (local eqref)
+    (local structref)
+    (local arrayref)
+    (local i31ref)
+    (local (ref null 0))
+    (local (ref null 0))
+    (local (ref null 0))
+    (local (ref null 1))
+    (local (ref null func))
+    (local (ref null 0))
+    (local (ref null extern))
+    (local (ref null any))
+    (local (ref null eq))
+    (local (ref null i31))
+    (local (ref null struct))
+
+    local.get 0
+    ref.test null array
+    drop
+    local.get 1
+    ref.cast i31
+    drop
+  )
+)

BIN
tests/unit/gc/wasm-apps/func2.wasm


+ 78 - 0
tests/unit/gc/wasm-apps/func2.wast

@@ -0,0 +1,78 @@
+(module
+  (type $t0 (func))
+  (type $t1 (func (param (ref null 1))))
+  (type $t2 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref structref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 1) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 2) (ref null $t0))
+                  (result (ref null func))))
+  (type $t3 (func (param i32 i32) (result (ref null 3))))
+
+  (type $t4 (func))
+  (type $t5 (func (param (ref null 3))))
+  (type $t6 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref structref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 5) (ref null $t0))
+                  (result (ref null func))))
+  (type $t7 (func (param i32 i32) (result (ref null 4))))
+
+  (type $t11 (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null struct)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type $t12 (struct))
+  (type $t13 (struct (field)))
+  (type $t14 (struct (field i8)))
+  (type $t15 (struct (field i8 i8 i8 i8)))
+  (type $t16 (struct (field $x1 i32) (field $y1 i32)))
+  (type $t17 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type $t18 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type $t19 (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  (type $t20 (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref structref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type $t21 (struct))
+  (type $t22 (struct (field)))
+  (type $t23 (struct (field i8)))
+  (type $t24 (struct (field i8 i8 i8 i8)))
+  (type $t25 (struct (field $x3 i32) (field $y3 i32)))
+  (type $t26 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type $t27 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type $t28 (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type $t31 (array i8))
+  (type $t32 (array i16))
+  (type $t33 (array i32))
+  (type $t34 (array i64))
+  (type $t35 (array f32))
+  (type $t36 (array f64))
+  (type $t37 (array anyref))
+  (type $t38 (array (ref i31)))
+  (type $t39 (array (ref 0)))
+  (type $t40 (array (ref null 1)))
+  (type $t43 (array (mut i8)))
+  (type $t44 (array (mut i16)))
+  (type $t45 (array (mut i32)))
+  (type $t46 (array (mut i64)))
+  (type $t47 (array (mut i32)))
+  (type $t48 (array (mut i64)))
+  (type $t49 (array (mut anyref)))
+  (type $t50 (array (mut (ref struct))))
+  (type $t51 (array (mut (ref 0))))
+  (type $t52 (array (mut (ref null i31))))
+)

BIN
tests/unit/gc/wasm-apps/global1.wasm


+ 91 - 0
tests/unit/gc/wasm-apps/global1.wast

@@ -0,0 +1,91 @@
+(module
+  (type $ftype0 (func (param i32)))
+  (type $ftype1 (func (param i32 i64) (result i32)))
+  (type $ftype2 (func (param f32 f64) (result f64)))
+  (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t1 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t2 (func (param i32 i32) (result (ref null 4))))
+
+  ;; Duplicated types
+  (type $t3 (func))
+  (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t5 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t6 (func (param i32 i32) (result (ref null 4))))
+
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  ;; Duplicated types
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x3 i32) (field $y3 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type (array i8))
+  (type (array i16))
+  (type (array i32))
+  (type (array i64))
+  (type (array f32))
+  (type (array f64))
+  (type (array anyref))
+  (type (array (ref array)))
+  (type (array (ref 0)))
+  (type (array (ref null 1)))
+  (type (array (mut i8)))
+  (type (array (mut i16)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut anyref)))
+  (type (array (mut (ref array))))
+  (type (array (mut (ref 0))))
+  (type (array (mut (ref null i31))))
+
+  (global $g0 funcref (ref.func $f0))
+  (global $g1 externref (ref.null extern))
+  (global $g2 anyref (ref.null any))
+  (global $g3 eqref (ref.null array))
+  (global $g4 arrayref (ref.null array))
+  (global $g5 i31ref (ref.null i31))
+
+  (func $f0)
+)

BIN
tests/unit/gc/wasm-apps/struct1.wasm


+ 10 - 0
tests/unit/gc/wasm-apps/struct1.wast

@@ -0,0 +1,10 @@
+(module
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+)

BIN
tests/unit/gc/wasm-apps/struct2.wasm


+ 33 - 0
tests/unit/gc/wasm-apps/struct2.wast

@@ -0,0 +1,33 @@
+(module
+  (type $vec (struct (field f32) (field $y (mut f32)) (field $z f32)))
+
+  ;;(global (ref $vec) (struct.new_canon $vec (f32.const 1) (f32.const 2) (f32.const 3)))
+  (global (ref $vec) (struct.new_canon_default $vec))
+
+  (func (export "new") (result anyref)
+    (struct.new_canon_default $vec)
+  )
+
+  (func $get_0 (param $v (ref $vec)) (result f32)
+    (struct.get $vec 0 (local.get $v))
+  )
+  (func (export "get_0") (result f32)
+    (call $get_0 (struct.new_canon_default $vec))
+  )
+
+  (func $set_get_y (param $v (ref $vec)) (param $y f32) (result f32)
+    (struct.set $vec $y (local.get $v) (local.get $y))
+    (struct.get $vec $y (local.get $v))
+  )
+  (func (export "set_get_y") (param $y f32) (result f32)
+    (call $set_get_y (struct.new_canon_default $vec) (local.get $y))
+  )
+
+  (func $set_get_1 (param $v (ref $vec)) (param $y f32) (result f32)
+    (struct.set $vec 1 (local.get $v) (local.get $y))
+    (struct.get $vec $y (local.get $v))
+  )
+  (func (export "set_get_1") (param $y f32) (result f32)
+    (call $set_get_1 (struct.new_canon_default $vec) (local.get $y))
+  )
+)

BIN
tests/unit/gc/wasm-apps/struct3.wasm


+ 9 - 0
tests/unit/gc/wasm-apps/struct3.wast

@@ -0,0 +1,9 @@
+(module
+  (type $t (struct (field i32 (mut i32))))
+  (func (export "struct.get-null")
+    (local (ref null $t)) (drop (struct.get $t 1 (local.get 0)))
+  )
+  (func (export "struct.set-null")
+    (local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0))
+  )
+)

BIN
tests/unit/gc/wasm-apps/table1.wasm


+ 108 - 0
tests/unit/gc/wasm-apps/table1.wast

@@ -0,0 +1,108 @@
+(module
+  (type $ftype0 (func (param i32)))
+  (type $ftype1 (func (param i32 i64) (result i32)))
+  (type $ftype2 (func (param f32 f64) (result f64)))
+  (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t1 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t2 (func (param i32 i32) (result (ref null 4))))
+
+  ;; Duplicated types
+  (type $t3 (func))
+  (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t5 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t6 (func (param i32 i32) (result (ref null 4))))
+
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  ;; Duplicated types
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x3 i32) (field $y3 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type (array i8))
+  (type (array i16))
+  (type (array i32))
+  (type (array i64))
+  (type (array f32))
+  (type (array f64))
+  (type (array anyref))
+  (type (array (ref array)))
+  (type (array (ref 0)))
+  (type (array (ref null 1)))
+  (type (array (mut i8)))
+  (type (array (mut i16)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut anyref)))
+  (type (array (mut (ref array))))
+  (type (array (mut (ref 0))))
+  (type (array (mut (ref null i31))))
+
+  (table 10 funcref)
+  (table 20 externref)
+  ;; non-defaultable element type
+  ;; (table 30 (ref func))
+  ;; (table 40 (ref extern))
+  (table 50 anyref)
+  (table 60 eqref)
+  (table 100 arrayref)
+  (table 100 i31ref)
+  (table 100 (ref null 0))
+  (table 100 (ref null 2))
+  (table 100 (ref null func))
+  (table 100 (ref null extern))
+  (table 100 (ref null any))
+  (table 100 (ref null eq))
+  (table 100 (ref null i31))
+  (table 100 (ref null array))
+  ;; non-defaultable element type
+  ;; (table 100 (ref 0))
+  ;; (table 100 (ref $t0))
+  ;; (table 100 (ref 3))
+  ;; (table 100 (ref $t0))
+  (table 100 (ref null func))
+  (table 100 (ref null extern))
+  (table 100 (ref null 5))
+  (table 100 (ref null $t0))
+)

BIN
tests/unit/gc/wasm-apps/test1.wasm


+ 117 - 0
tests/unit/gc/wasm-apps/test1.wast

@@ -0,0 +1,117 @@
+(module
+  (type $t (func))
+  (type $t0 (func (param (ref null $t) (ref $t) (ref null 0) (ref 0) (ref null 1) (ref 1))))
+  (type $t1 (func (param funcref externref anyref eqref
+                         i31ref structref arrayref
+                         nullref nullfuncref nullexternref
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref null none) (ref null nofunc) (ref null noextern)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array)
+                         (ref none) (ref nofunc) (ref noextern)
+
+                         (ref null 0) (ref null $t0) (ref null $t1)
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref $t) (ref $t0) (ref $t1)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array))
+                  (result (ref null func) (ref null extern) (ref $t0))))
+  (type $t2 (func (param i32 i32) (result (ref null $t1))))
+
+  ;; Duplicated types
+  (type $t3 (func))
+  (type $t4 (func (param (ref null $t) (ref $t) (ref null 0) (ref 0) (ref null 1) (ref 1))))
+  (type $t5 (func (param funcref externref anyref eqref
+                         i31ref structref arrayref
+                         nullref nullfuncref nullexternref
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref null none) (ref null nofunc) (ref null noextern)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array)
+                         (ref none) (ref nofunc) (ref noextern)
+
+                         (ref null 0) (ref null $t0) (ref null $t1)
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref $t) (ref $t0) (ref $t1)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array))
+                  (result (ref null func) (ref null extern) (ref $t0))))
+  (type $t6 (func (param i32 i32) (result (ref null $t1))))
+
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func) (ref extern)
+                       anyref eqref structref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null struct) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  ;; Duplicated types
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func) (ref extern)
+                       anyref eqref structref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null struct) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x3 i32) (field $y3 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type (array i8))
+  (type (array i16))
+  (type (array i32))
+  (type (array i64))
+  (type (array f32))
+  (type (array f64))
+  (type (array anyref))
+  (type (array (ref struct)))
+  (type (array (ref array)))
+  (type (array (ref null struct)))
+  (type (array (ref null array)))
+  (type (array (ref 0)))
+  (type (array (ref null 1)))
+  (type (array (mut i8)))
+  (type (array (mut i16)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut anyref)))
+  (type (array (mut (ref struct))))
+  (type (array (mut (ref array))))
+  (type (array (mut (ref null struct))))
+  (type (array (mut (ref null array))))
+  (type (array (mut (ref 0))))
+  (type (array (mut (ref null i31))))
+
+  ;; sub types
+  (type $e0 (sub (array i32)))
+  (type $e1 (sub $e0 (array i32)))
+
+  (type $e2 (sub (array anyref)))
+  (type $e3 (sub (array (ref null $e0))))
+  (type $e4 (sub (array (ref $e1))))
+  (type $e5 (sub $e1 (array i32)))
+
+  (type $m1 (sub (array (mut i32))))
+  (type $m2 (sub $m1 (array (mut i32))))
+)

BIN
tests/unit/gc/wasm-apps/test2.wasm


+ 104 - 0
tests/unit/gc/wasm-apps/test2.wast

@@ -0,0 +1,104 @@
+(module
+  (type $ft (func))
+  (type $st (struct))
+  (type $at (array i8))
+
+  (table $ta 10 anyref)
+  (table $tf 10 funcref)
+  (table $te 10 externref)
+
+  (elem declare func $f)
+  (func $f)
+
+  (func (export "init") (param $x externref)
+    (table.set $ta (i32.const 0) (ref.null any))
+    (table.set $ta (i32.const 1) (ref.null struct))
+    (table.set $ta (i32.const 2) (ref.null none))
+    (table.set $ta (i32.const 3) (i31.new (i32.const 7)))
+    (table.set $ta (i32.const 4) (struct.new_canon_default $st))
+    (table.set $ta (i32.const 5) (array.new_canon_default $at (i32.const 0)))
+    (table.set $ta (i32.const 6) (extern.internalize (local.get $x)))
+    (table.set $ta (i32.const 7) (extern.internalize (ref.null extern)))
+
+    (table.set $tf (i32.const 0) (ref.null nofunc))
+    (table.set $tf (i32.const 1) (ref.null func))
+    (table.set $tf (i32.const 2) (ref.func $f))
+
+    (table.set $te (i32.const 0) (ref.null noextern))
+    (table.set $te (i32.const 1) (ref.null extern))
+    (table.set $te (i32.const 2) (local.get $x))
+    (table.set $te (i32.const 3) (extern.externalize (i31.new (i32.const 8))))
+    (table.set $te (i32.const 4) (extern.externalize (struct.new_canon_default $st)))
+    (table.set $te (i32.const 5) (extern.externalize (ref.null any)))
+  )
+
+  (func (export "ref_test_null_data") (param $i i32) (result i32)
+    (i32.add
+      (ref.is_null (table.get $ta (local.get $i)))
+      (ref.test null none (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_any") (param $i i32) (result i32)
+    (i32.add
+      (ref.test any (table.get $ta (local.get $i)))
+      (ref.test null any (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_eq") (param $i i32) (result i32)
+    (i32.add
+      (ref.test eq (table.get $ta (local.get $i)))
+      (ref.test null eq (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_i31") (param $i i32) (result i32)
+    (i32.add
+      (ref.test i31 (table.get $ta (local.get $i)))
+      (ref.test null i31 (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_struct") (param $i i32) (result i32)
+    (i32.add
+      (ref.test struct (table.get $ta (local.get $i)))
+      (ref.test null struct (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_array") (param $i i32) (result i32)
+    (i32.add
+      (ref.test array (table.get $ta (local.get $i)))
+      (ref.test null array (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_null_func") (param $i i32) (result i32)
+    (i32.add
+      (ref.is_null (table.get $tf (local.get $i)))
+      (ref.test null nofunc (table.get $tf (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_func") (param $i i32) (result i32)
+    (i32.add
+      (ref.test func (table.get $tf (local.get $i)))
+      (ref.test null func (table.get $tf (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_null_extern") (param $i i32) (result i32)
+    (i32.add
+      (ref.is_null (table.get $te (local.get $i)))
+      (ref.test null noextern (table.get $te (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_extern") (param $i i32) (result i32)
+    (i32.add
+      (ref.test extern (table.get $te (local.get $i)))
+      (ref.test null extern (table.get $te (local.get $i)))
+    )
+  )
+)

BIN
tests/unit/gc/wasm-apps/test3.wasm


+ 146 - 0
tests/unit/gc/wasm-apps/test3.wast

@@ -0,0 +1,146 @@
+(module
+  (type $t0 (sub (struct)))
+  (type $t1 (sub $t0 (struct (field i32))))
+  (type $t1' (sub $t0 (struct (field i32))))
+  (type $t2 (sub $t1 (struct (field i32 i32))))
+  (type $t2' (sub $t1' (struct (field i32 i32))))
+  (type $t3 (sub $t0 (struct (field i32 i32))))
+  (type $t0' (sub $t0 (struct)))
+  (type $t4 (sub $t0' (struct (field i32 i32))))
+
+  (table 20 (ref null struct))
+
+  (func $init
+    (table.set (i32.const 0) (struct.new_canon_default $t0))
+    (table.set (i32.const 10) (struct.new_canon_default $t0))
+    (table.set (i32.const 1) (struct.new_canon_default $t1))
+    (table.set (i32.const 11) (struct.new_canon_default $t1'))
+    (table.set (i32.const 2) (struct.new_canon_default $t2))
+    (table.set (i32.const 12) (struct.new_canon_default $t2'))
+    (table.set (i32.const 3) (struct.new_canon_default $t3))
+    (table.set (i32.const 4) (struct.new_canon_default $t4))
+  )
+
+  (func (export "test-sub")
+    (call $init)
+    (block $l
+      ;; must hold
+      (br_if $l (i32.eqz (ref.test null $t0 (ref.null struct))))
+      (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t0))))
+      (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t1))))
+      (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t2))))
+      (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t3))))
+      (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t4))))
+      (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 0)))))
+      (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 1)))))
+      (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 2)))))
+      (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 3)))))
+      (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 4)))))
+
+      (br_if $l (i32.eqz (ref.test null $t1 (ref.null struct))))
+      (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t0))))
+      (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t1))))
+      (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t2))))
+      (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t3))))
+      (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t4))))
+      (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 1)))))
+      (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 2)))))
+
+      (br_if $l (i32.eqz (ref.test null $t2 (ref.null struct))))
+      (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t0))))
+      (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t1))))
+      (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t2))))
+      (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t3))))
+      (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t4))))
+      (br_if $l (i32.eqz (ref.test null $t2 (table.get (i32.const 2)))))
+
+      (br_if $l (i32.eqz (ref.test null $t3 (ref.null struct))))
+      (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t0))))
+      (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t1))))
+      (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t2))))
+      (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t3))))
+      (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t4))))
+      (br_if $l (i32.eqz (ref.test null $t3 (table.get (i32.const 3)))))
+
+      (br_if $l (i32.eqz (ref.test null $t4 (ref.null struct))))
+      (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t0))))
+      (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t1))))
+      (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t2))))
+      (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t3))))
+      (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t4))))
+      (br_if $l (i32.eqz (ref.test null $t4 (table.get (i32.const 4)))))
+
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4)))))
+
+      (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 1)))))
+      (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 2)))))
+
+      (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 2)))))
+
+      (br_if $l (i32.eqz (ref.test $t3 (table.get (i32.const 3)))))
+
+      (br_if $l (i32.eqz (ref.test $t4 (table.get (i32.const 4)))))
+
+      ;; must not hold
+      (br_if $l (ref.test $t0 (ref.null struct)))
+      (br_if $l (ref.test $t1 (ref.null struct)))
+      (br_if $l (ref.test $t2 (ref.null struct)))
+      (br_if $l (ref.test $t3 (ref.null struct)))
+      (br_if $l (ref.test $t4 (ref.null struct)))
+
+      (br_if $l (ref.test $t1 (table.get (i32.const 0))))
+      (br_if $l (ref.test $t1 (table.get (i32.const 3))))
+      (br_if $l (ref.test $t1 (table.get (i32.const 4))))
+
+      (br_if $l (ref.test $t2 (table.get (i32.const 0))))
+      (br_if $l (ref.test $t2 (table.get (i32.const 1))))
+      (br_if $l (ref.test $t2 (table.get (i32.const 3))))
+      (br_if $l (ref.test $t2 (table.get (i32.const 4))))
+
+      (br_if $l (ref.test $t3 (table.get (i32.const 0))))
+      (br_if $l (ref.test $t3 (table.get (i32.const 1))))
+      (br_if $l (ref.test $t3 (table.get (i32.const 2))))
+      (br_if $l (ref.test $t3 (table.get (i32.const 4))))
+
+      (br_if $l (ref.test $t4 (table.get (i32.const 0))))
+      (br_if $l (ref.test $t4 (table.get (i32.const 1))))
+      (br_if $l (ref.test $t4 (table.get (i32.const 2))))
+      (br_if $l (ref.test $t4 (table.get (i32.const 3))))
+
+      (return)
+    )
+    (unreachable)
+  )
+
+  (func (export "test-canon")
+    (call $init)
+    (block $l
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4)))))
+
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 10)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 11)))))
+      (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 12)))))
+
+      (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 1)))))
+      (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 2)))))
+
+      (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 11)))))
+      (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 12)))))
+
+      (br_if $l (i32.eqz (ref.test $t2' (table.get (i32.const 2)))))
+
+      (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 12)))))
+
+      (return)
+    )
+    (unreachable)
+  )
+)

BIN
tests/unit/gc/wasm-apps/test4.wasm


+ 46 - 0
tests/unit/gc/wasm-apps/test4.wast

@@ -0,0 +1,46 @@
+(module
+  (type $ft (func))
+  (type $st (struct))
+  (type $at (array i8))
+
+  (table 10 anyref)
+
+  (elem declare func $f)
+  (func $f)
+
+  (func (export "init") (param $x externref)
+    (table.set (i32.const 0) (ref.null any))
+    (table.set (i32.const 1) (i31.new (i32.const 7)))
+    (table.set (i32.const 2) (struct.new_canon_default $st))
+    (table.set (i32.const 3) (array.new_canon_default $at (i32.const 0)))
+    (table.set (i32.const 4) (extern.internalize (local.get $x)))
+    (table.set (i32.const 5) (ref.null i31))
+    (table.set (i32.const 6) (ref.null struct))
+    (table.set (i32.const 7) (ref.null none))
+  )
+
+  (func (export "ref_cast_non_null") (param $i i32)
+    (drop (ref.as_non_null (table.get (local.get $i))))
+    (drop (ref.cast null any (table.get (local.get $i))))
+  )
+  (func (export "ref_cast_null") (param $i i32)
+    (drop (ref.cast null any (table.get (local.get $i))))
+    (drop (ref.cast null struct (table.get (local.get $i))))
+    (drop (ref.cast null array (table.get (local.get $i))))
+    (drop (ref.cast null i31 (table.get (local.get $i))))
+    (drop (ref.cast null none (table.get (local.get $i))))
+  )
+  (func (export "ref_cast_i31") (param $i i32)
+    (drop (ref.cast i31 (table.get (local.get $i))))
+    (drop (ref.cast null i31 (table.get (local.get $i))))
+  )
+  (func (export "ref_cast_struct") (param $i i32)
+    (drop (ref.cast struct (table.get (local.get $i))))
+    (drop (ref.cast null struct (table.get (local.get $i))))
+  )
+  (func (export "ref_cast_array") (param $i i32)
+    (drop (ref.cast array (table.get (local.get $i))))
+    (drop (ref.cast null array (table.get (local.get $i))))
+  )
+)
+

BIN
tests/unit/gc/wasm-apps/test5.wasm


+ 85 - 0
tests/unit/gc/wasm-apps/test5.wast

@@ -0,0 +1,85 @@
+(module
+  (type $t0 (sub (struct)))
+  (type $t1 (sub $t0 (struct (field i32))))
+  (type $t1' (sub $t0 (struct (field i32))))
+  (type $t2 (sub $t1 (struct (field i32 i32))))
+  (type $t2' (sub $t1' (struct (field i32 i32))))
+  (type $t3 (sub $t0 (struct (field i32 i32))))
+  (type $t0' (sub $t0 (struct)))
+  (type $t4 (sub $t0' (struct (field i32 i32))))
+
+  (table 20 (ref null struct))
+
+  (func $init
+    (table.set (i32.const 0) (struct.new_canon_default $t0))
+    (table.set (i32.const 10) (struct.new_canon_default $t0))
+    (table.set (i32.const 1) (struct.new_canon_default $t1))
+    (table.set (i32.const 11) (struct.new_canon_default $t1'))
+    (table.set (i32.const 2) (struct.new_canon_default $t2))
+    (table.set (i32.const 12) (struct.new_canon_default $t2'))
+    (table.set (i32.const 3) (struct.new_canon_default $t3))
+    (table.set (i32.const 4) (struct.new_canon_default $t4))
+  )
+
+  (func (export "test-sub")
+    (call $init)
+
+    (drop (ref.cast null $t0 (ref.null struct)))
+    (drop (ref.cast null $t0 (table.get (i32.const 0))))
+    (drop (ref.cast null $t0 (table.get (i32.const 1))))
+    (drop (ref.cast null $t0 (table.get (i32.const 2))))
+    (drop (ref.cast null $t0 (table.get (i32.const 3))))
+    (drop (ref.cast null $t0 (table.get (i32.const 4))))
+
+    (drop (ref.cast null $t0 (ref.null struct)))
+    (drop (ref.cast null $t1 (table.get (i32.const 1))))
+    (drop (ref.cast null $t1 (table.get (i32.const 2))))
+
+    (drop (ref.cast null $t0 (ref.null struct)))
+    (drop (ref.cast null $t2 (table.get (i32.const 2))))
+
+    (drop (ref.cast null $t0 (ref.null struct)))
+    (drop (ref.cast null $t3 (table.get (i32.const 3))))
+
+    (drop (ref.cast null $t4 (table.get (i32.const 4))))
+
+    (drop (ref.cast $t0 (table.get (i32.const 0))))
+    (drop (ref.cast $t0 (table.get (i32.const 1))))
+    (drop (ref.cast $t0 (table.get (i32.const 2))))
+    (drop (ref.cast $t0 (table.get (i32.const 3))))
+    (drop (ref.cast $t0 (table.get (i32.const 4))))
+
+    (drop (ref.cast $t1 (table.get (i32.const 1))))
+    (drop (ref.cast $t1 (table.get (i32.const 2))))
+
+    (drop (ref.cast $t2 (table.get (i32.const 2))))
+
+    (drop (ref.cast $t3 (table.get (i32.const 3))))
+
+    (drop (ref.cast $t4 (table.get (i32.const 4))))
+  )
+
+  (func (export "test-canon")
+    (call $init)
+
+    (drop (ref.cast $t0 (table.get (i32.const 0))))
+    (drop (ref.cast $t0 (table.get (i32.const 1))))
+    (drop (ref.cast $t0 (table.get (i32.const 2))))
+    (drop (ref.cast $t0 (table.get (i32.const 3))))
+    (drop (ref.cast $t0 (table.get (i32.const 4))))
+
+    (drop (ref.cast $t0 (table.get (i32.const 10))))
+    (drop (ref.cast $t0 (table.get (i32.const 11))))
+    (drop (ref.cast $t0 (table.get (i32.const 12))))
+
+    (drop (ref.cast $t1' (table.get (i32.const 1))))
+    (drop (ref.cast $t1' (table.get (i32.const 2))))
+
+    (drop (ref.cast $t1 (table.get (i32.const 11))))
+    (drop (ref.cast $t1 (table.get (i32.const 12))))
+
+    (drop (ref.cast $t2' (table.get (i32.const 2))))
+
+    (drop (ref.cast $t2 (table.get (i32.const 12))))
+  )
+)

BIN
tests/unit/gc/wasm-apps/test6.wasm


+ 27 - 0
tests/unit/gc/wasm-apps/test6.wast

@@ -0,0 +1,27 @@
+(module
+  (type $st (sub (struct)))
+  (type $st' (sub (struct (field i32))))
+  (type $at (array i8))
+  (type $st-sub1 (sub $st (struct)))
+  (type $st-sub2 (sub $st (struct)))
+  (type $st'-sub1 (sub $st' (struct (field i32))))
+  (type $st'-sub2 (sub $st' (struct (field i32))))
+
+  (table 20 (ref null eq))
+
+  (func (export "init")
+    (table.set (i32.const 0) (ref.null eq))
+    (table.set (i32.const 1) (ref.null i31))
+    (table.set (i32.const 2) (i31.new (i32.const 7)))
+    (table.set (i32.const 3) (i31.new (i32.const 7)))
+    (table.set (i32.const 4) (i31.new (i32.const 8)))
+    (table.set (i32.const 5) (struct.new_canon_default $st))
+    (table.set (i32.const 6) (struct.new_canon_default $st))
+    (table.set (i32.const 7) (array.new_canon_default $at (i32.const 0)))
+    (table.set (i32.const 8) (array.new_canon_default $at (i32.const 0)))
+  )
+
+  (func (export "eq") (param $i i32) (param $j i32) (result i32)
+    (ref.eq (table.get (local.get $i)) (table.get (local.get $j)))
+  )
+)

+ 1 - 0
tests/unit/interpreter/.gitignore

@@ -0,0 +1 @@
+/build/*

+ 42 - 0
tests/unit/interpreter/CMakeLists.txt

@@ -0,0 +1,42 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-interpreter)
+
+add_definitions (-DRUN_ON_LINUX)
+
+add_definitions (-Dattr_container_malloc=malloc)
+add_definitions (-Dattr_container_free=free)
+# add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 1)
+set (WAMR_BUILD_AOT 0)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${LIBC_BUILTIN_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+    )
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (interpreter_test ${unit_test_sources})
+
+target_link_libraries (interpreter_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+gtest_discover_tests(interpreter_test)

+ 50 - 0
tests/unit/interpreter/interpreter_test.cc

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <limits.h>
+#include "gtest/gtest.h"
+#include "wasm_runtime_common.h"
+#include "bh_platform.h"
+
+// To use a test fixture, derive a class from testing::Test.
+class InterpreterTest : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() { wasm_runtime_destroy(); }
+
+  public:
+    char global_heap_buf[512 * 1024];
+    RuntimeInitArgs init_args;
+};
+
+TEST_F(InterpreterTest, wasm_runtime_is_built_in_module)
+{
+    bool ret = wasm_runtime_is_built_in_module("env");
+    ASSERT_TRUE(ret);
+
+    ret = ret = wasm_runtime_is_built_in_module("env1");
+    ASSERT_FALSE(ret);
+}

+ 32 - 0
tests/unit/libc-builtin/CMakeLists.txt

@@ -0,0 +1,32 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-libc-builtin)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 0)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${WAMR_RUNTIME_LIB_SOURCE}
+    )
+
+add_executable (libc_builtin_test ${unit_test_sources})
+
+target_link_libraries (libc_builtin_test gtest_main)
+
+gtest_discover_tests(libc_builtin_test)

+ 170 - 0
tests/unit/libc-builtin/func_types.h

@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#pragma once
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+extern "C" {
+typedef char *_va_list;
+
+typedef int (*printf_func_type)(wasm_exec_env_t exec_env, const char *format,
+                                _va_list va_args);
+
+typedef int (*sprintf_func_type)(wasm_exec_env_t exec_env, char *str,
+                                 const char *format, _va_list va_args);
+
+typedef int (*snprintf_func_type)(wasm_exec_env_t exec_env, char *str,
+                                  uint32 size, const char *format,
+                                  _va_list va_args);
+
+typedef int (*puts_func_type)(wasm_exec_env_t exec_env, const char *str);
+
+typedef int (*putchar_func_type)(wasm_exec_env_t exec_env, int c);
+
+typedef uint32 (*strdup_func_type)(wasm_exec_env_t exec_env, const char *str);
+
+typedef uint32 (*_strdup_func_type)(wasm_exec_env_t exec_env, const char *str);
+
+typedef int32 (*memcmp_func_type)(wasm_exec_env_t exec_env, const void *s1,
+                                  const void *s2, uint32 size);
+
+typedef uint32 (*memcpy_func_type)(wasm_exec_env_t exec_env, void *dst,
+                                   const void *src, uint32 size);
+
+typedef uint32 (*memmove_func_type)(wasm_exec_env_t exec_env, void *dst,
+                                    void *src, uint32 size);
+
+typedef uint32 (*memset_func_type)(wasm_exec_env_t exec_env, void *s, int32 c,
+                                   uint32 size);
+
+typedef uint32 (*strchr_func_type)(wasm_exec_env_t exec_env, const char *s,
+                                   int32 c);
+
+typedef int32 (*strcmp_func_type)(wasm_exec_env_t exec_env, const char *s1,
+                                  const char *s2);
+
+typedef int32 (*strncmp_func_type)(wasm_exec_env_t exec_env, const char *s1,
+                                   const char *s2, uint32 size);
+
+typedef uint32 (*strcpy_func_type)(wasm_exec_env_t exec_env, char *dst,
+                                   const char *src);
+
+typedef uint32 (*strncpy_func_type)(wasm_exec_env_t exec_env, char *dst,
+                                    const char *src, uint32 size);
+
+typedef uint32 (*strlen_func_type)(wasm_exec_env_t exec_env, const char *s);
+
+typedef uint32 (*malloc_func_type)(wasm_exec_env_t exec_env, uint32 size);
+
+typedef uint32 (*calloc_func_type)(wasm_exec_env_t exec_env, uint32 nmemb,
+                                   uint32 size);
+
+typedef uint32 (*realloc_func_type)(wasm_exec_env_t exec_env, uint32 ptr,
+                                    uint32 new_size);
+
+typedef void (*free_func_type)(wasm_exec_env_t exec_env, void *ptr);
+
+typedef int32 (*atoi_func_type)(wasm_exec_env_t exec_env, const char *s);
+
+typedef void (*exit_func_type)(wasm_exec_env_t exec_env, int32 status);
+
+typedef int32 (*strtol_func_type)(wasm_exec_env_t exec_env, const char *nptr,
+                                  char **endptr, int32 base);
+
+typedef uint32 (*strtoul_func_type)(wasm_exec_env_t exec_env, const char *nptr,
+                                    char **endptr, int32 base);
+
+typedef uint32 (*memchr_func_type)(wasm_exec_env_t exec_env, const void *s,
+                                   int32 c, uint32 n);
+
+typedef int32 (*strncasecmp_func_type)(wasm_exec_env_t exec_env, const char *s1,
+                                       const char *s2, uint32 n);
+typedef uint32 (*strspn_func_type)(wasm_exec_env_t exec_env, const char *s,
+                                   const char *accept);
+
+typedef uint32 (*strcspn_func_type)(wasm_exec_env_t exec_env, const char *s,
+                                    const char *reject);
+
+typedef uint32 (*strstr_func_type)(wasm_exec_env_t exec_env, const char *s,
+                                   const char *find);
+
+typedef int32 (*isupper_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*isalpha_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*isspace_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*isgraph_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*isprint_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*isdigit_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*isxdigit_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*tolower_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*toupper_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef int32 (*isalnum_func_type)(wasm_exec_env_t exec_env, int32 c);
+
+typedef void (*setTempRet0_func_type)(wasm_exec_env_t exec_env,
+                                      uint32 temp_ret);
+
+typedef uint32 (*getTempRet0_func_type)(wasm_exec_env_t exec_env);
+
+typedef uint32 (*llvm_bswap_i16_func_type)(wasm_exec_env_t exec_env,
+                                           uint32 data);
+
+typedef uint32 (*llvm_bswap_i32_func_type)(wasm_exec_env_t exec_env,
+                                           uint32 data);
+
+typedef uint32 (*bitshift64Lshr_func_type)(wasm_exec_env_t exec_env,
+                                           uint32 uint64_part0,
+                                           uint32 uint64_part1, uint32 bits);
+
+typedef uint32 (*bitshift64Shl_func_type)(wasm_exec_env_t exec_env,
+                                          uint32 int64_part0,
+                                          uint32 int64_part1, uint32 bits);
+
+typedef void (*llvm_stackrestore_func_type)(wasm_exec_env_t exec_env,
+                                            uint32 llvm_stack);
+
+typedef uint32 (*llvm_stacksave_func_type)(wasm_exec_env_t exec_env);
+
+typedef uint32 (*emscripten_memcpy_big_func_type)(wasm_exec_env_t exec_env,
+                                                  void *dst, const void *src,
+                                                  uint32 size);
+
+typedef void (*abort_func_type)(wasm_exec_env_t exec_env, int32 code);
+
+typedef void (*abortStackOverflow_func_type)(wasm_exec_env_t exec_env,
+                                             int32 code);
+
+typedef void (*nullFunc_X_func_type)(wasm_exec_env_t exec_env, int32 code);
+
+typedef uint32 (*__cxa_allocate_exception_func_type)(wasm_exec_env_t exec_env,
+                                                     uint32 thrown_size);
+
+typedef void (*__cxa_begin_catch_func_type)(wasm_exec_env_t exec_env,
+                                            void *exception_object);
+
+typedef void (*__cxa_throw_func_type)(wasm_exec_env_t exec_env,
+                                      void *thrown_exception, void *tinfo,
+                                      uint32 table_elem_idx);
+
+struct timespec_app {
+    int64 tv_sec;
+    int32 tv_nsec;
+};
+
+typedef uint32 (*clock_gettime_func_type)(wasm_exec_env_t exec_env,
+                                          uint32 clk_id,
+                                          struct timespec_app *ts_app);
+
+typedef uint64 (*clock_func_type)(wasm_exec_env_t exec_env);
+}

+ 1412 - 0
tests/unit/libc-builtin/libc_builtin_test.cc

@@ -0,0 +1,1412 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "func_types.h"
+#include "test_helper.h"
+#include "wasm_export.h"
+#include "gtest/gtest.h"
+#include <limits.h>
+
+#include "../interpreter/wasm.h"
+
+void *func_ptr;
+#define CALL_FUNC(name, ...) \
+    ((name##_func_type)get_func(#name))(dummy_exec_env.get(), ##__VA_ARGS__)
+
+extern "C" {
+extern uint32_t
+get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
+
+extern bool
+wasm_native_lookup_libc_builtin_global(const char *module_name,
+                                       const char *global_name,
+                                       WASMGlobalImport *global);
+}
+
+class LibcBuiltinTest : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp()
+    {
+        n_native_symbols = get_libc_builtin_export_apis(&native_symbols);
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+  public:
+    WAMRRuntimeRAII<512 * 1024> runtime;
+    DummyExecEnv dummy_exec_env;
+    static NativeSymbol *native_symbols;
+    static uint32_t n_native_symbols;
+
+    static void *get_func(const char *name)
+    {
+        int32_t i;
+
+        for (i = 0; i < n_native_symbols; i++) {
+            if (strcmp(native_symbols[i].symbol, name) == 0) {
+                return native_symbols[i].func_ptr;
+            }
+        }
+
+        return NULL;
+    }
+};
+
+NativeSymbol *LibcBuiltinTest::native_symbols;
+uint32_t LibcBuiltinTest::n_native_symbols;
+
+static const char very_long_string[] =
+    R"(2mwa9vxDhuuvO47XePZvc4DAMdR8dzgKrmRNAM3qVoedFhG7GYyhlC4JiuSdrw8G
+         7vrPoCLGlVlGwMw7ATDL3bA5Filds8krTxS7h8ioq6CY4UmKl1zjHlmnOYRO3Wmp
+         ylp21RrG8LzfHFerFyKFxA1GB93OuTFcasO2n9uQljCx8h5KRolbvjdHVnado4B6
+         3zNV990V7T7LIJHwZKb0RGg0fFo4GQd6Mfdl6aD3UlpKBIxjbonyeaQBY7hPZB8R
+         J1JV5iw2PWB2BJEGoGhTvlc0a9FxmeqWIjpnU3yNEg2lD3NjZU627pTFcoAy5GCz
+         wDyF5QzcvtAgWBR95kRpDtV21CRyQ6HteorX1aHemoMYWOLIvX52stUTAnOImMD8
+         tIw6xwkOZx5fs3x9m540pPnRDiihLn2XuQ1PLPwA6orWOGm3dBKthqsycTqaIl0L
+         0gpycKbVYFHmakfgEyP9fyMziLT11B6EPzomHQAYgTVUdDl9u63P6sQCeaPwAYsY
+         gus28uK9YYjpXgOOziG8ocBddvids1iLJLdbiAqKyHaVY4IBLVWU3F74tKGF7TeI
+         DGAfvpzHls19VM9bKReBfCmDgbib7mCpYEFAQCmu5my0C8QrJlUoOgiljIO0x3sH
+         ByNf4k9OfhzYi1V4cvDnMELVrk0fyZWmIxDvig7nfzI57OltT28pughPBlLxTn8X
+         xyMNVYn1dD6Wpp7sqOBjxWGWmdrjleyin0iQ05UbfioHazvLKHtDfm5P2WwVejm6)";
+
+TEST_F(LibcBuiltinTest, puts)
+{
+    char ll_string[2048];
+
+    /* Capture the stdout */
+    testing::internal::CaptureStdout();
+    EXPECT_EQ(CALL_FUNC(puts, "Hello Wrold"), strlen("Hello Wrold\n"));
+    EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold\n");
+
+    testing::internal::CaptureStdout();
+    EXPECT_EQ(CALL_FUNC(puts, "c"), strlen("c\n"));
+    EXPECT_EQ(testing::internal::GetCapturedStdout(), "c\n");
+
+    testing::internal::CaptureStdout();
+    EXPECT_EQ(CALL_FUNC(puts, very_long_string), strlen(very_long_string) + 1);
+    EXPECT_EQ(testing::internal::GetCapturedStdout(),
+              std::string(very_long_string) + "\n");
+
+    memset(ll_string, 0xAA, sizeof(ll_string));
+    testing::internal::CaptureStdout();
+    EXPECT_EQ(CALL_FUNC(puts, ll_string), strlen(ll_string) + 1);
+    EXPECT_EQ(testing::internal::GetCapturedStdout(),
+              std::string(ll_string) + "\n");
+}
+
+TEST_F(LibcBuiltinTest, printf)
+{
+    WAMRVaList empty_va_list(dummy_exec_env.get());
+
+    /* Capture the stdout */
+    testing::internal::CaptureStdout();
+    EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", empty_va_list.get()),
+              strlen("Hello Wrold"));
+    EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold");
+
+    testing::internal::CaptureStdout();
+    EXPECT_EQ(CALL_FUNC(printf, "c", empty_va_list.get()), strlen("c"));
+    EXPECT_EQ(testing::internal::GetCapturedStdout(), "c");
+
+    testing::internal::CaptureStdout();
+    EXPECT_EQ(CALL_FUNC(printf, very_long_string, empty_va_list.get()),
+              strlen(very_long_string));
+    EXPECT_EQ(testing::internal::GetCapturedStdout(), very_long_string);
+
+    /* type */
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add(20);            //%d 20
+        va_list.add(65);            //%i 65
+        va_list.add(10);            //%O 12
+        va_list.add(10);            //%u 10
+        va_list.add(255);           //%x ff
+        va_list.add(255);           //%X FF
+        va_list.add(3.14);          //%f 3.14
+        va_list.add(3.14);          //%F 3.14
+        va_list.add(0.000001);      //%e 1.000000e-06
+        va_list.add(0.000001);      //%E 1.000000E-06
+        va_list.add(0.000001);      //%g 1e-06
+        va_list.add(0.000001);      //%G 1E-06
+        va_list.add("Hello World"); //%s Hello World
+
+        testing::internal::CaptureStdout();
+        /* clang-format off */
+        EXPECT_EQ(CALL_FUNC(printf, "%d, %i, %o, %u, %x, %X, %f, %F, %e, %E, %g, %G, %s", va_list.get()), 97);
+        EXPECT_EQ(testing::internal::GetCapturedStdout(),
+        "20, 65, 12, 10, ff, FF, 3.140000, 3.140000, 1.000000e-06, 1.000000E-06, 1e-06, 1E-06, Hello World");
+        /* clang-format on */
+    }
+
+    /* %c */
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add('C'); //%c C
+        // va_list.add("Hello"); //%p
+        testing::internal::CaptureStdout();
+        EXPECT_EQ(CALL_FUNC(printf, "%c", va_list.get()), 1);
+        EXPECT_EQ(testing::internal::GetCapturedStdout(), "C");
+    }
+
+    /* %p */
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add("Hello");
+        testing::internal::CaptureStdout();
+        EXPECT_EQ(CALL_FUNC(printf, "%p", va_list.get()), 7);
+        EXPECT_EQ(testing::internal::GetCapturedStdout(), "0x200a8");
+    }
+
+    {
+        /* clang-format off */
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add(20);        //%td
+        va_list.add(20);        //%zd
+        va_list.add(20);        //%ld
+
+        va_list.add(20L);        //%jd
+
+        testing::internal::CaptureStdout();
+
+        EXPECT_EQ(CALL_FUNC(printf, "%td, %zd, %ld, %jd", va_list.get()), 14);
+        EXPECT_EQ(testing::internal::GetCapturedStdout(),
+                  "20, 20, 20, 20");
+        /* clang-format on */
+    }
+
+    /* %% */
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+        EXPECT_TRUE(CALL_FUNC(printf, "%%", va_list.get()));
+    }
+
+    /* %n */
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList empty_va_list(dummy_exec_env.get());
+
+        /* Capture the stdout */
+        testing::internal::CaptureStdout();
+        CALL_FUNC(printf, "0123%n", empty_va_list.get());
+        EXPECT_EQ(testing::internal::GetCapturedStdout(), "0123");
+    }
+
+    /* flag */
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        /*%-*/
+        va_list.add(20); //%-d 20
+        va_list.add(20); //%d 20
+
+        /*%+*/
+        va_list.add(20);  //%+d +20
+        va_list.add(-20); //%+d -20
+
+        /*% */
+        va_list.add(20);  //% d  20
+        va_list.add(-20); //% d -20
+
+        /*%#*/
+        va_list.add(20);   //%#o 024
+        va_list.add(255);  //%#x 0xff
+        va_list.add(255);  //%#X 0xFF
+        va_list.add(3.14); //%#.f 3.
+        va_list.add(3.14); //%#.lf 3.
+        va_list.add(3.14); //%#.e 3.e+00
+        va_list.add(3.14); //%#.E 3.E+00
+        va_list.add(3.14); //%#.g 3.
+        va_list.add(3.14); //%#.G 3.
+        va_list.add(20);   //%#.a %a
+        va_list.add(20);   //%#.A %A
+
+        /*%0*/
+        va_list.add(20); //%03d 020
+
+        testing::internal::CaptureStdout();
+        /* clang-format off */
+        EXPECT_EQ(CALL_FUNC(printf, "%-d, %d, %+d, %+d, % d, % d, %#o, %#x, %#X, %#.f, %#.lf, %#.e, %#.E, %#.g, %#.G, %#.a, %#.A, %03d", va_list.get()), 88);
+        EXPECT_EQ(testing::internal::GetCapturedStdout(),
+                  "20, 20, +20, -20,  20, -20, 024, 0xff, 0XFF, 3., 3., 3.e+00, 3.E+00, 3., 3., %a, %A, 020");
+        /* clang-format on */
+    }
+
+    /* precision */
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add(20); //%d 20
+        va_list.add(20); //%.1d 20
+        va_list.add(20); //%.2d 20
+        va_list.add(20); //%.3d 020
+        va_list.add(20); //%.4d 0020
+        va_list.add(20); //%.5d 00020
+        va_list.add(20); //%.6d 000020
+        va_list.add(20); //%.7d 0000020
+        va_list.add(20); //%.8d 00000020
+        va_list.add(20); //%.9d 000000020
+        testing::internal::CaptureStdout();
+        /* clang-format off */
+        EXPECT_EQ(CALL_FUNC(printf, "%d, %.1d, %.2d, %.3d, %.4d, %.5d, %.6d, %.7d, %.8d, %.9d", va_list.get()), 66);
+        EXPECT_EQ(testing::internal::GetCapturedStdout(),
+                  "20, 20, 20, 020, 0020, 00020, 000020, 0000020, 00000020, 000000020");
+        /* clang-format on */
+    }
+
+    /*length*/
+    {
+        /* clang-format off */
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add(0x7F);        //%hhd 127  -char
+        va_list.add(0xFF);        //%hhu.1d 255 -unsiged char
+        va_list.add(0x7FFF);      //%hd 32767 -sing short int
+        va_list.add(0xFFFF);      //%hu 65535 -unsiged short
+        va_list.add(0x7FFFFFFF); //%ld 2147483647 - sing long
+        va_list.add(0xFFFFFFFF); //%lu 4294967295 -unsigned long
+        va_list.add(0x7FFFFFFFFFFFFFFF); //%lld 9223372036854775807 sing long long
+        va_list.add(0xFFFFFFFFFFFFFFFF);//%llu 18446744073709551615 unsiged long long
+
+        testing::internal::CaptureStdout();
+
+        EXPECT_EQ(CALL_FUNC(printf, "%hhd, %hhu, %hd, %hu, %ld, %lu, %lld, %llu", va_list.get()), 89);
+        EXPECT_EQ(testing::internal::GetCapturedStdout(),
+                  "127, 255, 32767, 65535, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615");
+        /* clang-format on */
+    }
+
+    EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", 0), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", NULL), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", (char *)-1), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_EQ(CALL_FUNC(printf, (char *)-1, (char *)-1), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+}
+
+TEST_F(LibcBuiltinTest, sprintf)
+{
+    const char *buf;
+    const char *str = "Hello Wrold";
+    const char *str_sig = "c";
+    const char *str_f = "20, 3.140000, Hello World";
+    const char *str_long = "eqwewerwerqwer34were"; // test ok
+    // const char *str_long = "TDSFGAWE%#$TERFQ@$%$@!%$@!RS!$#@$%"
+    //                             "WAWAAEWAFSDNGFUTKNZDAERQWYNZREWGHAH";
+    //                             //fail
+
+    WAMRVaList empty_va_list(dummy_exec_env.get());
+
+    AppData buf_app{ dummy_exec_env.get(), buf };
+    AppData str_app{ dummy_exec_env.get(), str };
+    AppData str_sig_app{ dummy_exec_env.get(), str_sig };
+    AppData str_long_app{ dummy_exec_env.get(), str_long };
+
+    EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
+                        (char *)str_app.get_native_addr(), 0),
+              0);
+    EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
+                        (char *)str_app.get_native_addr(), NULL),
+              0);
+    EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
+                        (char *)str_app.get_native_addr(), (char *)-1),
+              0);
+
+    EXPECT_FALSE(CALL_FUNC(sprintf, (char *)-1,
+                           (char *)str_app.get_native_addr(),
+                           empty_va_list.get()));
+
+    EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
+                        (char *)str_app.get_native_addr(), empty_va_list.get()),
+              strlen(str));
+    EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(),
+                        str_app.get_native_addr(), strlen(str)),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
+                        (char *)str_sig_app.get_native_addr(),
+                        empty_va_list.get()),
+              strlen(str_sig));
+    EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(),
+                        str_sig_app.get_native_addr(), strlen(str_sig)),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
+                        (char *)str_long_app.get_native_addr(),
+                        empty_va_list.get()),
+              strlen(str_long));
+    EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(),
+                        str_long_app.get_native_addr(), strlen(str_long)),
+              0);
+
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add(20);
+        va_list.add(3.14);
+        va_list.add("Hello World");
+
+        /* This is like printf("%d, %f, %s", 20, 3.14, "Hello World") */
+        EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(),
+                            "%d, %f, %s", va_list.get()),
+                  25);
+        EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), str_f, 25), 0);
+    }
+}
+
+TEST_F(LibcBuiltinTest, snprintf)
+{
+    char buf[1024];
+    char buf1[10];
+
+    WAMRVaList empty_va_list(dummy_exec_env.get());
+
+    EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", 0),
+              0);
+    EXPECT_EQ(
+        CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", NULL),
+        0);
+    EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold",
+                        (char *)-1),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold",
+                        empty_va_list.get()),
+              strlen("Hello Wrold"));
+    EXPECT_EQ(CALL_FUNC(memcmp, buf, "Hello Wrold", strlen("Hello Wrold")), 0);
+
+    EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen(very_long_string),
+                        very_long_string, empty_va_list.get()),
+              strlen(very_long_string));
+    {
+        /* Construct a va_list to call printf */
+        WAMRVaList va_list(dummy_exec_env.get());
+
+        va_list.add(20);
+        va_list.add(3.14);
+        va_list.add("Hello World");
+
+        EXPECT_EQ(CALL_FUNC(snprintf, buf, 25, "%d, %f, %s", va_list.get()),
+                  25);
+    }
+}
+
+TEST_F(LibcBuiltinTest, putchar)
+{
+    char ch;
+
+    for (ch = 'a'; ch <= 'z'; ch++)
+        EXPECT_EQ(CALL_FUNC(putchar, ch), 1);
+
+    for (ch = '0'; ch <= '9'; ch++)
+        EXPECT_EQ(CALL_FUNC(putchar, ch), 1);
+
+    for (ch = 0; ch < 127; ch++)
+        EXPECT_EQ(CALL_FUNC(putchar, ch), 1);
+}
+
+TEST_F(LibcBuiltinTest, strdup)
+{
+    const char *src = "Hello World!";
+
+    AppData src_app{ dummy_exec_env.get(), src };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(strdup, NULL), 0);
+
+    EXPECT_GE(CALL_FUNC(strdup, (char *)src_app.get_native_addr()), 0);
+}
+
+TEST_F(LibcBuiltinTest, _strdup)
+{
+    const char *src = "Hello World!";
+
+    AppData src_app{ dummy_exec_env.get(), src };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(_strdup, NULL), 0);
+
+    EXPECT_GE(CALL_FUNC(_strdup, (char *)src_app.get_native_addr()), 0);
+}
+
+TEST_F(LibcBuiltinTest, memcmp)
+{
+    const char *a = "aBcDeF";
+    const char *b = "AbCdEf";
+    const char *c = "aacdef";
+    const char *d = "aBcDeF";
+
+    AppData a_app{ dummy_exec_env.get(), a };
+    AppData b_app{ dummy_exec_env.get(), b };
+    AppData c_app{ dummy_exec_env.get(), c };
+    AppData d_app{ dummy_exec_env.get(), d };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(memcmp, (void *)-1, d_app.get_native_addr(), 0), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    /* size = 0 */
+    EXPECT_EQ(
+        CALL_FUNC(memcmp, a_app.get_native_addr(), d_app.get_native_addr(), 0),
+        0);
+
+    // /* s1>s2 */
+    EXPECT_GT(CALL_FUNC(memcmp, a_app.get_native_addr(),
+                        b_app.get_native_addr(), strlen(a)),
+              0);
+    // /* s1<s2 */
+    EXPECT_LT(CALL_FUNC(memcmp, a_app.get_native_addr(),
+                        c_app.get_native_addr(), strlen(a)),
+              0);
+
+    // /* s1=s2 */
+    EXPECT_EQ(CALL_FUNC(memcmp, a_app.get_native_addr(),
+                        d_app.get_native_addr(), strlen(a)),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, memcpy)
+{
+    const char *src = "Hell World";
+    char *dest;
+
+    AppData src_app{ dummy_exec_env.get(), src };
+    AppData dest_app{ dummy_exec_env.get(), dest };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(memcpy, (void *)-1, src_app.get_native_addr(), 0), 0);
+
+    EXPECT_EQ(CALL_FUNC(memcpy, dest_app.get_native_addr(),
+                        src_app.get_native_addr(), 0),
+              dest_app.get_app_addr());
+
+    EXPECT_EQ(CALL_FUNC(memcpy, (void *)-1, src_app.get_native_addr(), 10), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    CALL_FUNC(memcpy, dest_app.get_native_addr(), src_app.get_native_addr(),
+              strlen(src));
+    EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
+                        src_app.get_native_addr(), strlen(src)),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, memmove)
+{
+    const char *src = "Hell World";
+    char *dest;
+
+    AppData src_app{ dummy_exec_env.get(), src };
+    AppData dest_app{ dummy_exec_env.get(), dest };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(memmove, (void *)-1, dest_app.get_native_addr(), 0), 0);
+
+    EXPECT_EQ(CALL_FUNC(memmove, dest_app.get_native_addr(),
+                        src_app.get_native_addr(), 0),
+              dest_app.get_app_addr());
+
+    EXPECT_EQ(CALL_FUNC(memmove, (void *)-1, dest_app.get_native_addr(), 10),
+              0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    CALL_FUNC(memmove, dest_app.get_native_addr(), src_app.get_native_addr(),
+              strlen(src));
+    EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
+                        src_app.get_native_addr(), strlen(src)),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, memset)
+{
+    const char *src = "Hello World!";
+    AppData src_app{ dummy_exec_env.get(), src };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(memset, (void *)-1, 1, strlen(src)), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_EQ(CALL_FUNC(memcmp, src_app.get_native_addr(), "Hello World!",
+                        strlen(src)),
+              0);
+    EXPECT_GE(CALL_FUNC(memset, src_app.get_native_addr(), '\0', strlen(src)),
+              0);
+    EXPECT_EQ(CALL_FUNC(memcmp, src_app.get_native_addr(),
+                        "\0\0\0\0\0\0\0\0\0\0\0\0", strlen(src)),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, strchr)
+{
+    const char *src = "Hell World";
+    unsigned int ch_existent = 'o';
+    unsigned int ch_non_existent = '$';
+
+    AppData src_app{ dummy_exec_env.get(), src };
+
+    EXPECT_EQ(
+        CALL_FUNC(strchr, (char *)src_app.get_native_addr(), ch_non_existent),
+        0);
+    EXPECT_GE(CALL_FUNC(strchr, (char *)src_app.get_native_addr(), ch_existent),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, strcmp)
+{
+    const char *a = "Hello World!";
+    const char *b = "hello World!";
+    const char *c = "Hello World!";
+
+    AppData a_app{ dummy_exec_env.get(), a };
+    AppData b_app{ dummy_exec_env.get(), b };
+    AppData c_app{ dummy_exec_env.get(), c };
+
+    /*s1>s2*/
+    EXPECT_GT(CALL_FUNC(strcmp, (char *)b_app.get_native_addr(),
+                        (char *)a_app.get_native_addr()),
+              0);
+    /*s1<s2*/
+    EXPECT_LT(CALL_FUNC(strcmp, (char *)a_app.get_native_addr(),
+                        (char *)b_app.get_native_addr()),
+              0);
+    /*s1=s2*/
+    EXPECT_EQ(CALL_FUNC(strcmp, (char *)a_app.get_native_addr(),
+                        (char *)c_app.get_native_addr()),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, strncmp)
+{
+    const char *a = "Hello World!";
+    const char *b = "hello World!";
+    const char *c = "Hello World!";
+
+    AppData a_app{ dummy_exec_env.get(), a };
+    AppData b_app{ dummy_exec_env.get(), b };
+    AppData c_app{ dummy_exec_env.get(), c };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(strncmp, (char *)-1, (char *)a_app.get_native_addr(),
+                        strlen(a)),
+              0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    /* size = 0 */
+    EXPECT_EQ(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
+                        (char *)c_app.get_native_addr(), 0),
+              0);
+
+    /*s1>s2*/
+    EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(),
+                        (char *)a_app.get_native_addr(), strlen(a)),
+              0);
+    /*s1<s2*/
+    EXPECT_LT(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
+                        (char *)b_app.get_native_addr(), strlen(a)),
+              0);
+    /*s1=s2*/
+    EXPECT_EQ(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
+                        (char *)c_app.get_native_addr(), strlen(a)),
+              0);
+
+    /*s1>s2*/
+    EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(),
+                        (char *)a_app.get_native_addr(), 3),
+              0);
+    /*s1<s2*/
+    EXPECT_LT(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
+                        (char *)b_app.get_native_addr(), 3),
+              0);
+    /*s1=s2*/
+    EXPECT_EQ(CALL_FUNC(strncmp, (char *)a_app.get_native_addr(),
+                        (char *)c_app.get_native_addr(), 3),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, strcpy)
+{
+    char *src = (char *)"Hello World!";
+    char *dest;
+
+    AppData src_app{ dummy_exec_env.get(), src };
+    AppData dest_app{ dummy_exec_env.get(), dest };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(strcpy, (char *)-1, (char *)src_app.get_native_addr()),
+              0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_GE(CALL_FUNC(strcpy, (char *)dest_app.get_native_addr(),
+                        (char *)src_app.get_native_addr()),
+              0);
+    EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
+                        (char *)src_app.get_native_addr(), strlen(src)),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, strncpy)
+{
+    char *src = (char *)"Hello World!";
+    char *dest;
+
+    AppData src_app{ dummy_exec_env.get(), src };
+    AppData dest_app{ dummy_exec_env.get(), dest };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(strncpy, (char *)-1, (char *)src_app.get_native_addr(),
+                        strlen(src)),
+              0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_GE(CALL_FUNC(strncpy, (char *)dest_app.get_native_addr(),
+                        (char *)src_app.get_native_addr(), strlen(src)),
+              0);
+    EXPECT_EQ(CALL_FUNC(memcmp, (char *)dest_app.get_native_addr(),
+                        (char *)src_app.get_native_addr(), strlen(src)),
+              0);
+
+    EXPECT_GE(CALL_FUNC(strncpy, (char *)dest_app.get_native_addr(),
+                        (char *)src_app.get_native_addr(), 3),
+              0);
+    EXPECT_EQ(CALL_FUNC(memcmp, (char *)dest_app.get_native_addr(),
+                        (char *)src_app.get_native_addr(), 3),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, strlen)
+{
+    const char *src = "Hello World!";
+
+    AppData src_app{ dummy_exec_env.get(), src };
+
+    EXPECT_EQ(CALL_FUNC(strlen, (char *)src_app.get_native_addr()), 12);
+}
+
+TEST_F(LibcBuiltinTest, malloc)
+{
+    EXPECT_GT(CALL_FUNC(malloc, 0), 0);
+    EXPECT_GT(CALL_FUNC(malloc, 100), 0);
+    EXPECT_EQ(CALL_FUNC(malloc, 0xFFFFFFFF), 0);
+}
+
+TEST_F(LibcBuiltinTest, calloc)
+{
+    /* nmemb = 1 size=0xffffffff total_size >= UINT32_MAX  */
+    EXPECT_EQ(CALL_FUNC(calloc, 1, 0xffffffff), 0);
+
+    /* nmemb = 1 size=0xffffffff-1 total_size >= UINT32_MAX-1  */
+    EXPECT_EQ(CALL_FUNC(calloc, 1, (0xffffffff - 1)), 0);
+
+    /* nmemb = 1 size = 0 total_size = 0 */
+    /* According to Linux man page:
+    If nmemb or size is 0, then calloc() returns either NULL, or a unique
+    pointer value that can later be successfully  passed  to free() */
+    EXPECT_GE(CALL_FUNC(calloc, 1, 0), 0);
+
+    /* nmemb = 10 size = 1024 total_size < UINT32_MAX */
+    EXPECT_GT(CALL_FUNC(calloc, 10, 1024), 0);
+}
+
+TEST_F(LibcBuiltinTest, realloc)
+{
+    unsigned int ptr = 0;
+
+    // ptr = 0;
+    // EXPECT_EQ(CALL_FUNC(realloc, ptr, 1024), 0);
+
+    // ptr = 1;
+    // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0);
+
+    // ptr = 3;
+    // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0);
+
+    /* If ptr is NULL, then the call is equivalent to malloc(size), for all
+     * values of size */
+    ptr = CALL_FUNC(realloc, ptr, 1024);
+    EXPECT_EQ(ptr, ptr);
+    EXPECT_EQ(CALL_FUNC(realloc, ptr, 10), ptr);
+    EXPECT_EQ(CALL_FUNC(realloc, ptr, 15), ptr);
+
+    ptr = CALL_FUNC(realloc, ptr, 2048);
+    EXPECT_EQ(ptr, ptr);
+
+    /* If size is equal to zero, and ptr is not NULL, then
+       the call is equivalent to free(ptr) */
+    CALL_FUNC(realloc, ptr, 0);
+}
+
+TEST_F(LibcBuiltinTest, free)
+{
+    const char *src;
+    const char *s = "Hello World!";
+
+    AppMemory src_mem{ dummy_exec_env.get(), 15 };
+    AppData s_app{ dummy_exec_env.get(), s };
+
+    CALL_FUNC(free, (char *)0xFFFFFFFF);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    CALL_FUNC(free, (char *)-1);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    CALL_FUNC(free, NULL);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    memset((char *)src_mem.get_native_addr(), '\0', 15);
+    strcpy((char *)src_mem.get_native_addr(), (char *)s_app.get_native_addr());
+    EXPECT_EQ(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(),
+                        s_app.get_native_addr(), 15),
+              0);
+
+    /* free */
+    CALL_FUNC(free, (char *)src_mem.get_native_addr());
+    EXPECT_NE(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(),
+                        s_app.get_native_addr(), 15),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, atoi)
+{
+    char *src = (char *)"123";
+    char *src1 = (char *)"-123";
+
+    AppData src_app{ dummy_exec_env.get(), src };
+    AppData src1_app{ dummy_exec_env.get(), src1 };
+
+    EXPECT_EQ(CALL_FUNC(atoi, (char *)src_app.get_native_addr()), 123);
+    EXPECT_EQ(CALL_FUNC(atoi, (char *)src1_app.get_native_addr()), -123);
+}
+
+TEST_F(LibcBuiltinTest, exit)
+{
+    CALL_FUNC(exit, 3);
+    EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.exit(3)");
+    dummy_exec_env.clear_exception();
+}
+
+TEST_F(LibcBuiltinTest, strtol)
+{
+    char str[20] = "20";
+    char str1[20] = "-20";
+    char buffer[20] = "0x31";
+    char buffer1[20] = "10379cend$3";
+    char *ptr;
+
+    AppData src_app{ dummy_exec_env.get(), str };
+    AppData src1_app{ dummy_exec_env.get(), str1 };
+    AppData buffer_app{ dummy_exec_env.get(), buffer };
+    AppData buffer1_app{ dummy_exec_env.get(), buffer1 };
+    AppMemory ptr_app{ dummy_exec_env.get(), 20 };
+
+    CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    CALL_FUNC(strtol, (char *)src_app.get_native_addr(), &ptr, 10);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 2), 0);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 8), 0);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 16),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 32),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 2),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 8),
+              16);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 10),
+              20);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 16),
+              32);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 32),
+              64);
+
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 2),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 8),
+              -16);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 10),
+              -20);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 16),
+              -32);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 32),
+              -64);
+
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 0),
+              49);
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 16),
+              49);
+
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 10),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer1_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 10),
+              10379);
+    // EXPECT_STREQ((char *)ptr_app.get_native_addr(), "cend$3");
+
+    uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr();
+    EXPECT_GT(str_app_addr, 0);
+    char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr);
+    EXPECT_NE(str_native_addr, nullptr);
+    EXPECT_STREQ(str_native_addr, "cend$3");
+}
+
+TEST_F(LibcBuiltinTest, strtoul)
+{
+    char str[20] = "20";
+    char buffer[20] = "0x31";
+    char buffer1[20] = "10379cend$3";
+    char *ptr;
+
+    AppData src_app{ dummy_exec_env.get(), str };
+    AppData buffer_app{ dummy_exec_env.get(), buffer };
+    AppData buffer1_app{ dummy_exec_env.get(), buffer1 };
+    AppMemory ptr_app{ dummy_exec_env.get(), 20 };
+
+    CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), &ptr, 10);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 2),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 8),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 16),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 32),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 2),
+              0);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 8),
+              16);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 10),
+              20);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 16),
+              32);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 32),
+              64);
+
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 0),
+              49);
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 16),
+              49);
+
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 10),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer1_app.get_native_addr(),
+                        (char **)ptr_app.get_native_addr(), 10),
+              10379);
+
+    uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr();
+    EXPECT_GT(str_app_addr, 0);
+    char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr);
+    EXPECT_NE(str_native_addr, nullptr);
+    EXPECT_STREQ(str_native_addr, "cend$3");
+}
+
+TEST_F(LibcBuiltinTest, memchr)
+{
+    const char src[] = "Hello World.";
+    char ch = 'o';
+
+    AppData src_app{ dummy_exec_env.get(), src };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(memchr, (char *)-1, ch, strlen(src)), 0);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: out of bounds memory access");
+    dummy_exec_env.clear_exception();
+
+    EXPECT_GE(CALL_FUNC(memchr, src_app.get_native_addr(), ch, strlen(src)), 0);
+}
+
+TEST_F(LibcBuiltinTest, strncasecmp)
+{
+    const char *src1 = "Hello World.";
+    const char *src2 = "hel";
+    const char *src3 = "HELLO WORLD.";
+
+    AppData src1_app{ dummy_exec_env.get(), src1 };
+    AppData src2_app{ dummy_exec_env.get(), src2 };
+    AppData src3_app{ dummy_exec_env.get(), src3 };
+
+    EXPECT_GT(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(),
+                        (char *)src2_app.get_native_addr(), 4),
+              0);
+
+    EXPECT_LT(CALL_FUNC(strncasecmp, (char *)src2_app.get_native_addr(),
+                        (char *)src1_app.get_native_addr(), 4),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(),
+                        (char *)src3_app.get_native_addr(), strlen(src1)),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, strspn)
+{
+    const char *src1 = "Hello world!";
+    const char *src2 = "abcd";
+    const char *src3 = "l";
+    const char *src4 = "Hell";
+    const char *src5 = "Helo";
+
+    AppData src1_app{ dummy_exec_env.get(), src1 };
+    AppData src2_app{ dummy_exec_env.get(), src2 };
+    AppData src3_app{ dummy_exec_env.get(), src3 };
+    AppData src4_app{ dummy_exec_env.get(), src4 };
+    AppData src5_app{ dummy_exec_env.get(), src5 };
+
+    EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
+                        (char *)src2_app.get_native_addr()),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
+                        (char *)src3_app.get_native_addr()),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
+                        (char *)src4_app.get_native_addr()),
+              4);
+
+    EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(),
+                        (char *)src5_app.get_native_addr()),
+              5);
+}
+
+TEST_F(LibcBuiltinTest, strcspn)
+{
+    const char *src1 = "Hello world!";
+    const char *src2 = ".?";
+    const char *src3 = "llo";
+    const char *src4 = "http://www.baidu.com/";
+    const char *src5 = "?.,:\"\'-!";
+
+    AppData src1_app{ dummy_exec_env.get(), src1 };
+    AppData src2_app{ dummy_exec_env.get(), src2 };
+    AppData src3_app{ dummy_exec_env.get(), src3 };
+    AppData src4_app{ dummy_exec_env.get(), src4 };
+    AppData src5_app{ dummy_exec_env.get(), src5 };
+
+    EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(),
+                        (char *)src2_app.get_native_addr()),
+              12);
+
+    EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(),
+                        (char *)src3_app.get_native_addr()),
+              2);
+
+    EXPECT_EQ(CALL_FUNC(strcspn, (char *)src4_app.get_native_addr(),
+                        (char *)src5_app.get_native_addr()),
+              4);
+}
+
+TEST_F(LibcBuiltinTest, strstr)
+{
+    const char *src1 = "Hello world!";
+    const char *src2 = "abcd";
+    const char *src3 = "Hello";
+    const char *src4 = "H";
+    const char *src5 = "llo";
+
+    AppData src1_app{ dummy_exec_env.get(), src1 };
+    AppData src2_app{ dummy_exec_env.get(), src2 };
+    AppData src3_app{ dummy_exec_env.get(), src3 };
+    AppData src4_app{ dummy_exec_env.get(), src4 };
+    AppData src5_app{ dummy_exec_env.get(), src5 };
+
+    EXPECT_EQ(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(),
+                        (char *)src2_app.get_native_addr()),
+              0);
+
+    EXPECT_EQ(CALL_FUNC(strstr, (char *)src3_app.get_native_addr(),
+                        (char *)src1_app.get_native_addr()),
+              0);
+
+    EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(),
+                        (char *)src4_app.get_native_addr()),
+              0);
+
+    EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(),
+                        (char *)src5_app.get_native_addr()),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, isupper)
+{
+    EXPECT_FALSE(CALL_FUNC(isupper, 'a'));
+
+    EXPECT_FALSE(CALL_FUNC(isupper, 97));
+
+    EXPECT_FALSE(CALL_FUNC(isupper, '0'));
+
+    EXPECT_FALSE(CALL_FUNC(isupper, '.'));
+
+    EXPECT_TRUE(CALL_FUNC(isupper, 'A'));
+
+    EXPECT_TRUE(CALL_FUNC(isupper, 65));
+}
+
+TEST_F(LibcBuiltinTest, isalpha)
+{
+    EXPECT_FALSE(CALL_FUNC(isalpha, '0'));
+
+    EXPECT_FALSE(CALL_FUNC(isalpha, 0));
+
+    EXPECT_FALSE(CALL_FUNC(isalpha, '?'));
+
+    EXPECT_TRUE(CALL_FUNC(isalpha, 'A'));
+
+    EXPECT_TRUE(CALL_FUNC(isalpha, 'a'));
+}
+
+TEST_F(LibcBuiltinTest, isspace)
+{
+    EXPECT_FALSE(CALL_FUNC(isspace, '0'));
+
+    EXPECT_FALSE(CALL_FUNC(isspace, 0));
+
+    EXPECT_FALSE(CALL_FUNC(isspace, '?'));
+
+    EXPECT_TRUE(CALL_FUNC(isspace, ' '));
+    EXPECT_TRUE(CALL_FUNC(isspace, '\t'));
+    EXPECT_TRUE(CALL_FUNC(isspace, '\n'));
+    EXPECT_TRUE(CALL_FUNC(isspace, '\v'));
+    EXPECT_TRUE(CALL_FUNC(isspace, '\f'));
+    EXPECT_TRUE(CALL_FUNC(isspace, '\r'));
+}
+
+TEST_F(LibcBuiltinTest, isgraph)
+{
+    /* ASCII 0x00-0x20 */
+    EXPECT_FALSE(CALL_FUNC(isgraph, 0x00));
+    EXPECT_FALSE(CALL_FUNC(isgraph, 0x20));
+
+    /* ASCII 0x7F */
+    EXPECT_FALSE(CALL_FUNC(isgraph, 0x7F));
+    EXPECT_FALSE(CALL_FUNC(isgraph, 0x80));
+
+    /* ASCII 0x21-0x7E */
+    EXPECT_TRUE(CALL_FUNC(isgraph, 0x21));
+    EXPECT_TRUE(CALL_FUNC(isgraph, 0x7E));
+}
+
+TEST_F(LibcBuiltinTest, isprint)
+{
+    /* ASCII 0x00-0x1F */
+    EXPECT_FALSE(CALL_FUNC(isprint, 0x00));
+    EXPECT_FALSE(CALL_FUNC(isprint, 0x1F));
+
+    /* ASCII 0x7F */
+    EXPECT_FALSE(CALL_FUNC(isprint, 0x7F));
+    EXPECT_FALSE(CALL_FUNC(isprint, 0x80));
+
+    /* ASCII 0x20-0x7E */
+    EXPECT_TRUE(CALL_FUNC(isprint, 0x20));
+    EXPECT_TRUE(CALL_FUNC(isprint, 0x7E));
+}
+
+TEST_F(LibcBuiltinTest, isdigit)
+{
+    /* ASCII 0x00-0x2F */
+    EXPECT_FALSE(CALL_FUNC(isdigit, 0x00));
+    EXPECT_FALSE(CALL_FUNC(isdigit, 0x2F));
+
+    /* ASCII 0x3A-0x7F */
+    EXPECT_FALSE(CALL_FUNC(isdigit, 0x3A));
+    EXPECT_FALSE(CALL_FUNC(isdigit, 0x7F));
+
+    /* ASCII 0x30-0x39 */
+    EXPECT_TRUE(CALL_FUNC(isdigit, 0x30));
+    EXPECT_TRUE(CALL_FUNC(isdigit, 0x39));
+}
+
+TEST_F(LibcBuiltinTest, isxdigit)
+{
+    char str[] = "-FFEE";
+    char str1[] = "FFEE";
+
+    EXPECT_FALSE(CALL_FUNC(isxdigit, str[0]));
+    EXPECT_TRUE(CALL_FUNC(isxdigit, str1[0]));
+
+    /* ASCII 0x00-0x2F */
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x00));
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x2F));
+
+    /* ASCII 0x3A-0x40 */
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x3A));
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x40));
+
+    /* ASCII 0x49-0x60 */
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x49));
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x60));
+
+    /* ASCII 0x67-0x7F */
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x67));
+    EXPECT_FALSE(CALL_FUNC(isxdigit, 0x7F));
+
+    /* ASCII 0x30-0x39 */
+    EXPECT_TRUE(CALL_FUNC(isxdigit, 0x30));
+    EXPECT_TRUE(CALL_FUNC(isxdigit, 0x39));
+
+    /* ASCII 0x41-0x46 */
+    EXPECT_TRUE(CALL_FUNC(isxdigit, 0x41));
+    EXPECT_TRUE(CALL_FUNC(isxdigit, 0x46));
+
+    /* ASCII 0x61-0x66 */
+    EXPECT_TRUE(CALL_FUNC(isxdigit, 0x61));
+    EXPECT_TRUE(CALL_FUNC(isxdigit, 0x66));
+}
+
+TEST_F(LibcBuiltinTest, tolower)
+{
+    char src[] = "aBcDeFgH12345;!#$";
+    char dest[sizeof(src)];
+    int i;
+
+    for (i = 0; i < sizeof(src); i++) {
+        dest[i] = CALL_FUNC(tolower, (src[i]));
+    }
+    EXPECT_STREQ(dest, "abcdefgh12345;!#$");
+}
+
+TEST_F(LibcBuiltinTest, toupper)
+{
+    char src[] = "aBcDeFgH12345;!#$";
+    char dest[sizeof(src)];
+    int i;
+
+    for (i = 0; i < sizeof(src); i++) {
+        dest[i] = CALL_FUNC(toupper, (src[i]));
+    }
+    EXPECT_STREQ(dest, "ABCDEFGH12345;!#$");
+}
+
+TEST_F(LibcBuiltinTest, isalnum)
+{
+    char src[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678"
+                 "9!\"#$%&'()*+,-./:;<=>?@[^_'{|}~";
+    int i;
+    int isalnum_cnt = 0;
+
+    for (i = 0; i < sizeof(src); i++) {
+        if (CALL_FUNC(isalnum, (src[i])))
+            isalnum_cnt++;
+    }
+    EXPECT_EQ(isalnum_cnt, 62);
+}
+
+TEST_F(LibcBuiltinTest, emscripten_memcpy_big)
+{
+    const char *src = "Hell World";
+    char *dest;
+
+    AppData src_app{ dummy_exec_env.get(), src };
+    AppData dest_app{ dummy_exec_env.get(), dest };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(emscripten_memcpy_big, (void *)-1,
+                        src_app.get_native_addr(), 0),
+              0);
+
+    CALL_FUNC(emscripten_memcpy_big, dest_app.get_native_addr(),
+              src_app.get_native_addr(), strlen(src));
+    EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(),
+                        src_app.get_native_addr(), strlen(src)),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, abort)
+{
+    CALL_FUNC(abort, 33);
+    EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.abort(33)");
+    dummy_exec_env.clear_exception();
+}
+
+TEST_F(LibcBuiltinTest, abortStackOverflow)
+{
+    CALL_FUNC(abortStackOverflow, 33);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: env.abortStackOverflow(33)");
+    dummy_exec_env.clear_exception();
+}
+
+TEST_F(LibcBuiltinTest, nullFunc_X)
+{
+    CALL_FUNC(nullFunc_X, 33);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: env.nullFunc_X(33)");
+    dummy_exec_env.clear_exception();
+}
+
+TEST_F(LibcBuiltinTest, __cxa_allocate_exception)
+{
+    EXPECT_NE(CALL_FUNC(__cxa_allocate_exception, 0x0), 0x0);
+    EXPECT_EQ(CALL_FUNC(__cxa_allocate_exception, 0xFFFF), 0x0);
+}
+
+TEST_F(LibcBuiltinTest, __cxa_begin_catch)
+{
+    /* 无函数原型 */
+}
+
+TEST_F(LibcBuiltinTest, __cxa_throw)
+{
+    void *excepton;
+    void *tinfo;
+
+    CALL_FUNC(__cxa_throw, excepton, tinfo, 1);
+    EXPECT_STREQ(dummy_exec_env.get_exception(),
+                 "Exception: exception thrown by stdc++");
+    dummy_exec_env.clear_exception();
+}
+
+struct timespec_app app;
+TEST_F(LibcBuiltinTest, clock_gettime)
+{
+    struct timespec_app *tsapp;
+    tsapp = &app;
+
+    AppMemory tsapp_app{ dummy_exec_env.get(), sizeof(struct timespec_app) };
+
+    /* exception */
+    EXPECT_EQ(CALL_FUNC(clock_gettime, 0, (struct timespec_app *)-1), -1);
+
+    EXPECT_EQ(CALL_FUNC(clock_gettime, 100, NULL), -1);
+
+    EXPECT_EQ(CALL_FUNC(clock_gettime, 100, 0), -1);
+
+    EXPECT_EQ(CALL_FUNC(clock_gettime, 10,
+                        (struct timespec_app *)tsapp_app.get_native_addr()),
+              0);
+}
+
+TEST_F(LibcBuiltinTest, clock)
+{
+    EXPECT_GE(CALL_FUNC(clock), 0);
+}
+
+WASMGlobalImport glb;
+TEST_F(LibcBuiltinTest, wasm_native_lookup_libc_builtin_global)
+{
+    const char *module_name = "module name";
+    const char *global_name = "global name";
+
+    const char *module_name1 = "global";
+    const char *global_name1 = "NaN";
+    const char *global_name2 = "Infinity";
+    WASMGlobalImport *global = &glb;
+
+    EXPECT_FALSE(
+        wasm_native_lookup_libc_builtin_global(NULL, global_name, global));
+    EXPECT_FALSE(
+        wasm_native_lookup_libc_builtin_global(module_name, NULL, global));
+    EXPECT_FALSE(
+        wasm_native_lookup_libc_builtin_global(module_name, global_name, NULL));
+    EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name,
+                                                        global_name, global));
+    EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name,
+                                                        global_name1, global));
+
+    EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1,
+                                                       global_name1, global));
+
+    EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1,
+                                                       global_name2, global));
+}

+ 78 - 0
tests/unit/linear-memory-aot/CMakeLists.txt

@@ -0,0 +1,78 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-linear-memory-aot)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 0)
+set (WAMR_BUILD_MEMORY_PROFILING 1)
+set (WAMR_BUILD_INTERP 0)
+set (WAMR_BUILD_AOT 1)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+    ${UNIT_SOURCE}
+    ${WAMR_RUNTIME_LIB_SOURCE}
+    ${UNCOMMON_SHARED_SOURCE}
+    ${SRC_LIST}
+    ${PLATFORM_SHARED_SOURCE}
+    ${UTILS_SHARED_SOURCE}
+    ${MEM_ALLOC_SHARED_SOURCE}
+    ${LIB_HOST_AGENT_SOURCE}
+    ${NATIVE_INTERFACE_SOURCE}
+    ${LIBC_BUILTIN_SOURCE}
+    ${IWASM_COMMON_SOURCE}
+    ${IWASM_INTERP_SOURCE}
+    ${IWASM_AOT_SOURCE}
+    ${IWASM_COMPL_SOURCE}
+    ${WASM_APP_LIB_SOURCE_ALL}
+)
+
+# Test case: .aot file with hardware bound check.
+add_executable (linear_memory_test_aot ${unit_test_sources})
+target_link_libraries (linear_memory_test_aot gtest_main)
+gtest_discover_tests(linear_memory_test_aot)
+target_compile_definitions(linear_memory_test_aot PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0)
+
+# Ensure that aot compiled is completed before linear_memory_test_aot is built
+set(dummy_output "${CMAKE_CURRENT_BINARY_DIR}/dummy_output")
+
+add_custom_command(OUTPUT ${dummy_output}
+  COMMAND ./build_aot.sh
+  COMMAND ${CMAKE_COMMAND} -E touch ${dummy_output}
+  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/build_aot.sh
+  COMMENT "Executing script to compile aot files"
+  VERBATIM
+)
+
+add_custom_target(
+  RunBuildAot ALL
+  DEPENDS ${dummy_output}
+)
+
+add_dependencies(linear_memory_test_aot RunBuildAot)
+
+add_custom_command(TARGET linear_memory_test_aot POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy
+  ${CMAKE_CURRENT_SOURCE_DIR}/build/*.aot
+  ${CMAKE_CURRENT_BINARY_DIR}
+  COMMENT "Copy aot files to the directory: build/linear-memory-aot."
+)
+
+# Test case: .aot file with no hardware bound check.
+add_executable (linear_memory_test_aot_no_hw_bound ${unit_test_sources})
+target_link_libraries (linear_memory_test_aot_no_hw_bound gtest_main)
+gtest_discover_tests(linear_memory_test_aot_no_hw_bound)
+target_compile_definitions(linear_memory_test_aot_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1)

+ 45 - 0
tests/unit/linear-memory-aot/build_aot.sh

@@ -0,0 +1,45 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+# Define a list of .wasm files
+file_names=("mem_grow_out_of_bounds_01" "mem_grow_out_of_bounds_02"
+    "mem_page_01" "mem_page_02" "mem_page_03" "mem_page_05"
+    "mem_page_07" "mem_page_08" "mem_page_09" "mem_page_10"
+    "mem_page_12" "mem_page_14" "mem_page_16" "mem_page_20" "out_of_bounds")
+
+WORKDIR="$PWD"
+WAMRC_ROOT_DIR="${WORKDIR}/../../../wamr-compiler"
+WAMRC="${WAMRC_ROOT_DIR}/build/wamrc"
+WAST2WASM="/opt/wabt/bin/wat2wasm"
+
+# build wamrc if not exist
+if [ ! -s "$WAMRC" ]; then
+    cd $WAMRC_ROOT_DIR
+    if [ -d "$WAMRC/build" ]; then
+        rm -r build 
+    fi
+    cmake -B build && cmake --build build -j $(nproc)
+    cd $WORKDIR
+fi
+
+# error if not exist
+if [ ! -s "$WAST2WASM" ]; then
+    echo "please install wabt first" && exit -1
+fi
+
+# Iterate over the files array
+rm -r build 
+mkdir build
+for file_name in "${file_names[@]}"; do
+    # wast to wasm
+    $WAST2WASM "${file_name}.wast" -o "build/${file_name}.wasm"
+    # compile the aot files, x86-64, x86-32, no_hw_bounds, no_hw_bounds_x32
+    $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm"
+    $WAMRC --target=i386 -o "build/${file_name}_32.aot" "build/${file_name}.wasm"
+    $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm"
+    $WAMRC --bounds-checks=1 --target=i386 -o "build/${file_name}_no_hw_bounds_32.aot" "build/${file_name}.wasm"
+done

+ 361 - 0
tests/unit/linear-memory-aot/linear_memory_aot_test.cc

@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "wasm_runtime_common.h"
+
+static std::string CWD;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+#if WASM_DISABLE_HW_BOUND_CHECK != 0
+#define TEST_SUITE_NAME linear_memory_test_suite_aot_no_hw_bound
+#else
+#define TEST_SUITE_NAME linear_memory_test_suite_aot
+#endif
+
+class TEST_SUITE_NAME : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase() { CWD = get_binary_path(); }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+struct ret_env {
+    wasm_exec_env_t exec_env;
+    wasm_module_t aot_module;
+    wasm_module_inst_t aot_module_inst;
+    unsigned char *aot_file_buf;
+    char error_buf[128];
+};
+
+struct ret_env
+load_aot(char *aot_file_tested, unsigned int app_heap_size)
+{
+    std::string aot_mem_page = aot_file_tested;
+    const char *aot_file = strdup((CWD + aot_mem_page).c_str());
+    wasm_module_inst_t aot_module_inst = nullptr;
+    wasm_module_t aot_module = nullptr;
+    wasm_exec_env_t exec_env = nullptr;
+    unsigned char *aot_file_buf = nullptr;
+    unsigned int aot_file_size = 0;
+    unsigned int stack_size = 16 * 1024, heap_size = app_heap_size;
+    char error_buf[128] = { 0 };
+    struct ret_env ret_module_env;
+
+    memset(ret_module_env.error_buf, 0, 128);
+    aot_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(aot_file, &aot_file_size);
+    if (!aot_file_buf) {
+        goto fail;
+    }
+
+    aot_module = wasm_runtime_load(aot_file_buf, aot_file_size, error_buf,
+                                   sizeof(error_buf));
+    if (!aot_module) {
+        memcpy(ret_module_env.error_buf, error_buf, 128);
+        goto fail;
+    }
+
+    aot_module_inst = wasm_runtime_instantiate(
+        aot_module, stack_size, heap_size, error_buf, sizeof(error_buf));
+    if (!aot_module_inst) {
+        memcpy(ret_module_env.error_buf, error_buf, 128);
+        goto fail;
+    }
+
+    exec_env = wasm_runtime_create_exec_env(aot_module_inst, stack_size);
+
+fail:
+    ret_module_env.exec_env = exec_env;
+    ret_module_env.aot_module = aot_module;
+    ret_module_env.aot_module_inst = aot_module_inst;
+    ret_module_env.aot_file_buf = aot_file_buf;
+
+    return ret_module_env;
+}
+
+void
+destroy_module_env(struct ret_env module_env)
+{
+    if (module_env.exec_env) {
+        wasm_runtime_destroy_exec_env(module_env.exec_env);
+    }
+
+    if (module_env.aot_module_inst) {
+        wasm_runtime_deinstantiate(module_env.aot_module_inst);
+    }
+
+    if (module_env.aot_module) {
+        wasm_runtime_unload(module_env.aot_module);
+    }
+
+    if (module_env.aot_file_buf) {
+        wasm_runtime_free(module_env.aot_file_buf);
+    }
+}
+
+TEST_F(TEST_SUITE_NAME, test_aot_mem_page_count)
+{
+    struct ret_env tmp_module_env;
+    const unsigned int num_normal_aot = 9;
+    const unsigned int num_error_aot = 2;
+
+#if UINTPTR_MAX == UINT64_MAX
+    const char *aot_file_normal[num_normal_aot] = {
+        "/mem_page_01.aot", "/mem_page_02.aot", "/mem_page_05.aot",
+        "/mem_page_07.aot", "/mem_page_08.aot", "/mem_page_09.aot",
+        "/mem_page_10.aot", "/mem_page_12.aot", "/mem_page_14.aot"
+    };
+
+    const char *aot_file_error[num_error_aot] = { "/mem_page_03.aot",
+                                                  "/mem_page_16.aot" };
+#else
+    const char *aot_file_normal[num_normal_aot] = {
+        "/mem_page_01_32.aot", "/mem_page_02_32.aot", "/mem_page_05_32.aot",
+        "/mem_page_07_32.aot", "/mem_page_08_32.aot", "/mem_page_09_32.aot",
+        "/mem_page_10_32.aot", "/mem_page_12_32.aot", "/mem_page_14_32.aot"
+    };
+
+    const char *aot_file_error[num_error_aot] = { "/mem_page_03_32.aot",
+                                                  "/mem_page_16_32.aot" };
+#endif
+
+    // Test normal wasm file.
+    for (int i = 0; i < num_normal_aot; i++) {
+#if UINTPTR_MAX != UINT64_MAX
+        // 32 bit do not load this wasm.
+        if ((0 == strcmp("/mem_page_14_32.aot", aot_file_normal[i]))) {
+            continue;
+        }
+#endif
+
+        tmp_module_env = load_aot((char *)aot_file_normal[i], 16 * 1024);
+        EXPECT_NE(nullptr, tmp_module_env.aot_module);
+        EXPECT_NE(nullptr, tmp_module_env.aot_file_buf);
+
+        destroy_module_env(tmp_module_env);
+    }
+
+    // Test error wasm file.
+    for (int i = 0; i < num_error_aot; i++) {
+        tmp_module_env = load_aot((char *)aot_file_error[i], 16 * 1024);
+        if (0 != strlen(tmp_module_env.error_buf)) {
+            /* 3 and 16 are for legit for loader, the init and max page count
+             * can be 65536, but they can't allocate any host managed heap, so
+             * instantiating errors  */
+            EXPECT_EQ(0, strncmp("AOT module instantiate failed",
+                                 (const char *)tmp_module_env.error_buf, 29));
+            printf("%s\n", tmp_module_env.error_buf);
+        }
+
+        destroy_module_env(tmp_module_env);
+    }
+}
+
+TEST_F(TEST_SUITE_NAME, test_aot_about_app_heap)
+{
+    struct ret_env tmp_module_env;
+
+    // Test case: init_page_count = 65536, app heap size = 1.
+#if UINTPTR_MAX == UINT64_MAX
+    tmp_module_env = load_aot((char *)"/mem_page_03.aot", 1);
+#else
+    tmp_module_env = load_aot((char *)"/mem_page_03_32.aot", 1);
+#endif
+    EXPECT_EQ(
+        0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10));
+    destroy_module_env(tmp_module_env);
+
+    // Test case: init_page_count = 65535, app heap size = 65537.
+#if UINTPTR_MAX == UINT64_MAX
+    tmp_module_env = load_aot((char *)"/mem_page_20.aot", 65537);
+#else
+    tmp_module_env = load_aot((char *)"/mem_page_20_32.aot", 65537);
+#endif
+    EXPECT_EQ(
+        0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10));
+    destroy_module_env(tmp_module_env);
+}
+
+TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds)
+{
+    struct ret_env tmp_module_env;
+    WASMFunctionInstanceCommon *func = nullptr;
+    bool ret = false;
+    uint32 argv[1] = { 9999 * 64 * 1024 };
+    const char *exception = nullptr;
+
+    /* TODO: use no_hw_bounds version when disable */
+#if UINTPTR_MAX == UINT64_MAX
+    tmp_module_env = load_aot((char *)"/out_of_bounds.aot", 16 * 1024);
+#else
+    tmp_module_env = load_aot((char *)"/out_of_bounds_32.aot", 16 * 1024);
+#endif
+    func = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, "load");
+    if (!func) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+    }
+
+    exception = wasm_runtime_get_exception(tmp_module_env.aot_module_inst);
+    EXPECT_EQ(0,
+              strncmp("Exception: out of bounds memory access", exception, 38));
+
+failed_out_of_bounds:
+    destroy_module_env(tmp_module_env);
+}
+
+TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds)
+{
+    struct ret_env tmp_module_env;
+    WASMFunctionInstanceCommon *func_mem_grow = nullptr;
+    WASMFunctionInstanceCommon *func_mem_size = nullptr;
+    bool ret = false;
+    uint32 argv[1] = { 65535 };
+    const char *exception = nullptr;
+
+    /* TODO: use no_hw_bounds version when disable */
+    // Test case: module((memory 2)), memory.grow 65535, then memory.size.
+#if UINTPTR_MAX == UINT64_MAX
+    tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01.aot", 0);
+#else
+    tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01_32.aot", 0);
+#endif
+
+    func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst,
+                                                 "mem_grow");
+    if (!func_mem_grow) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst,
+                                                 "mem_size");
+    if (!func_mem_size) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+    EXPECT_EQ(-1, argv[0]);
+
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+    EXPECT_EQ(2, argv[0]);
+
+    // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65534,
+    // memory.grow 1.
+    destroy_module_env(tmp_module_env);
+
+#if UINTPTR_MAX == UINT64_MAX
+    tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_02.aot", 32768);
+#else
+    tmp_module_env =
+        load_aot((char *)"/mem_grow_out_of_bounds_02_32.aot", 32768);
+#endif
+
+    func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst,
+                                                 "mem_grow");
+    if (!func_mem_grow) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst,
+                                                 "mem_size");
+    if (!func_mem_size) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+    EXPECT_EQ(2, argv[0]);
+
+    argv[0] = 65534;
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+#if UINTPTR_MAX == UINT64_MAX
+    EXPECT_EQ(2, argv[0]);
+#else
+    EXPECT_EQ(-1, argv[0]);
+#endif
+
+    argv[0] = 1;
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+#if UINTPTR_MAX == UINT64_MAX
+    EXPECT_EQ(-1, argv[0]);
+#else
+    EXPECT_EQ(2, argv[0]);
+#endif
+
+failed_out_of_bounds:
+    destroy_module_env(tmp_module_env);
+}

+ 16 - 0
tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast

@@ -0,0 +1,16 @@
+(module
+  (type $0 (func (result i32)))
+  (type $1 (func (param i32) (result i32)))
+  (memory 2)
+  (export "mem_grow" (func $6))
+  (export "mem_size" (func $7))
+ 
+  (func $6 (type $1) (param $0 i32) (result i32)
+    local.get $0
+    memory.grow
+    )
+
+  (func $7 (type $0) (result i32)
+    memory.size
+    )
+)

+ 16 - 0
tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast

@@ -0,0 +1,16 @@
+(module
+  (type $0 (func (result i32)))
+  (type $1 (func (param i32) (result i32)))
+  (memory 1)
+  (export "mem_grow" (func $6))
+  (export "mem_size" (func $7))
+ 
+  (func $6 (type $1) (param $0 i32) (result i32)
+    local.get $0
+    memory.grow
+    )
+
+  (func $7 (type $0) (result i32)
+    memory.size
+    )
+)

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_01.wast

@@ -0,0 +1 @@
+(module (memory 0))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_02.wast

@@ -0,0 +1 @@
+(module (memory 1))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_03.wast

@@ -0,0 +1 @@
+(module (memory 65536))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_05.wast

@@ -0,0 +1 @@
+(module (memory 0 0))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_07.wast

@@ -0,0 +1 @@
+(module (memory 1 1))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_08.wast

@@ -0,0 +1 @@
+(module (memory 0 1))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_09.wast

@@ -0,0 +1 @@
+(module (memory 1 256))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_10.wast

@@ -0,0 +1 @@
+(module (memory 0 65535))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_12.wast

@@ -0,0 +1 @@
+(module (memory 0 65536))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_14.wast

@@ -0,0 +1 @@
+(module (memory 65535 65536))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_16.wast

@@ -0,0 +1 @@
+(module (memory 65536 65536))

+ 1 - 0
tests/unit/linear-memory-aot/mem_page_20.wast

@@ -0,0 +1 @@
+(module (memory 65535))

+ 10 - 0
tests/unit/linear-memory-aot/out_of_bounds.wast

@@ -0,0 +1,10 @@
+(module
+  (type $1 (func (param i32) (result i32)))
+  (memory $3 0)
+  (export "load" (func $4))
+
+  (func $4 (type $1) (param $0 i32) (result i32)
+    local.get $0
+    i32.load
+    )
+)

+ 2 - 0
tests/unit/linear-memory-aot/readme

@@ -0,0 +1,2 @@
+build 64 bit target: cmake ..
+build 32 bit target: cmake .. -DWAMR_BUILD_TARGET=X86_32

+ 59 - 0
tests/unit/linear-memory-wasm/CMakeLists.txt

@@ -0,0 +1,59 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-linear-memory-wasm)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 0)
+set (WAMR_BUILD_MEMORY_PROFILING 1)
+set (WAMR_BUILD_INTERP 1)
+set (WAMR_BUILD_AOT 0)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+    ${UNIT_SOURCE}
+    ${WAMR_RUNTIME_LIB_SOURCE}
+    ${UNCOMMON_SHARED_SOURCE}
+    ${SRC_LIST}
+    ${PLATFORM_SHARED_SOURCE}
+    ${UTILS_SHARED_SOURCE}
+    ${MEM_ALLOC_SHARED_SOURCE}
+    ${LIB_HOST_AGENT_SOURCE}
+    ${NATIVE_INTERFACE_SOURCE}
+    ${LIBC_BUILTIN_SOURCE}
+    ${IWASM_COMMON_SOURCE}
+    ${IWASM_INTERP_SOURCE}
+    ${IWASM_AOT_SOURCE}
+    ${IWASM_COMPL_SOURCE}
+    ${WASM_APP_LIB_SOURCE_ALL}
+)
+
+# Test case: .wasm file with hardware bound check.
+add_executable (linear_memory_test_wasm ${unit_test_sources})
+target_link_libraries (linear_memory_test_wasm gtest_main)
+gtest_discover_tests(linear_memory_test_wasm)
+target_compile_definitions(linear_memory_test_wasm PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0)
+
+add_custom_command(TARGET linear_memory_test_wasm POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy
+  ${CMAKE_CURRENT_LIST_DIR}/wasm_files/*
+  ${CMAKE_CURRENT_BINARY_DIR}
+  COMMENT "Copy wasm files to the directory: build/linear-memory-wasm."
+)
+
+# Test case: .wasm file with no hardware bound check.
+add_executable (linear_memory_test_wasm_no_hw_bound ${unit_test_sources})
+target_link_libraries (linear_memory_test_wasm_no_hw_bound gtest_main)
+gtest_discover_tests(linear_memory_test_wasm_no_hw_bound)
+target_compile_definitions(linear_memory_test_wasm_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1)

+ 327 - 0
tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc

@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "wasm_runtime_common.h"
+
+static std::string CWD;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+#if WASM_DISABLE_HW_BOUND_CHECK != 0
+#define TEST_SUITE_NAME linear_memory_test_suite_wasm_no_hw_bound
+#else
+#define TEST_SUITE_NAME linear_memory_test_suite_wasm
+#endif
+
+class TEST_SUITE_NAME : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase() { CWD = get_binary_path(); }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+struct ret_env {
+    wasm_exec_env_t exec_env;
+    wasm_module_t wasm_module;
+    wasm_module_inst_t wasm_module_inst;
+    unsigned char *wasm_file_buf;
+    char error_buf[128];
+};
+
+struct ret_env
+load_wasm(char *wasm_file_tested, unsigned int app_heap_size)
+{
+    std::string wasm_mem_page = wasm_file_tested;
+    const char *wasm_file = strdup((CWD + wasm_mem_page).c_str());
+    wasm_module_inst_t wasm_module_inst = nullptr;
+    wasm_module_t wasm_module = nullptr;
+    wasm_exec_env_t exec_env = nullptr;
+    unsigned char *wasm_file_buf = nullptr;
+    unsigned int wasm_file_size = 0;
+    unsigned int stack_size = 16 * 1024, heap_size = app_heap_size;
+    char error_buf[128] = { 0 };
+    struct ret_env ret_module_env;
+
+    memset(ret_module_env.error_buf, 0, 128);
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    if (!wasm_file_buf) {
+        goto fail;
+    }
+
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    if (!wasm_module) {
+        memcpy(ret_module_env.error_buf, error_buf, 128);
+        goto fail;
+    }
+
+    wasm_module_inst = wasm_runtime_instantiate(
+        wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf));
+    if (!wasm_module_inst) {
+        memcpy(ret_module_env.error_buf, error_buf, 128);
+        goto fail;
+    }
+
+    exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size);
+
+fail:
+    ret_module_env.exec_env = exec_env;
+    ret_module_env.wasm_module = wasm_module;
+    ret_module_env.wasm_module_inst = wasm_module_inst;
+    ret_module_env.wasm_file_buf = wasm_file_buf;
+
+    return ret_module_env;
+}
+
+void
+destroy_module_env(struct ret_env module_env)
+{
+    if (module_env.exec_env) {
+        wasm_runtime_destroy_exec_env(module_env.exec_env);
+    }
+
+    if (module_env.wasm_module_inst) {
+        wasm_runtime_deinstantiate(module_env.wasm_module_inst);
+    }
+
+    if (module_env.wasm_module) {
+        wasm_runtime_unload(module_env.wasm_module);
+    }
+
+    if (module_env.wasm_file_buf) {
+        wasm_runtime_free(module_env.wasm_file_buf);
+    }
+}
+
+TEST_F(TEST_SUITE_NAME, test_wasm_mem_page_count)
+{
+    struct ret_env tmp_module_env;
+    unsigned int num_normal_wasm = 9;
+    unsigned int num_error_wasm = 10;
+    const char *wasm_file_normal[num_normal_wasm] = {
+        "/wasm_mem_page_01.wasm", "/wasm_mem_page_02.wasm",
+        "/wasm_mem_page_05.wasm", "/wasm_mem_page_07.wasm",
+        "/wasm_mem_page_08.wasm", "/wasm_mem_page_09.wasm",
+        "/wasm_mem_page_10.wasm", "/wasm_mem_page_12.wasm",
+        "/wasm_mem_page_14.wasm"
+    };
+
+    const char *wasm_file_error[num_error_wasm] = {
+        "/wasm_mem_page_03.wasm", "/wasm_mem_page_04.wasm",
+        "/wasm_mem_page_06.wasm", "/wasm_mem_page_11.wasm",
+        "/wasm_mem_page_13.wasm", "/wasm_mem_page_15.wasm",
+        "/wasm_mem_page_16.wasm", "/wasm_mem_page_17.wasm",
+        "/wasm_mem_page_18.wasm", "/wasm_mem_page_19.wasm"
+    };
+
+    // Test normal wasm file.
+    for (int i = 0; i < num_normal_wasm; i++) {
+#if UINTPTR_MAX != UINT64_MAX
+        // 32 bit do not load this wasm.
+        if ((0 == strcmp("/wasm_mem_page_12.wasm", wasm_file_normal[i]))
+            || (0 == strcmp("/wasm_mem_page_14.wasm", wasm_file_normal[i]))) {
+            continue;
+        }
+#endif
+        tmp_module_env = load_wasm((char *)wasm_file_normal[i], 16 * 1024);
+        EXPECT_NE(nullptr, tmp_module_env.wasm_module);
+        EXPECT_NE(nullptr, tmp_module_env.wasm_file_buf);
+
+#if WASM_DISABLE_HW_BOUND_CHECK == 0
+        EXPECT_NE(nullptr, tmp_module_env.exec_env);
+        EXPECT_NE(nullptr, tmp_module_env.wasm_module_inst);
+#endif
+        destroy_module_env(tmp_module_env);
+    }
+
+    // Test error wasm file.
+    for (int i = 0; i < num_error_wasm; i++) {
+        tmp_module_env = load_wasm((char *)wasm_file_error[i], 16 * 1024);
+
+        if (0 != strlen(tmp_module_env.error_buf)) {
+            EXPECT_EQ(0, strncmp("WASM module",
+                                 (const char *)tmp_module_env.error_buf, 11));
+        }
+
+        destroy_module_env(tmp_module_env);
+    }
+}
+
+TEST_F(TEST_SUITE_NAME, test_wasm_about_app_heap)
+{
+    struct ret_env tmp_module_env;
+
+    // Test case: init_page_count = 65536, app heap size = 1.
+    tmp_module_env = load_wasm((char *)"/wasm_mem_page_03.wasm", 1);
+    EXPECT_EQ(0, strncmp("WASM module instantiate failed",
+                         (const char *)tmp_module_env.error_buf, 30));
+    destroy_module_env(tmp_module_env);
+
+    // Test case: init_page_count = 65535, app heap size = 65537.
+    tmp_module_env = load_wasm((char *)"/wasm_mem_page_20.wasm", 65537);
+    EXPECT_EQ(0, strncmp("WASM module instantiate failed",
+                         (const char *)tmp_module_env.error_buf, 30));
+    destroy_module_env(tmp_module_env);
+}
+
+TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds)
+{
+    struct ret_env tmp_module_env;
+    WASMFunctionInstanceCommon *func = nullptr;
+    bool ret = false;
+    uint32 argv[1] = { 9999 * 64 * 1024 };
+    const char *exception = nullptr;
+
+    tmp_module_env = load_wasm((char *)"/out_of_bounds.wasm", 16 * 1024);
+    func =
+        wasm_runtime_lookup_function(tmp_module_env.wasm_module_inst, "load");
+    if (!func) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+    }
+
+    exception = wasm_runtime_get_exception(tmp_module_env.wasm_module_inst);
+    EXPECT_EQ(0,
+              strncmp("Exception: out of bounds memory access", exception, 38));
+
+failed_out_of_bounds:
+    destroy_module_env(tmp_module_env);
+}
+
+TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds)
+{
+    struct ret_env tmp_module_env;
+    WASMFunctionInstanceCommon *func_mem_grow = nullptr;
+    WASMFunctionInstanceCommon *func_mem_size = nullptr;
+    bool ret = false;
+    // after refactor, the 65536 pages to one 4G page optimization is removed
+    // the size can be 65536 now, so use 2 + 65535 to test OOB
+    uint32 argv[1] = { 65535 };
+    const char *exception = nullptr;
+
+    // Test case: module((memory 2)), memory.grow 65535, then memory.size.
+    tmp_module_env = load_wasm((char *)"/mem_grow_out_of_bounds_01.wasm", 0);
+    func_mem_grow = wasm_runtime_lookup_function(
+        tmp_module_env.wasm_module_inst, "mem_grow");
+    if (!func_mem_grow) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    func_mem_size = wasm_runtime_lookup_function(
+        tmp_module_env.wasm_module_inst, "mem_size");
+    if (!func_mem_size) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+    EXPECT_EQ(-1, argv[0]);
+
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+    EXPECT_EQ(2, argv[0]);
+
+    // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65535,
+    // memory.grow 1.
+    destroy_module_env(tmp_module_env);
+    tmp_module_env =
+        load_wasm((char *)"/mem_grow_out_of_bounds_02.wasm", 32768);
+    func_mem_grow = wasm_runtime_lookup_function(
+        tmp_module_env.wasm_module_inst, "mem_grow");
+    if (!func_mem_grow) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    func_mem_size = wasm_runtime_lookup_function(
+        tmp_module_env.wasm_module_inst, "mem_size");
+    if (!func_mem_size) {
+        printf("\nFailed to wasm_runtime_lookup_function!\n");
+        goto failed_out_of_bounds;
+    }
+
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+    EXPECT_EQ(2, argv[0]);
+
+    argv[0] = 65535;
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+    EXPECT_NE(2, argv[0]);
+
+    argv[0] = 1;
+    ret =
+        wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv);
+    if (!ret) {
+        printf("\nFailed to wasm_runtime_call_wasm!\n");
+        goto failed_out_of_bounds;
+    }
+
+    EXPECT_EQ(2, argv[0]);
+
+failed_out_of_bounds:
+    destroy_module_env(tmp_module_env);
+}

+ 16 - 0
tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast

@@ -0,0 +1,16 @@
+(module
+  (type $0 (func (result i32)))
+  (type $1 (func (param i32) (result i32)))
+  (memory 2)
+  (export "mem_grow" (func $6))
+  (export "mem_size" (func $7))
+ 
+  (func $6 (type $1) (param $0 i32) (result i32)
+    local.get $0
+    memory.grow
+    )
+
+  (func $7 (type $0) (result i32)
+    memory.size
+    )
+)

+ 16 - 0
tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast

@@ -0,0 +1,16 @@
+(module
+  (type $0 (func (result i32)))
+  (type $1 (func (param i32) (result i32)))
+  (memory 1)
+  (export "mem_grow" (func $6))
+  (export "mem_size" (func $7))
+ 
+  (func $6 (type $1) (param $0 i32) (result i32)
+    local.get $0
+    memory.grow
+    )
+
+  (func $7 (type $0) (result i32)
+    memory.size
+    )
+)

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_01.wast

@@ -0,0 +1 @@
+(module (memory 0))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_02.wast

@@ -0,0 +1 @@
+(module (memory 1))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_03.wast

@@ -0,0 +1 @@
+(module (memory 65536))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_04.wast

@@ -0,0 +1 @@
+(module (memory 65537)) ;; Should report an error.

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_05.wast

@@ -0,0 +1 @@
+(module (memory 0 0))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_06.wast

@@ -0,0 +1 @@
+(module (memory 1 0)) ;; Should report an error.

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_07.wast

@@ -0,0 +1 @@
+(module (memory 1 1))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_08.wast

@@ -0,0 +1 @@
+(module (memory 0 1))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_09.wast

@@ -0,0 +1 @@
+(module (memory 1 256))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_10.wast

@@ -0,0 +1 @@
+(module (memory 0 65535))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_11.wast

@@ -0,0 +1 @@
+(module (memory 65535 0)) ;; Should report an error.

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_12.wast

@@ -0,0 +1 @@
+(module (memory 0 65536))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_13.wast

@@ -0,0 +1 @@
+(module (memory 65536 0)) ;; Should report an error.

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_14.wast

@@ -0,0 +1 @@
+(module (memory 65535 65536))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_15.wast

@@ -0,0 +1 @@
+(module (memory 65536 65535)) ;; Should report an error.

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_16.wast

@@ -0,0 +1 @@
+(module (memory 65536 65536))

+ 1 - 0
tests/unit/linear-memory-wasm/mem_page_17.wast

@@ -0,0 +1 @@
+(module (memory 65537 65537)) ;; Should report an error.

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.