Przeglądaj źródła

Enable aarch64 support, add component test framework and test suite (#211)

and refine aot call indirect op
wenyongh 5 lat temu
rodzic
commit
01e85144f4
77 zmienionych plików z 3275 dodań i 270 usunięć
  1. 1 0
      README.md
  2. 4 1
      build-scripts/config_common.cmake
  3. 1 1
      build-scripts/runtime_lib.cmake
  4. 3 0
      core/config.h
  5. 2 0
      core/iwasm/aot/aot_loader.c
  6. 1 2
      core/iwasm/aot/aot_reloc.h
  7. 68 10
      core/iwasm/aot/aot_runtime.c
  8. 6 1
      core/iwasm/aot/aot_runtime.h
  9. 238 0
      core/iwasm/aot/arch/aot_reloc_aarch64.c
  10. 1 5
      core/iwasm/aot/arch/aot_reloc_arm.c
  11. 0 4
      core/iwasm/aot/arch/aot_reloc_thumb.c
  12. 2 0
      core/iwasm/aot/iwasm_aot.cmake
  13. 76 0
      core/iwasm/common/arch/invokeNative_aarch64.s
  14. 2 0
      core/iwasm/common/iwasm_common.cmake
  15. 11 3
      core/iwasm/common/wasm_runtime_common.c
  16. 233 233
      core/iwasm/compilation/aot_emit_function.c
  17. 16 0
      core/iwasm/compilation/aot_llvm.c
  18. 8 3
      doc/build_wamr.md
  19. 1 1
      product-mini/platforms/android/CMakeLists.txt
  20. 1 1
      product-mini/platforms/linux/CMakeLists.txt
  21. 1 1
      product-mini/platforms/zephyr/simple/CMakeLists.txt
  22. 9 1
      product-mini/platforms/zephyr/simple/build.sh
  23. 7 0
      product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf
  24. 3 0
      samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt
  25. 1 1
      samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c
  26. 3 0
      samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt
  27. 56 0
      test-tools/component_test/README.md
  28. 11 0
      test-tools/component_test/__init__.py
  29. 11 0
      test-tools/component_test/framework/__init__.py
  30. 29 0
      test-tools/component_test/framework/case_base.py
  31. 38 0
      test-tools/component_test/framework/engine.py
  32. 287 0
      test-tools/component_test/framework/framework.py
  33. 40 0
      test-tools/component_test/framework/suite.py
  34. 98 0
      test-tools/component_test/framework/test_api.py
  35. 70 0
      test-tools/component_test/framework/test_utils.py
  36. 0 0
      test-tools/component_test/harness/__init__.py
  37. 150 0
      test-tools/component_test/harness/harness_api.py
  38. 285 0
      test-tools/component_test/host-clients/src/host_app_sample.c
  39. 44 0
      test-tools/component_test/host-clients/src/makefile
  40. 7 0
      test-tools/component_test/set_dev_env.sh
  41. 151 0
      test-tools/component_test/start.py
  42. 0 0
      test-tools/component_test/suites/01-life-cycle/__init__.py
  43. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/01-install/__init__.py
  44. 94 0
      test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py
  45. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/02-request/__init__.py
  46. 73 0
      test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py
  47. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/03-event/__init__.py
  48. 67 0
      test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py
  49. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/__init__.py
  50. 80 0
      test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py
  51. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/__init__.py
  52. 70 0
      test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py
  53. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/06-timer/__init__.py
  54. 70 0
      test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py
  55. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/07-sensor/__init__.py
  56. 65 0
      test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py
  57. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/__init__.py
  58. 78 0
      test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py
  59. 0 0
      test-tools/component_test/suites/01-life-cycle/cases/__init__.py
  60. 56 0
      test-tools/component_test/suites/01-life-cycle/suite_setup.py
  61. 16 0
      test-tools/component_test/suites/01-life-cycle/test-app/01_install.c
  62. 62 0
      test-tools/component_test/suites/01-life-cycle/test-app/02_request.c
  63. 53 0
      test-tools/component_test/suites/01-life-cycle/test-app/03_event.c
  64. 66 0
      test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c
  65. 52 0
      test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c
  66. 53 0
      test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c
  67. 50 0
      test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c
  68. 76 0
      test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c
  69. 69 0
      test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c
  70. 67 0
      test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c
  71. 39 0
      test-tools/component_test/suites/01-life-cycle/test-app/build.sh
  72. 10 0
      test-tools/component_test/suites/01-life-cycle/tools/product/start.sh
  73. 9 0
      test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh
  74. 0 0
      test-tools/component_test/suites/__init__.py
  75. 19 0
      test-tools/component_test/suites/readme.txt
  76. 4 1
      wamr-compiler/CMakeLists.txt
  77. 1 1
      wamr-compiler/main.c

+ 1 - 0
README.md

@@ -37,6 +37,7 @@ The iwasm supports the following architectures:
 
 - X86-64, X86-32
 - ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested)
+- AArch64 (Cortex-A57 and Cortex-A53 are tested)
 - MIPS
 - XTENSA
 

+ 4 - 1
build-scripts/config_common.cmake

@@ -27,6 +27,9 @@ elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
     add_definitions(-DBUILD_TARGET_THUMB)
     add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
   endif ()
+elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
+  add_definitions(-DBUILD_TARGET_AARCH64)
+  add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
 elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
   add_definitions(-DBUILD_TARGET_MIPS)
 elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
@@ -40,7 +43,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
 endif ()
 
 if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-  if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+  if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
     # Add -fPIC flag if build as 64-bit
     set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
     set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")

+ 1 - 1
build-scripts/runtime_lib.cmake

@@ -31,7 +31,7 @@ endif ()
 # Set default options
 
 # Set WAMR_BUILD_TARGET, currently values supported:
-# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
 if (NOT DEFINED WAMR_BUILD_TARGET)
     if (CMAKE_SIZEOF_VOID_P EQUAL 8)
         # Build as X86_64 by default in 64-bit platform

+ 3 - 0
core/config.h

@@ -8,6 +8,7 @@
 
 #if !defined(BUILD_TARGET_X86_64) \
     && !defined(BUILD_TARGET_AMD_64) \
+    && !defined(BUILD_TARGET_AARCH64) \
     && !defined(BUILD_TARGET_X86_32) \
     && !defined(BUILD_TARGET_ARM) \
     && !defined(BUILD_TARGET_ARM_VFP) \
@@ -19,6 +20,8 @@
 #define BUILD_TARGET_X86_64
 #elif defined(__amd64__) || defined(__amd64)
 #define BUILD_TARGET_AMD_64
+#elif defined(__aarch64__)
+#define BUILD_TARGET_AARCH64
 #elif defined(__i386__) || defined(__i386) || defined(i386)
 #define BUILD_TARGET_X86_32
 #elif defined(__thumb__)

+ 2 - 0
core/iwasm/aot/aot_loader.c

@@ -140,6 +140,7 @@ GET_U64_FROM_ADDR(uint32 *addr)
 #define E_MACHINE_MIPS      8       /* MIPS R3000 big-endian */
 #define E_MACHINE_MIPS_RS3_LE  10   /* MIPS R3000 little-endian */
 #define E_MACHINE_ARM      40       /* ARM/Thumb */
+#define E_MACHINE_AARCH64  183      /* AArch64 */
 #define E_MACHINE_ARC      45       /* Argonaut RISC Core */
 #define E_MACHINE_IA_64    50       /* Intel Merced */
 #define E_MACHINE_MIPS_X   51       /* Stanford MIPS-X */
@@ -196,6 +197,7 @@ get_aot_file_target(AOTTargetInfo *target_info,
             machine_type = "i386";
             break;
         case E_MACHINE_ARM:
+        case E_MACHINE_AARCH64:
             machine_type = target_info->arch;
             break;
         case E_MACHINE_MIPS:

+ 1 - 2
core/iwasm/aot/aot_reloc.h

@@ -14,9 +14,8 @@ typedef struct {
 
 #define REG_COMMON_SYMBOLS                \
     REG_SYM(aot_set_exception_with_id),   \
-    REG_SYM(aot_get_exception),           \
-    REG_SYM(aot_is_wasm_type_equal),      \
     REG_SYM(aot_invoke_native),           \
+    REG_SYM(aot_call_indirect),           \
     REG_SYM(wasm_runtime_enlarge_memory), \
     REG_SYM(wasm_runtime_set_exception),  \
     REG_SYM(fmin),                        \

+ 68 - 10
core/iwasm/aot/aot_runtime.c

@@ -811,7 +811,7 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
     return wasm_type_equal(type1, type2);
 }
 
-void
+bool
 aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
                   uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
 {
@@ -827,18 +827,76 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
     const char *signature = NULL;
     char buf[128];
 
+    bh_assert(func_idx < aot_module->import_func_count);
+
+    import_func = aot_module->import_funcs + func_idx;
+    if (!func_ptr) {
+        snprintf(buf, sizeof(buf),
+                 "fail to call unlinked import function (%s, %s)",
+                 import_func->module_name, import_func->func_name);
+        aot_set_exception(module_inst, buf);
+        return false;
+    }
+
+    signature = import_func->signature;
+    return wasm_runtime_invoke_native(exec_env, func_ptr,
+                                      func_type, signature,
+                                      frame_lp, argc, argv_ret);
+}
+
+bool
+aot_call_indirect(WASMExecEnv *exec_env,
+                  uint32 func_type_idx, uint32 table_elem_idx,
+                  uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
+{
+    AOTModuleInstance *module_inst = (AOTModuleInstance*)
+                                     wasm_runtime_get_module_inst(exec_env);
+    AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr;
+    uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr;
+    uint32 *table_data = (uint32*)module_inst->table_data.ptr;
+    AOTFuncType *func_type = aot_module->func_types[func_type_idx];;
+    void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr;
+    uint32 table_size = module_inst->table_size;
+    uint32 func_idx, func_type_idx1;
+    AOTImportFunc *import_func;
+    const char *signature = NULL;
+    char buf[128];
+
+    if (table_elem_idx >= table_size) {
+        aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT);
+        return false;
+    }
+
+    func_idx = table_data[table_elem_idx];
+    if (func_idx == (uint32)-1) {
+        aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT);
+        return false;
+    }
+
+    func_type_idx1 = func_type_indexes[func_idx];
+    if (!aot_is_wasm_type_equal(module_inst, func_type_idx, func_type_idx1)) {
+        aot_set_exception_with_id(module_inst, EXCE_INVALID_FUNCTION_TYPE_INDEX);
+        return false;
+    }
+
     if (func_idx < aot_module->import_func_count) {
+        /* Call native function */
         import_func = aot_module->import_funcs + func_idx;
-        if (!func_ptr) {
-            snprintf(buf, sizeof(buf),
-                    "fail to call unlinked import function (%s, %s)",
-                    import_func->module_name, import_func->func_name);
-            aot_set_exception(module_inst, buf);
-            return;
-        }
         signature = import_func->signature;
     }
-    wasm_runtime_invoke_native(exec_env, func_ptr,
-                               func_type, signature, frame_lp, argc, argv_ret);
+
+    if (!(func_ptr = func_ptrs[func_idx])) {
+        bh_assert(func_idx < aot_module->import_func_count);
+        import_func = aot_module->import_funcs + func_idx;
+        snprintf(buf, sizeof(buf),
+                 "fail to call unlinked import function (%s, %s)",
+                 import_func->module_name, import_func->func_name);
+        aot_set_exception(module_inst, buf);
+        return false;
+    }
+
+    return wasm_runtime_invoke_native(exec_env, func_ptr,
+                                      func_type, signature,
+                                      frame_lp, argc, argv_ret);
 }
 

+ 6 - 1
core/iwasm/aot/aot_runtime.h

@@ -435,10 +435,15 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
 /**
  * Invoke native function from aot code
  */
-void
+bool
 aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
                   uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
 
+bool
+aot_call_indirect(WASMExecEnv *exec_env,
+                  uint32 func_type_idx, uint32 table_elem_idx,
+                  uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
+
 uint32
 aot_get_plt_table_size();
 

+ 238 - 0
core/iwasm/aot/arch/aot_reloc_aarch64.c

@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_AARCH64_ADR_PREL_PG_HI21      275
+#define R_AARCH64_ADD_ABS_LO12_NC       277
+#define R_AARCH64_CALL26                283
+
+static SymbolMap target_sym_map[] = {
+    REG_COMMON_SYMBOLS
+};
+
+static void
+set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
+{
+    if (error_buf != NULL)
+        snprintf(error_buf, error_buf_size, "%s", string);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+    *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+    return target_sym_map;
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+    char *build_target = BUILD_TARGET;
+    char *p = target_buf, *p_end;
+    snprintf(target_buf, target_buf_size, "%s", build_target);
+    p_end = p + strlen(target_buf);
+    while (p < p_end) {
+        if (*p >= 'A' && *p <= 'Z')
+            *p++ += 'a' - 'A';
+        else
+            p++;
+    }
+    if (!strcmp(target_buf, "aarch64"))
+        snprintf(target_buf, target_buf_size, "aarch64v8");
+}
+
+static uint32
+get_plt_item_size()
+{
+    /* 8*4 bytes instructions and 8 bytes symbol address */
+    return 40;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+    uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+    for (i = 0; i < num; i++) {
+        uint32 *p = (uint32*)plt;
+        *p++ = 0xd10023ff; /* sub  sp, sp, #0x8 */
+        *p++ = 0xf90003fe; /* str  x30, [sp]    */
+        *p++ = 0x100000de; /* adr  x30, #24     */
+        *p++ = 0xf94003de; /* ldr  x30, [x30]   */
+        *p++ = 0xd63f03c0; /* blr  x30          */
+        *p++ = 0xf94003fe; /* ldr  x30, [sp]    */
+        *p++ = 0x910023ff; /* add  sp, sp, #0x8 */
+        *p++ = 0xd61f03c0; /* br   x30          */
+        /* symbol addr */
+        *(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
+        p += 2;
+        plt += get_plt_item_size();
+    }
+}
+
+uint32
+get_plt_table_size()
+{
+    return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) do { \
+    int64 m = ((int64)1 << (bits - 1));      \
+    val_ext = ((int64)val ^ m) - m;          \
+} while (0)
+
+#define Page(expr) ((expr) & ~0xFFF)
+
+static bool
+check_reloc_offset(uint32 target_section_size,
+                   uint64 reloc_offset, uint32 reloc_data_size,
+                   char *error_buf, uint32 error_buf_size)
+{
+    if (!(reloc_offset < (uint64)target_section_size
+          && reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
+        set_error_buf(error_buf, error_buf_size,
+                      "AOT module load failed: invalid relocation offset.");
+        return false;
+    }
+    return true;
+}
+
+bool
+apply_relocation(AOTModule *module,
+                 uint8 *target_section_addr, uint32 target_section_size,
+                 uint64 reloc_offset, uint64 reloc_addend,
+                 uint32 reloc_type, void *symbol_addr, int32 symbol_index,
+                 char *error_buf, uint32 error_buf_size)
+{
+    switch (reloc_type) {
+        case R_AARCH64_CALL26:
+        {
+            void *S, *P = (void*)(target_section_addr + reloc_offset);
+            int64 X, A, initial_addend;
+            int32 insn, imm26;
+
+            CHECK_RELOC_OFFSET(sizeof(int32));
+
+            insn = *(int32*)P;
+            imm26 = insn & 0x3FFFFFF;
+            SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend);
+            A = initial_addend;
+            A += (int64)reloc_addend;
+
+            if (symbol_index < 0) {
+                /* Symbol address itself is an AOT function.
+                 * Apply relocation with the symbol directly.
+                 * Suppose the symbol address is in +-128MB relative
+                 * to the relocation address.
+                 */
+                S = symbol_addr;
+            }
+            else {
+                uint8 *plt;
+                if (reloc_addend > 0) {
+                     set_error_buf(error_buf, error_buf_size,
+                                   "AOT module load failed: relocate to plt table "
+                                   "with reloc addend larger than 0 is unsupported.");
+                     return false;
+                }
+                /* Symbol address is not an AOT function,
+                 * but a function of runtime or native. Its address is
+                 * beyond of the +-128MB space. Apply relocation with
+                 * the PLT which branch to the target symbol address.
+                 */
+                S = plt = (uint8*)module->code + module->code_size
+                          - get_plt_table_size()
+                          + get_plt_item_size() * symbol_index;
+            }
+
+            /* S + A - P */
+            X = (int64)S + A - (int64)P;
+
+            /* Check overflow: +-128MB */
+            if (X > (128 * BH_MB) || X < (-128 * BH_MB)) {
+                set_error_buf(error_buf, error_buf_size,
+                              "AOT module load failed: "
+                              "target address out of range.");
+                return false;
+            }
+
+            /* write the imm26 back to instruction */
+            *(int32*)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF));
+            break;
+        }
+
+        case R_AARCH64_ADR_PREL_PG_HI21:
+        {
+            void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
+            int64 X, A, initial_addend;
+            int32 insn, immhi19, immlo2, imm21;
+
+            CHECK_RELOC_OFFSET(sizeof(int32));
+
+            insn = *(int32*)P;
+            immhi19 = (insn >> 5) & 0x7FFFF;
+            immlo2 = (insn >> 29) & 0x3;
+            imm21 = (immhi19 << 2) | immlo2;
+
+            SIGN_EXTEND_TO_INT64(imm21 << 12, 33, initial_addend);
+            A = initial_addend;
+            A += (int64)reloc_addend;
+
+            /* Page(S+A) - Page(P) */
+            X = Page((int64)S + A) - Page((int64)P);
+
+            /* Check overflow: +-4GB */
+            if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) {
+                set_error_buf(error_buf, error_buf_size,
+                              "AOT module load failed: "
+                              "target address out of range.");
+                return false;
+            }
+
+            /* write the imm21 back to instruction */
+            immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
+            immlo2 = (int32)((X >> 12) & 0x3);
+            *(int32*)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5);
+
+            break;
+        }
+
+        case R_AARCH64_ADD_ABS_LO12_NC:
+        {
+            void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
+            int64 X, A, initial_addend;
+            int32 insn, imm12;
+
+            CHECK_RELOC_OFFSET(sizeof(int32));
+
+            insn = *(int32*)P;
+            imm12 = (insn >> 10) & 0xFFF;
+
+            SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
+            A = initial_addend;
+            A += (int64)reloc_addend;
+
+            /* S + A */
+            X = (int64)S + A;
+
+            /* No need to check overflow for this reloction type */
+
+            /* write the imm12 back to instruction */
+            *(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
+            break;
+        }
+
+        default:
+            if (error_buf != NULL)
+                snprintf(error_buf, error_buf_size,
+                         "Load relocation section failed: "
+                         "invalid relocation type %d.",
+                         reloc_type);
+            return false;
+    }
+
+    return true;
+}
+

+ 1 - 5
core/iwasm/aot/arch/aot_reloc_arm.c

@@ -9,10 +9,6 @@
 #define R_ARM_JMP24     29  /* PC relative 24 bit (B/BL<cond>).  */
 #define R_ARM_ABS32     2   /* Direct 32 bit */
 
-#ifndef BH_MB
-#define BH_MB 1024 * 1024
-#endif
-
 void __divdi3();
 void __udivdi3();
 void __moddi3();
@@ -163,7 +159,7 @@ init_plt_table(uint8 *plt)
         /* nop */
         *p++ = 0xe1a00000;
         /* symbol addr */
-        *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;;
+        *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;
         plt += get_plt_item_size();
     }
 }

+ 0 - 4
core/iwasm/aot/arch/aot_reloc_thumb.c

@@ -8,10 +8,6 @@
 #define R_ARM_THM_CALL  10  /* PC relative (Thumb BL and ARMv5 Thumb BLX). */
 #define R_ARM_THM_JMP24 30  /* B.W */
 
-#ifndef BH_MB
-#define BH_MB 1024 * 1024
-#endif
-
 void __divdi3();
 void __udivdi3();
 void __moddi3();

+ 2 - 0
core/iwasm/aot/iwasm_aot.cmake

@@ -13,6 +13,8 @@ if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c)
 elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c)
+elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*")
+  set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c)
 elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
   set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c)
 elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")

+ 76 - 0
core/iwasm/common/arch/invokeNative_aarch64.s

@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+        .text
+        .align  2
+        .global invokeNative
+        .type   invokeNative,function
+
+/*
+ * Arguments passed in:
+ *
+ * x0 function ptr
+ * x1 argv
+ * x2 nstacks
+ */
+
+invokeNative:
+        sub     sp, sp, #0x30
+        stp     x19, x20, [sp, #0x20] /* save the registers */
+        stp     x21, x22, [sp, #0x10]
+        stp     x23, x24, [sp, #0x0]
+
+        mov     x19, x0          /* x19 = function ptr */
+        mov     x20, x1          /* x20 = argv */
+        mov     x21, x2          /* x21 = nstacks */
+        mov     x22, sp          /* save the sp before call function */
+
+        /* Fill in float-point registers */
+        ldp     d0, d1, [x20], #16 /* d0 = argv[0], d1 = argv[1] */
+        ldp     d2, d3, [x20], #16 /* d2 = argv[2], d3 = argv[3] */
+        ldp     d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */
+        ldp     d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */
+
+        /* Fill inteter registers */
+        ldp     x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
+        ldp     x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
+        ldp     x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
+        ldp     x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */
+
+        /* Now x20 points to stack args */
+
+        /* Directly call the fucntion if no args in stack */
+        cmp     x21, #0
+        beq     call_func
+
+        /* Fill all stack args: reserve stack space and fill ony by one */
+        mov     x23, sp
+        bic     sp,  x23, #15    /* Ensure stack is 16 bytes aligned */
+        lsl     x23, x21, #3     /* x23 = nstacks * 8 */
+        add     x23, x23, #15    /* x23 = (x23 + 15) & ~15 */
+        bic     x23, x23, #15
+        sub     sp, sp, x23      /* reserved stack space for stack arguments */
+        mov     x23, sp
+
+loop_stack_args:                 /* copy stack arguments to stack */
+        cmp     x21, #0
+        beq     call_func
+        ldr     x24, [x20], #8
+        str     x24, [x23], #8
+        sub     x21, x21, #1
+        b       loop_stack_args
+
+call_func:
+        mov     x20, x30         /* save x30(lr) */
+        blr     x19
+        mov     sp, x22          /* restore sp which is saved before calling fuction*/
+
+return:
+        mov     x30,  x20              /* restore x30(lr) */
+        ldp     x19, x20, [sp, #0x20]  /* restore the registers in stack */
+        ldp     x21, x22, [sp, #0x10]
+        ldp     x23, x24, [sp, #0x0]
+        add     sp, sp, #0x30          /* restore sp */
+        ret
+

+ 2 - 0
core/iwasm/common/iwasm_common.cmake

@@ -26,6 +26,8 @@ elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
   else ()
     set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s)
   endif ()
+elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*")
+  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
 elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s)
 elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA")

+ 11 - 3
core/iwasm/common/wasm_runtime_common.c

@@ -1811,7 +1811,9 @@ fail:
                  || defined(BUILD_TARGET_MIPS) \
                  || defined(BUILD_TARGET_XTENSA) */
 
-#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
+#if defined(BUILD_TARGET_X86_64) \
+   || defined(BUILD_TARGET_AMD_64) \
+   || defined(BUILD_TARGET_AARCH64)
 typedef void (*GenericFunctionPointer)();
 int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks);
 
@@ -1832,8 +1834,12 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative;
 #define MAX_REG_INTS  4
 #else
 #define MAX_REG_FLOATS  8
+#if defined(BUILD_TARGET_AARCH64)
+#define MAX_REG_INTS  8
+#else
 #define MAX_REG_INTS  6
-#endif
+#endif /* end of defined(BUILD_TARGET_AARCH64 */
+#endif /* end of defined(_WIN32) || defined(_WIN32_) */
 
 bool
 wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
@@ -1963,4 +1969,6 @@ fail:
     return ret;
 }
 
-#endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */
+#endif /* end of defined(BUILD_TARGET_X86_64) \
+                 || defined(BUILD_TARGET_AMD_64) \
+                 || defined(BUILD_TARGET_AARCH64) */

+ 233 - 233
core/iwasm/compilation/aot_emit_function.c

@@ -8,41 +8,17 @@
 #include "aot_emit_control.h"
 #include "../aot/aot_runtime.h"
 
-/* Check whether there was exception thrown, if yes, return directly */
 static bool
-check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
+    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
     AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
-    LLVMBasicBlockRef block_curr, check_exce_succ;
-    LLVMValueRef value, cmp;
-
-    /* Load the first byte of aot_module_inst->cur_exception, and check
-       whether it is '\0'. If yes, no exception was thrown. */
-    if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
-                                 "exce_value"))
-        || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
-                                  value, I8_ZERO, "cmp"))) {
-        aot_set_last_error("llvm build icmp failed.");
-        return false;
-    }
-
-    /* Add check exection success block */
-    if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
-                                                          func_ctx->func,
-                                                          "check_exce_succ"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        return false;
-    }
-
-    block_curr = LLVMGetInsertBlock(comp_ctx->builder);
-    LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
 
     /* Create function return block if it isn't created */
     if (!func_ctx->func_return_block) {
         if (!(func_ctx->func_return_block =
-                LLVMAppendBasicBlockInContext(comp_ctx->context,
-                                              func_ctx->func,
-                                              "func_ret"))) {
+                    LLVMAppendBasicBlockInContext(comp_ctx->context,
+                                                  func_ctx->func, "func_ret"))) {
             aot_set_last_error("llvm add basic block failed.");
             return false;
         }
@@ -70,6 +46,42 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
         }
     }
 
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
+    return true;
+}
+
+/* Check whether there was exception thrown, if yes, return directly */
+static bool
+check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMBasicBlockRef block_curr, check_exce_succ;
+    LLVMValueRef value, cmp;
+
+    /* Create function return block if it isn't created */
+    if (!create_func_return_block(comp_ctx, func_ctx))
+        return false;
+
+    /* Load the first byte of aot_module_inst->cur_exception, and check
+       whether it is '\0'. If yes, no exception was thrown. */
+    if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
+                                 "exce_value"))
+        || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
+                                  value, I8_ZERO, "cmp"))) {
+        aot_set_last_error("llvm build icmp failed.");
+        return false;
+    }
+
+    /* Add check exection success block */
+    if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
+                                                          func_ctx->func,
+                                                          "check_exce_succ"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        return false;
+    }
+
+    block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
+
     LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
     /* Create condition br */
     if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
@@ -82,18 +94,59 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
     return true;
 }
 
+/* Check whether there was exception thrown, if yes, return directly */
+static bool
+check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                  LLVMValueRef res)
+{
+    LLVMBasicBlockRef block_curr, check_call_succ;
+    LLVMValueRef cmp;
+
+    /* Create function return block if it isn't created */
+    if (!create_func_return_block(comp_ctx, func_ctx))
+        return false;
+
+    if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE,
+                              res, I8_ZERO, "cmp"))) {
+        aot_set_last_error("llvm build icmp failed.");
+        return false;
+    }
+
+    /* Add check exection success block */
+    if (!(check_call_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
+                                                          func_ctx->func,
+                                                          "check_exce_succ"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        return false;
+    }
+
+    block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMMoveBasicBlockAfter(check_call_succ, block_curr);
+
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
+    /* Create condition br */
+    if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
+                         check_call_succ, func_ctx->func_return_block)) {
+        aot_set_last_error("llvm build cond br failed.");
+        return false;
+    }
+
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_call_succ);
+    return true;
+}
+
 static bool
 call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             LLVMValueRef func_idx, AOTFuncType *aot_func_type,
                             LLVMTypeRef *param_types, LLVMValueRef *param_values,
                             uint32 param_count, uint32 param_cell_num,
                             LLVMTypeRef ret_type, uint8 wasm_ret_type,
-                            LLVMValueRef *p_value_ret)
+                            LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
 {
     LLVMTypeRef func_type, func_ptr_type, func_param_types[5];
     LLVMTypeRef ret_ptr_type, elem_ptr_type;
     LLVMValueRef func, elem_idx, elem_ptr;
-    LLVMValueRef func_param_values[5], value_ret, value_ret_ptr, res;
+    LLVMValueRef func_param_values[5], value_ret = NULL, value_ret_ptr, res;
     char buf[32], *func_name = "aot_invoke_native";
     uint32 i, cell_num = 0;
 
@@ -103,7 +156,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     func_param_types[2] = INT32_PTR_TYPE;           /* frame_lp */
     func_param_types[3] = I32_TYPE;                 /* argc */
     func_param_types[4] = INT32_PTR_TYPE;           /* argv_ret */
-    if (!(func_type = LLVMFunctionType(VOID_TYPE, func_param_types, 5, false))) {
+    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) {
         aot_set_last_error("llvm add function type failed.");
         return false;
     }
@@ -198,7 +251,8 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     /* call aot_invoke_native() function */
-    if (!(LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, ""))) {
+    if (!(res = LLVMBuildCall(comp_ctx->builder, func,
+                              func_param_values, 5, "res"))) {
         aot_set_last_error("llvm build call failed.");
         return false;
     }
@@ -207,6 +261,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         /* get function return value */
         *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
 
+    *p_res = res;
     return true;
 }
 
@@ -221,7 +276,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     AOTFuncType *func_type;
     LLVMTypeRef *param_types = NULL, ret_type;
     LLVMValueRef *param_values = NULL, value_ret = NULL, func;
-    LLVMValueRef import_func_idx;
+    LLVMValueRef import_func_idx, res;
     int32 i, j = 0, param_count;
     uint64 total_size;
     uint8 wasm_ret_type;
@@ -292,13 +347,17 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type,
                                          param_types + 1, param_values + 1,
                                          param_count, param_cell_num,
-                                         ret_type, wasm_ret_type, &value_ret))
+                                         ret_type, wasm_ret_type, &value_ret, &res))
+            goto fail;
+
+        /* Check whether there was exception thrown when executing the function */
+        if (!check_call_return(comp_ctx, func_ctx, res))
             goto fail;
     }
     else {
         func = func_ctxes[func_idx - import_func_count]->func;
 
-       /* Call the function */
+        /* Call the function */
         if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
                                         param_values, (uint32)param_count + 1,
                                         (func_type->result_count > 0
@@ -309,15 +368,15 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
         /* Set calling convention for the call with the func's calling convention */
         LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func));
+
+        /* Check whether there was exception thrown when executing the function */
+        if (!check_exception_thrown(comp_ctx, func_ctx))
+            goto fail;
     }
 
     if (func_type->result_count > 0)
         PUSH(value_ret, func_type->types[func_type->param_count]);
 
-    /* Check whether there was exception thrown when executing the function */
-    if (!check_exception_thrown(comp_ctx, func_ctx))
-        goto fail;
-
     ret = true;
 fail:
     if (param_types)
@@ -327,236 +386,179 @@ fail:
   return ret;
 }
 
-bool
-aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             uint32 type_idx)
+static bool
+call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                            AOTFuncType *aot_func_type,
+                            LLVMValueRef func_type_idx, LLVMValueRef table_elem_idx,
+                            LLVMTypeRef *param_types, LLVMValueRef *param_values,
+                            uint32 param_count, uint32 param_cell_num,
+                            LLVMTypeRef ret_type, uint8 wasm_ret_type,
+                            LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
 {
-    AOTFuncType *func_type;
-    LLVMValueRef elem_idx, table_elem, func_idx, ftype_idx_ptr, ftype_idx;
-    LLVMValueRef cmp_elem_idx, cmp_func_idx, is_ftype_match, is_ftype_mismatch;
-    LLVMValueRef func, func_ptr, func_const, table_size_const, cmp_func_ptr;
-    LLVMValueRef *param_values = NULL, param_values_tmp[3], value_ret;
-    LLVMTypeRef *param_types = NULL, param_types_tmp[3], ret_type,
-                f_type, f_ptr_type;
-    LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ;
-    LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ;
-    char *func_name = "aot_is_wasm_type_equal";
-    int32 i, j = 0, param_count;
-    uint32 param_cell_num;
-    uint64 total_size;
-    uint8 wasm_ret_type;
-    bool ret;
+    LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
+    LLVMTypeRef ret_ptr_type, elem_ptr_type;
+    LLVMValueRef func, elem_idx, elem_ptr;
+    LLVMValueRef func_param_values[6], value_ret = NULL, value_ret_ptr, res = NULL;
+    char buf[32], *func_name = "aot_call_indirect";
+    uint32 i, cell_num = 0;
 
-    /* Check function type index */
-    if (type_idx >= comp_ctx->comp_data->func_type_count) {
-        aot_set_last_error("type index is overflow");
+    /* prepare function type of aot_call_indirect */
+    func_param_types[0] = comp_ctx->exec_env_type;  /* exec_env */
+    func_param_types[1] = I32_TYPE;                 /* func_type_idx */
+    func_param_types[2] = I32_TYPE;                 /* table_elem_idx */
+    func_param_types[3] = INT32_PTR_TYPE;           /* frame_lp */
+    func_param_types[4] = I32_TYPE;                 /* argc */
+    func_param_types[5] = INT32_PTR_TYPE;           /* argv_ret */
+    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 6, false))) {
+        aot_set_last_error("llvm add function type failed.");
         return false;
     }
 
-    func_type = comp_ctx->comp_data->func_types[type_idx];
-
-    param_cell_num = wasm_type_param_cell_num(func_type);
-
-    POP_I32(elem_idx);
-
-    table_size_const = I32_CONST(comp_ctx->comp_data->table_size);
-    CHECK_LLVM_CONST(table_size_const);
-
-    /* Check if (uint32)elem index >= table size */
-    if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE,
-                                       elem_idx, table_size_const,
-                                       "cmp_elem_idx"))) {
-        aot_set_last_error("llvm build icmp failed.");
-        goto fail;
-    }
-
-    /* Throw exception if elem index >= table size */
-    if (!(check_elem_idx_succ =
-                LLVMAppendBasicBlockInContext(comp_ctx->context,
-                                              func_ctx->func,
-                                              "check_elem_idx_succ"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        goto fail;
-    }
-
-    LLVMMoveBasicBlockAfter(check_elem_idx_succ,
-                            LLVMGetInsertBlock(comp_ctx->builder));
-
-    if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT,
-                             true, cmp_elem_idx, check_elem_idx_succ)))
-        goto fail;
-
-    /* Load function index */
-    if (!(table_elem = LLVMBuildInBoundsGEP(comp_ctx->builder,
-                                            func_ctx->table_base,
-                                            &elem_idx, 1, "table_elem"))) {
-        aot_set_last_error("llvm build add failed.");
-        goto fail;
-    }
+    /* prepare function pointer */
+    if (comp_ctx->is_jit_mode) {
+        if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+            aot_set_last_error("create LLVM function type failed.");
+            return false;
+        }
 
-    if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
-        aot_set_last_error("llvm build load failed.");
-        goto fail;
+        /* JIT mode, call the function directly */
+        if (!(func = I64_CONST((uint64)(uintptr_t)aot_call_indirect))
+            || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+            aot_set_last_error("create LLVM value failed.");
+            return false;
+        }
     }
-
-    /* Check if func_idx == -1 */
-    if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
-                                       func_idx, I32_NEG_ONE,
-                                       "cmp_func_idx"))) {
-        aot_set_last_error("llvm build icmp failed.");
-        goto fail;
+    else {
+        if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
+            && !(func = LLVMAddFunction(comp_ctx->module,
+                                        func_name, func_type))) {
+            aot_set_last_error("add LLVM function failed.");
+            return false;
+        }
     }
 
-    /* Throw exception if func_idx == -1 */
-    if (!(check_func_idx_succ =
-                LLVMAppendBasicBlockInContext(comp_ctx->context,
-                                              func_ctx->func,
-                                              "check_func_idx_succ"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        goto fail;
+    if (param_count > 64) {
+        aot_set_last_error("prepare native arguments failed: "
+                           "maximum 64 parameter cell number supported.");
+        return false;
     }
 
-    LLVMMoveBasicBlockAfter(check_func_idx_succ,
-                            LLVMGetInsertBlock(comp_ctx->builder));
+    /* prepare frame_lp */
+    for (i = 0; i < param_count; i++) {
+        if (!(elem_idx = I32_CONST(cell_num))
+            || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
+            aot_set_last_error("llvm add const or pointer type failed.");
+            return false;
+        }
 
-    if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNINITIALIZED_ELEMENT,
-                             true, cmp_func_idx, check_func_idx_succ)))
-        goto fail;
+        snprintf(buf, sizeof(buf), "%s%d", "elem", i);
+        if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
+                                              func_ctx->argv_buf, &elem_idx, 1, buf))
+            || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
+                                             elem_ptr_type, buf))) {
+            aot_set_last_error("llvm build bit cast failed.");
+            return false;
+        }
 
-    /* Load function type index */
-    if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
-                                               func_ctx->func_type_indexes,
-                                               &func_idx, 1,
-                                               "ftype_idx_ptr"))) {
-        aot_set_last_error("llvm build inbounds gep failed.");
-        goto fail;
-    }
+        if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) {
+            aot_set_last_error("llvm build store failed.");
+            return false;
+        }
+        LLVMSetAlignment(res, 1);
 
-    if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr,
-                                    "ftype_idx"))) {
-        aot_set_last_error("llvm build load failed.");
-        goto fail;
+        cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
     }
 
-    /* Call aot_is_type_equal() to check whether function type match */
-    param_types_tmp[0] = INT8_PTR_TYPE;
-    param_types_tmp[1] = I32_TYPE;
-    param_types_tmp[2] = I32_TYPE;
-    ret_type = INT8_TYPE;
-
-    /* Create function type */
-    if (!(f_type = LLVMFunctionType(ret_type, param_types_tmp,
-                                    3, false))) {
-        aot_set_last_error("create LLVM function type failed.");
-        goto fail;
-    }
+    if (wasm_ret_type != VALUE_TYPE_VOID) {
+        if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
+            aot_set_last_error("llvm add pointer type failed.");
+            return false;
+        }
 
-    if (comp_ctx->is_jit_mode) {
-        /* Create function type */
-        if (!(f_ptr_type = LLVMPointerType(f_type, 0))) {
-            aot_set_last_error("create LLVM function type failed.");
-            goto fail;
+        if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
+                                           ret_ptr_type, "argv_ret"))) {
+            aot_set_last_error("llvm build bit cast failed.");
+            return false;
         }
-        /* Create LLVM function with const function pointer */
-        if (!(func_const = I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal))
-            || !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) {
-            aot_set_last_error("create LLVM value failed.");
-            goto fail;
+
+        /* convert to int32 pointer */
+        if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
+                                               INT32_PTR_TYPE, "argv_ret_ptr"))) {
+            aot_set_last_error("llvm build store failed.");
+            return false;
         }
     }
     else {
-        /* Create LLVM function with external function pointer */
-        if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
-            && !(func = LLVMAddFunction(comp_ctx->module, func_name, f_type))) {
-            aot_set_last_error("add LLVM function failed.");
-            goto fail;
-        }
+        value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
     }
 
-    /* Call the aot_is_type_equal() function */
-    param_values_tmp[0] = func_ctx->aot_inst;
-    param_values_tmp[1] = I32_CONST(type_idx);
-    param_values_tmp[2] = ftype_idx;
-
-    CHECK_LLVM_CONST(param_values_tmp[1]);
-
-    if (!(is_ftype_match = LLVMBuildCall(comp_ctx->builder, func,
-                                         param_values_tmp, 3,
-                                         "is_ftype_match"))) {
-        aot_set_last_error("llvm build icmp failed.");
-        goto fail;
-    }
+    func_param_values[0] = func_ctx->exec_env;
+    func_param_values[1] = func_type_idx;
+    func_param_values[2] = table_elem_idx;
+    func_param_values[3] = func_ctx->argv_buf;
+    func_param_values[4] = I32_CONST(param_cell_num);
+    func_param_values[5] = value_ret_ptr;
 
-    if (!(is_ftype_mismatch = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
-                                            is_ftype_match, I8_ZERO,
-                                            "is_ftype_mismatch"))) {
-        aot_set_last_error("llvm build icmp failed.");
-        goto fail;
+    if (!func_param_values[4]) {
+        aot_set_last_error("llvm create const failed.");
+        return false;
     }
 
-    if (!(check_ftype_idx_succ =
-                LLVMAppendBasicBlockInContext(comp_ctx->context,
-                                              func_ctx->func,
-                                              "check_ftype_idx_success"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        goto fail;
+    /* call aot_call_indirect() function */
+    if (!(res = LLVMBuildCall(comp_ctx->builder, func,
+                              func_param_values, 6, "res"))) {
+        aot_set_last_error("llvm build call failed.");
+        return false;
     }
 
-    LLVMMoveBasicBlockAfter(check_ftype_idx_succ,
-                            LLVMGetInsertBlock(comp_ctx->builder));
+    if (wasm_ret_type != VALUE_TYPE_VOID)
+        /* get function return value */
+        *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
 
-    if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_FUNCTION_TYPE_INDEX,
-                             true, is_ftype_mismatch, check_ftype_idx_succ)))
-        goto fail;
+    *p_res = res;
+    return true;
+}
 
-    /* Load function pointer */
-    if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs,
-                                          &func_idx, 1, "func_ptr"))) {
-        aot_set_last_error("llvm build inbounds gep failed.");
-        goto fail;
-    }
+bool
+aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             uint32 type_idx)
+{
+    AOTFuncType *func_type;
+    LLVMValueRef elem_idx, ftype_idx;
+    LLVMValueRef *param_values = NULL, value_ret = NULL, res = NULL;
+    LLVMTypeRef *param_types = NULL, ret_type;
+    int32 i, param_count;
+    uint32 param_cell_num;
+    uint64 total_size;
+    uint8 wasm_ret_type;
+    bool ret;
 
-    if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) {
-        aot_set_last_error("llvm build load failed.");
-        goto fail;
+    /* Check function type index */
+    if (type_idx >= comp_ctx->comp_data->func_type_count) {
+        aot_set_last_error("type index is overflow");
+        return false;
     }
 
-    /* Check whether import function is NULL */
-    if (!(cmp_func_ptr = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) {
-        aot_set_last_error("llvm build is null failed.");
-        goto fail;
-    }
+    ftype_idx = I32_CONST(type_idx);
+    CHECK_LLVM_CONST(ftype_idx);
 
-    /* Throw exception if import function is NULL */
-    if (!(check_func_ptr_succ =
-                LLVMAppendBasicBlockInContext(comp_ctx->context,
-                                              func_ctx->func,
-                                              "check_func_ptr_succ"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        goto fail;
-    }
+    func_type = comp_ctx->comp_data->func_types[type_idx];
 
-    LLVMMoveBasicBlockAfter(check_func_ptr_succ,
-                            LLVMGetInsertBlock(comp_ctx->builder));
+    param_cell_num = wasm_type_param_cell_num(func_type);
 
-    if (!(aot_emit_exception(comp_ctx, func_ctx,
-                             EXCE_CALL_UNLINKED_IMPORT_FUNC,
-                             true, cmp_func_ptr, check_func_ptr_succ)))
-        goto fail;
+    POP_I32(elem_idx);
 
     /* Initialize parameter types of the LLVM function */
     param_count = (int32)func_type->param_count;
-    total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
+    total_size = sizeof(LLVMTypeRef) * (uint64)param_count;
     if (total_size >= UINT32_MAX
         || !(param_types = wasm_runtime_malloc((uint32)total_size))) {
         aot_set_last_error("Allocate memory failed.");
         goto fail;
     }
 
-    j = 0;
-    param_types[j++] = comp_ctx->exec_env_type;
     for (i = 0; i < param_count; i++)
-        param_types[j++] = TO_LLVM_TYPE(func_type->types[i]);
+        param_types[i] = TO_LLVM_TYPE(func_type->types[i]);
 
     /* Resolve return type of the LLVM function */
     if (func_type->result_count) {
@@ -569,32 +571,30 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     /* Allocate memory for parameters */
-    total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1);
+    total_size = sizeof(LLVMValueRef) * (uint64)param_count;
     if (total_size >= UINT32_MAX
         || !(param_values = wasm_runtime_malloc((uint32)total_size))) {
         aot_set_last_error("Allocate memory failed.");
         goto fail;
     }
 
-    /* First parameter is exec env */
-    j = 0;
-    param_values[j++] = func_ctx->exec_env;
-
     /* Pop parameters from stack */
     for (i = param_count - 1; i >= 0; i--)
-        POP(param_values[i + j], func_type->types[i]);
+        POP(param_values[i], func_type->types[i]);
 
-    if (!call_aot_invoke_native_func(comp_ctx, func_ctx, func_idx, func_type,
-                                     param_types + 1, param_values + 1,
+    if (!call_aot_call_indirect_func(comp_ctx, func_ctx,
+                                     func_type, ftype_idx, elem_idx,
+                                     param_types, param_values,
                                      param_count, param_cell_num,
-                                     ret_type, wasm_ret_type, &value_ret))
+                                     ret_type, wasm_ret_type,
+                                     &value_ret, &res))
         goto fail;
 
     if (func_type->result_count > 0)
         PUSH(value_ret, func_type->types[func_type->param_count]);
 
     /* Check whether there was exception thrown when executing the function */
-    if (!check_exception_thrown(comp_ctx, func_ctx))
+    if (!check_call_return(comp_ctx, func_ctx, res))
         goto fail;
 
     ret = true;

+ 16 - 0
core/iwasm/compilation/aot_llvm.c

@@ -741,6 +741,18 @@ static ArchItem valid_archs[] = {
     { "x86_64", false },
     { "i386", false },
     { "mips", true },
+    { "aarch64v8", false },
+    { "aarch64v8.1", false },
+    { "aarch64v8.2", false },
+    { "aarch64v8.3", false },
+    { "aarch64v8.4", false },
+    { "aarch64v8.5", false },
+    { "aarch64_bev8", false },   /* big endian */
+    { "aarch64_bev8.1", false },
+    { "aarch64_bev8.2", false },
+    { "aarch64_bev8.3", false },
+    { "aarch64_bev8.4", false },
+    { "aarch64_bev8.5", false },
     { "armv4", true },
     { "armv4t", true },
     { "armv5t", true },
@@ -939,6 +951,10 @@ aot_create_comp_context(AOTCompData *comp_data,
                 arch = "thumbv4t";
             else if (!strcmp(arch, "thumbeb"))
                 arch = "thumbv4teb";
+            else if (!strcmp(arch, "aarch64"))
+                arch = "aarch64v8";
+            else if (!strcmp(arch, "aarch64_be"))
+                arch = "aarch64_bev8";
         }
 
         /* Check target arch */

+ 8 - 3
doc/build_wamr.md

@@ -23,7 +23,7 @@ The script `runtime_lib.cmake` defined a number of variables for configuring the
 
 - **WAMR_BUILD_PLATFORM**:  set the target platform. It can be set to any platform name (folder name) under folder [core/shared/platform](../core/shared/platform). 
 
-- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets:  X86_64, X86_32, ARM, THUMB, XTENSA and MIPS. For ARM and THUMB, the format is <arch>[<sub-arch>][_VFP] where <sub-arch> is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both <sub-arch> and [_VFP] are optional. e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on.
+- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets:  X86_64, X86_32, AArch64, ARM, THUMB, XTENSA and MIPS. For AArch64, ARM and THUMB, the format is <arch>[<sub-arch>][_VFP] where <sub-arch> is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both <sub-arch> and "_VFP" are optional. e.g. AARCH64, AARCH64V8, AARCHV8.1, ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on.
 
   ```bash
   cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM  
@@ -229,6 +229,10 @@ source ../../zephyr-env.sh
 ``` Bash
 ./build.sh stm32
 ```
+3. build for AArch64 (qemu_cortex_a53)
+``` Bash
+./build.sh qemu_cortex_a53
+```
 
 Note:
 WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default.
@@ -272,6 +276,7 @@ AliOS-Things
    aos make helloworld@linuxhost -c config
    aos make
    ./out/helloworld@linuxhost/binary/helloworld@linuxhost.elf
+   ```
 ```
    
    For developerkit:
@@ -279,8 +284,8 @@ AliOS-Things
    
    ``` C
 WAMR_BUILD_TARGET := THUMBV7M
-   ```
-   
+```
+
    ``` Bash
    aos make helloworld@developerkit -c config
    aos make

+ 1 - 1
product-mini/platforms/android/CMakeLists.txt

@@ -27,7 +27,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
 set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
 
 # Set WAMR_BUILD_TARGET, currently values supported:
-# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
 if (NOT DEFINED WAMR_BUILD_TARGET)
   if (CMAKE_SIZEOF_VOID_P EQUAL 8)
     # Build as X86_64 by default in 64-bit platform

+ 1 - 1
product-mini/platforms/linux/CMakeLists.txt

@@ -12,7 +12,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
 set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
 
 # Set WAMR_BUILD_TARGET, currently values supported:
-# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
 if (NOT DEFINED WAMR_BUILD_TARGET)
   if (CMAKE_SIZEOF_VOID_P EQUAL 8)
     # Build as X86_64 by default in 64-bit platform

+ 1 - 1
product-mini/platforms/zephyr/simple/CMakeLists.txt

@@ -10,7 +10,7 @@ enable_language (ASM)
 
 set (WAMR_BUILD_PLATFORM "zephyr")
 
-# Build as X86_32 by default, change to "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA"
+# Build as X86_32 by default, change to "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA"
 # if we want to support arm, thumb, mips or xtensa
 if (NOT DEFINED WAMR_BUILD_TARGET)
   set (WAMR_BUILD_TARGET "X86_32")

+ 9 - 1
product-mini/platforms/zephyr/simple/build.sh

@@ -5,13 +5,15 @@
 
 X86_TARGET="x86"
 STM32_TARGET="stm32"
+QEMU_CORTEX_A53="qemu_cortex_a53"
 
 if [ $# != 1 ] ; then
         echo "USAGE:"
-        echo "$0 $X86_TARGET|$STM32_TARGET"
+        echo "$0 $X86_TARGET|$STM32_TARGET|$QEMU_CORTEX_A53"
         echo "Example:"
         echo "        $0 $X86_TARGET"
         echo "        $0 $STM32_TARGET"
+        echo "        $0 $QEMU_CORTEX_A53"
         exit 1
 fi
 
@@ -29,6 +31,12 @@ elif [ "$TARGET" = "$STM32_TARGET" ] ; then
         cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_TARGET=THUMBV7 ..
         ninja
         ninja flash
+elif [ "$TARGET" = "$QEMU_CORTEX_A53" ] ; then
+        cp prj_qemu_cortex_a53.conf prj.conf
+        rm -fr build && mkdir build && cd build
+        cmake -GNinja -DBOARD=qemu_cortex_a53 -DWAMR_BUILD_TARGET=AARCH64 ..
+        ninja
+        ninja run
 else
         echo "unsupported target: $TARGET"
         exit 1

+ 7 - 0
product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf

@@ -0,0 +1,7 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+CONFIG_ARM_MMU=n
+CONFIG_STACK_SENTINEL=y
+CONFIG_PRINTK=y
+CONFIG_LOG=y

+ 3 - 0
samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt

@@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr")
 
 enable_language (ASM)
 
+add_definitions(-DWA_MALLOC=wasm_runtime_malloc)
+add_definitions(-DWA_FREE=wasm_runtime_free)
+
 # Build as THUMB by default
 # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS" or "XTENSA"
 # if we want to support arm_32, x86, mips or xtensa

+ 1 - 1
samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c

@@ -345,7 +345,7 @@ static host_interface interface = { .send = uart_send, .destroy = uart_destroy }
 #endif
 
 #ifdef __x86_64__
-static char global_heap_buf[400 * 1024] = { 0 };
+static char global_heap_buf[420 * 1024] = { 0 };
 #else
 static char global_heap_buf[270 * 1024] = { 0 };
 #endif

+ 3 - 0
samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt

@@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr")
 
 enable_language (ASM)
 
+add_definitions(-DWA_MALLOC=wasm_runtime_malloc)
+add_definitions(-DWA_FREE=wasm_runtime_free)
+
 # Build as THUMB by default
 # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS_32" or "XTENSA_32"
 # if we want to support arm_32, x86, mips or xtensa

+ 56 - 0
test-tools/component_test/README.md

@@ -0,0 +1,56 @@
+# Component Test
+
+The purpose of this test suite is to verify the basic components of WAMR work well in combination. It is highly recommended to run pass all suites before each commitment.
+
+Prerequisites
+==============
+- clang is available to build wasm application.
+- python is installed to run test script.
+
+
+Run the test
+=============
+```
+start.py [-h] [-s SUITE_ID [SUITE_ID ...]] [-t CASE_ID [CASE_ID ...]]
+              [-n REPEAT_TIME] [--shuffle_all]
+              [--cases_list CASES_LIST_FILE_PATH] [--skip_proc]
+              [-b BINARIES] [-d] [--rebuild]
+```
+It builds out the simple project binary including WAMR runtime binary ```simple``` and the testing tool ```host_tool``` before running the test suites.
+
+Test output is like:
+```
+Test Execution Summary:
+        Success:              8
+        Cases fails:          0
+        Setup fails:          0
+        Case load fails:      0
+
+
+------------------------------------------------------------
+The run folder is [run-03-23-16-29]
+that's all. bye
+kill to quit..
+Killed
+```
+
+The detailed report and log is generated in ```run``` folder. The binaries copy is also put in that folder.
+
+Usage samples
+==============
+
+Run default test suite:
+</br>
+```python start.py```
+
+Rebuild all test apps and then run default test suite:
+</br>
+```python start.py --rebuild```
+
+Run a specified test suite:
+</br>
+```python start.py -s 01-life-cycle```
+
+Run a specified test case:
+</br>
+```python start.py -t 01-install```

+ 11 - 0
test-tools/component_test/__init__.py

@@ -0,0 +1,11 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+__all__ = [
+    "net_manager", "wifi_daemon_utils"
+]
+
+__author__ = ""
+__package__ = "model"
+__version__ = "1.0"

+ 11 - 0
test-tools/component_test/framework/__init__.py

@@ -0,0 +1,11 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+__all__ = [
+    "net_manager", "wifi_daemon_utils"
+]
+
+__author__ = ""
+__package__ = "model"
+__version__ = "1.0"

+ 29 - 0
test-tools/component_test/framework/case_base.py

@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import os
+import json
+from test.test_support import _run_suite
+
+class CTestCaseBase(object):
+    def __init__(self, suite):
+          self.m_suite = suite
+          return
+    def on_get_case_description(self):
+        return "Undefined"
+
+    def on_setup_case(self):
+        return True, ''
+
+    def on_cleanup_case(self):
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        return True, ''
+
+    def get_suite(self):
+        return self.m_suite
+

+ 38 - 0
test-tools/component_test/framework/engine.py

@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import datetime
+import os
+import pprint
+import random
+import re
+import shlex
+import subprocess
+import signal
+import sys
+import time
+
+from .test_utils  import *
+from .test_api import *
+
+
+
+
+def read_cases_from_file(file_path):
+    if not os.path.exists(file_path):
+        return False, None
+
+    with open(file_path, 'r') as f:
+        content = f.readlines()
+
+    content = [x.strip() for x in content]
+    print content
+    if len(content) == 0:
+        return False, None
+
+    return True, content
+
+
+

+ 287 - 0
test-tools/component_test/framework/framework.py

@@ -0,0 +1,287 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import datetime
+import os
+import pprint
+import random
+import re
+import shlex
+import subprocess
+import signal
+import sys
+import time
+import shutil
+
+from .test_api import *
+import this
+
+
+'''
+The run evironment dir structure:
+
+ run/
+      run{date-time}/
+         suites/
+               {suite name}/
+                      -- target/  (the target software being tested)
+                      -- tools/   (the tools for testing the target software)
+'''
+
+
+framework=None
+
+def get_framework():
+    global framework
+    return framework
+
+def my_import(name):
+    mod = __import__(name)
+    components = name.split('.')
+    for comp in components[1:]:
+        mod = getattr(mod, comp)
+    return mod
+
+
+# we maintain a root path apart from framework location
+# so the suites can be located in anywhere
+class CTestFramework(object):
+
+    def __init__(self,  path):
+        self.running_case = ''
+        self.running_suite = ''
+        self.target_suites = {}
+        self.target_cases = {}
+        self.root_path = path
+        self.running_folder=''
+        self.report = None
+        self.sucess_cases = 0
+        self.failed_cases = 0
+        self.setup_fails = 0
+        self.load_fails = 0;
+        global framework
+        framework = self
+
+        api_set_root_path(path)
+
+        print "root_path is " + self.root_path
+
+    def gen_execution_stats(self):
+        return '\nTest Execution Summary: '  \
+                       '\n\tSuccess:              {}'  \
+                       '\n\tCases fails:          {}' \
+                       '\n\tSetup fails:          {}' \
+                       '\n\tCase load fails:      {}'.format(
+           self.sucess_cases,  self.failed_cases, self.setup_fails, self.load_fails)
+
+    def report_result(self, success, message, case_description):
+        if self.report is None:
+            return
+
+        case_pass = "pass"
+        if not success:
+            case_pass = "fail"
+
+        self.report.write(case_pass + ": [" + self.running_case + "]\n\treason: " + \
+                          message + "\n\tcase: " + case_description + "\n")
+        return
+
+    def get_running_path(self):
+        return self.root_path + "/run/" + self.running_folder
+
+    def load_suites(self):
+        self.target_suites = os.listdir(self.root_path + "/suites")
+        return
+
+    def run_case(self, suite_instance, case):
+        # load the test case module
+        case_description = ''
+        suite = suite_instance.m_name
+        api_log("\n>>start run [" + case + "] >>")
+        module_name = 'suites.' + suite + ".cases." + case + ".case"
+        try:
+            module = my_import(module_name)
+        except Exception, e:
+            report_fail("load case fail: " + str(e))
+            api_log_error("load case fail: " + str(e))
+            self.load_fails = self.load_fails +1
+            print(traceback.format_exc())
+            return False
+
+        try:
+            case = module.CTestCase(suite_instance)
+        except Exception, e:
+            report_fail("initialize case fail: " + str(e))
+            api_log_error("initialize case fail: " + str(e))
+            self.load_fails = self.load_fails +1
+            return False
+
+        # call the case on setup callback
+        try:
+            case_description = case.on_get_case_description()
+            result, message = case.on_setup_case()
+        except Exception, e:
+            result = False
+            message = str(e);
+        if not result:
+            api_log_error(message)
+            report_fail (message, case_description)
+            self.failed_cases = self.failed_cases+1
+            return False
+
+        # call the case execution callaback
+        try:
+            result, message = case.on_run_case()
+        except Exception, e:
+            result = False
+            message = str(e);
+        if not result:
+            report_fail (message, case_description)
+            api_log_error(message)
+            self.failed_cases = self.failed_cases+1
+        else:
+            report_success(case_description)
+            self.sucess_cases = self.sucess_cases +1
+
+        # call the case cleanup callback
+        try:
+            clean_result, message = case.on_cleanup_case()
+        except Exception, e:
+            clean_result = False
+            message = str(e)
+
+        if not clean_result:
+            api_log(message)
+
+        return  result
+
+    def run_suite(self, suite, cases):
+        # suite setup
+        message = ''
+        api_log("\n>>> Suite [" + suite + "] starting >>>")
+        running_folder = self.get_running_path()+ "/suites/" + suite;
+
+        module_name = 'suites.' + suite + ".suite_setup"
+        try:
+            module = my_import(module_name)
+        except Exception, e:
+            report_fail("load suite [" + suite +"] fail: " + str(e))
+            self.load_fails = self.load_fails +1
+            return False
+
+        try:
+            suite_instance = module.CTestSuite(suite, \
+                self.root_path + '/suites/' + suite, running_folder)
+        except Exception, e:
+            report_fail("initialize suite fail: " + str(e))
+            self.load_fails = self.load_fails +1
+            return False
+
+        result, message = suite_instance.load_settings()
+        if not result:
+            report_fail("load settings fail: " + str(e))
+            self.load_fails = self.load_fails +1
+            return False
+
+        try:
+            result, message = suite_instance.on_suite_setup()
+        except Exception, e:
+            result = False
+            message = str(e);
+        if not result:
+            api_log_error(message)
+            report_fail (message)
+            self.setup_fails = self.setup_fails + 1
+            return False
+
+        self.running_suite = suite
+
+        cases.sort()
+
+        # run cases
+        for case in cases:
+            if not os.path.isdir(self.root_path + '/suites/' + suite + '/cases/' + case):
+                continue
+
+            self.running_case = case
+            self.run_case(suite_instance, case)
+            self.running_case = ''
+
+        # suites cleanup
+        self.running_suite = ''
+        try:
+            result, message = suite_instance.on_suite_cleanup()
+        except Exception, e:
+            result = False
+            message = str(e);
+        if not result:
+            api_log_error(message)
+            report_fail (message)
+            self.setup_fails = self.setup_fails + 1
+        return
+
+    def start_run(self):
+        if self.target_suites is None:
+            print "\n\nstart run: no target suites, exit.."
+            return
+
+        cur_time = time.localtime()
+        time_prefix = "{:02}-{:02}-{:02}-{:02}".format(
+            cur_time.tm_mon, cur_time.tm_mday, cur_time.tm_hour,  cur_time.tm_min)
+
+        debug = api_get_value('debug', False)
+        if debug:
+            self.running_folder = 'debug'
+        else:
+            self.running_folder = 'run-' + time_prefix
+
+        folder = self.root_path + "/run/" +self.running_folder;
+
+        if os.path.exists(folder):
+            shutil.rmtree(folder, ignore_errors=True)
+
+        if not os.path.exists(folder):
+            os.makedirs(folder )
+            os.makedirs(folder  + "/suites")
+
+        api_init_log(folder + "/test.log")
+
+        self.report = open(folder + "/report.txt", 'a')
+
+        self.target_suites.sort()
+
+        for suite in self.target_suites:
+            if not os.path.isdir(self.root_path + '/suites/' + suite):
+                continue
+            self.report.write("suite " + suite + " cases:\n")
+            if self.target_cases is None:
+                cases = os.listdir(self.root_path + "/suites/" + suite + "/cases")
+                self.run_suite(suite, cases)
+            else:
+                self.run_suite(suite, self.target_cases)
+            self.report.write("\n")
+
+        self.report.write("\n\n")
+        summary = self.gen_execution_stats()
+        self.report.write(summary);
+        self.report.flush()
+        self.report.close()
+        print summary
+
+
+def report_fail(message, case_description=''):
+    global framework
+    if framework is not None:
+        framework.report_result(False, message, case_description)
+
+    api_log_error(message)
+
+    return
+
+def report_success(case_description=''):
+    global framework
+    if framework is not None:
+        framework.report_result(True , "OK", case_description)
+    return

+ 40 - 0
test-tools/component_test/framework/suite.py

@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import os
+import json
+
+class CTestSuiteBase(object):
+    def __init__(self, name, suite_path, run_path):
+        self.suite_path=suite_path
+        self.run_path=run_path
+        self.m_name = name
+        self.settings = {}
+
+    def get_settings_item(self,  item):
+            if item in self.settings:
+                return self.settings[item]
+            else:
+                return None
+
+    def load_settings(self):
+        path = self.suite_path + "/settings.cfg"
+        if os.path.isfile(path):
+            try:
+                fp = open(path, 'r')
+                self.settings = json.load(fp)
+                fp.close()
+            except Exception, e:
+                return False, 'Load settings fail: ' + e.message
+            return True, 'OK'
+        else:
+            return True, 'No file'
+
+    def on_suite_setup(self):
+        return True, 'OK'
+
+    def on_suite_cleanup(self):
+        return True, 'OK'
+

+ 98 - 0
test-tools/component_test/framework/test_api.py

@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import logging
+import threading
+from .test_utils import *
+
+global logger
+logger = None
+
+def api_init_log(log_path):
+    global logger
+    print "api_init_log: " + log_path
+    logger = logging.getLogger(__name__)
+
+    logger.setLevel(level = logging.INFO)
+    handler = logging.FileHandler(log_path)
+    handler.setLevel(logging.INFO)
+    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
+    handler.setFormatter(formatter)
+
+    console = logging.StreamHandler()
+    console.setLevel(logging.INFO)
+
+    logger.addHandler(handler)
+    logger.addHandler(console)
+
+    return
+
+def api_log(message):
+    global logger
+    if logger is None:
+        print message
+    else:
+        logger.info (message)
+    return
+
+def api_log_error(message):
+    global logger
+    if logger is None:
+        print message
+    else:
+        logger.error (message)
+    return
+
+def api_logv(message):
+    global logger
+    if logger is None:
+        print message
+    else:
+        logger.info(message)
+    return
+
+#####################################3
+global g_case_runner_event
+def api_wait_case_event(timeout):
+    global g_case_runner_event
+    g_case_runner_event.clear()
+    g_case_runner_event.wait(timeout)
+
+def api_notify_case_runner():
+    global g_case_runner_event
+    g_case_runner_event.set()
+
+def api_create_case_event():
+    global g_case_runner_event
+    g_case_runner_event = threading.Event()
+
+#######################################
+
+def api_init_globals():
+    global _global_dict
+    _global_dict = {}
+
+def api_set_value(name, value):
+    _global_dict[name] = value
+
+def api_get_value(name, defValue=None):
+    try:
+        return _global_dict[name]
+    except KeyError:
+        return defValue
+
+
+#########################################
+global root_path
+def api_set_root_path(root):
+    global root_path
+    root_path = root
+
+def api_get_root_path():
+    global root_path
+    return root_path;
+
+
+

+ 70 - 0
test-tools/component_test/framework/test_utils.py

@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import datetime
+import os
+import random
+import re
+import shlex
+import subprocess
+import sys
+import time
+import shutil
+from subprocess import check_output, CalledProcessError
+
+def t_getPIDs(process):
+    try:
+        pidlist = map(int, check_output(["pidof", process]).split())
+    except  CalledProcessError:
+        pidlist = []
+    #print process + ':list of PIDs = ' + ', '.join(str(e) for e in pidlist)
+    return pidlist
+
+
+def t_kill_process_by_name(p_keywords):
+    pid_list = []
+    ps_info = subprocess.check_output(shlex.split("ps aux")).split("\n")
+    for p in ps_info:
+        if p_keywords in p:
+            tmp = p.split(" ")
+            tmp = [x for x in tmp if len(x) > 0]
+            pid_list.append(tmp[1])
+
+    for pid in pid_list:
+        cmd = "kill -9 {}".format(pid)
+        subprocess.call(shlex.split(cmd))
+
+    return pid_list
+
+
+
+#proc    -> name of the process
+#kill = 1  -> search for pid for kill
+#kill = 0  -> search for name (default)
+
+def t_process_exists(proc, kill = 0):
+    ret = False
+    processes  = t_getPIDs(proc)
+
+    for pid in processes:
+            if kill == 0:
+                return True
+            else:
+                print "kill [" + proc + "], pid=" + str(pid)
+                os.kill((pid), 9)
+                ret = True
+    return ret
+
+def t_copy_files(source_dir, pattern, dest_dir):
+    files = os.listdir(source_dir)
+    for file in files:
+        if file is '/' or file is '.' or file is '..':
+            continue
+
+        if pattern == '*' or pattern is '' or files.endswith(pattern):
+            shutil.copy(source_dir+"/"+ file,dest_dir)
+
+
+

+ 0 - 0
test-tools/component_test/harness/__init__.py


+ 150 - 0
test-tools/component_test/harness/harness_api.py

@@ -0,0 +1,150 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import os
+import shutil
+import subprocess
+import json
+import time
+
+from framework import test_api
+from framework.test_utils import *
+
+output = "output.txt"
+
+def start_env():
+    os.system("./start.sh")
+
+def stop_env():
+    os.system("./stop.sh")
+    time.sleep(0.5)
+    os.chdir("../") #reset path for other cases in the same suite
+
+def check_is_timeout():
+    line_num = 0
+    ft = open(output, 'r')
+    lines = ft.readlines()
+
+    for line in reversed(lines):
+        if (line[0:36] == "--------one operation begin.--------"):
+            break
+        line_num = line_num + 1
+
+    ft.close()
+    if (lines[-(line_num)] == "operation timeout"):
+        return True
+    else:
+        return False
+
+def parse_ret(file):
+    ft = open(file, 'a')
+    ft.writelines("\n")
+    ft.writelines("--------one operation finish.--------")
+    ft.writelines("\n")
+    ft.close()
+
+    ft = open(file, 'r')
+    for line in reversed(ft.readlines()):
+        if (line[0:16] == "response status "):
+            ret = line[16:]
+            ft.close()
+            return int(ret)
+
+def run_host_tool(cmd, file):
+    ft = open(file, 'a')
+    ft.writelines("--------one operation begin.--------")
+    ft.writelines("\n")
+    ft.close()
+    os.system(cmd + " -o" + file)
+    if (check_is_timeout() == True):
+        return -1
+    return parse_ret(file)
+
+def install_app(app_name, file_name):
+    return run_host_tool("./host_tool -i " + app_name + " -f ../test-app/" + file_name, output)
+
+def uninstall_app(app_name):
+    return run_host_tool("./host_tool -u " + app_name, output)
+
+def query_app():
+    return run_host_tool("./host_tool -q ", output)
+
+def send_request(url, action, payload):
+    if (payload is None):
+        return run_host_tool("./host_tool -r " + url + " -A " + action, output)
+    else:
+        return run_host_tool("./host_tool -r " + url + " -A " + action + " -p " + payload, output)
+
+def register(url, timeout, alive_time):
+    return run_host_tool("./host_tool -s " + url + " -t " + str(timeout) + " -a " + str(alive_time), output)
+
+def deregister(url):
+    return run_host_tool("./host_tool -d " + url, output)
+
+def get_response_payload():
+    line_num = 0
+    ft = open(output, 'r')
+    lines = ft.readlines()
+
+    for line in reversed(lines):
+        if (line[0:16] == "response status "):
+            break
+        line_num = line_num + 1
+
+    payload_lines = lines[-(line_num):-1]
+    ft.close()
+
+    return payload_lines
+
+def check_query_apps(expected_app_list):
+    if (check_is_timeout() == True):
+        return False
+    json_lines = get_response_payload()
+    json_str = " ".join(json_lines)
+    json_dict = json.loads(json_str)
+    app_list = []
+
+    for key, value in json_dict.items():
+        if key[0:6] == "applet":
+            app_list.append(value)
+
+    if (sorted(app_list) == sorted(expected_app_list)):
+        return True
+    else:
+        return False
+
+def check_response_payload(expected_payload):
+    if (check_is_timeout() == True):
+        return False
+    json_lines = get_response_payload()
+    json_str = " ".join(json_lines)
+
+    if (json_str.strip() != ""):
+        json_dict = json.loads(json_str)
+    else:
+        json_dict = {}
+
+    if (json_dict == expected_payload):
+        return True
+    else:
+        return False
+
+def check_get_event():
+    line_num = 0
+    ft = open(output, 'r')
+    lines = ft.readlines()
+
+    for line in reversed(lines):
+        if (line[0:16] == "response status "):
+            break
+        line_num = line_num + 1
+
+    payload_lines = lines[-(line_num):-1]
+    ft.close()
+
+    if (payload_lines[1][0:17] ==  "received an event"):
+        return True
+    else:
+        return False

+ 285 - 0
test-tools/component_test/host-clients/src/host_app_sample.c

@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include "host_api.h"
+#include "bi-inc/attr_container.h"
+#include "er-coap-constants.h"
+
+static char *read_file_to_buffer(const char *filename, int *ret_size);
+int send_request_to_applet_success = 0;
+const char *label_for_request = "request1";
+int event_listener_counter = 0;
+char *applet_buf[1024 * 1024];
+const char *host_agent_ip = "127.0.0.1";
+void f_aee_response_handler(void *usr_ctx, aee_response_t *response)
+{
+    if (response == NULL) {
+        printf("########## request timeout!!! \n");
+    } else {
+        char *str = (char *) usr_ctx;
+        printf("#### dump response ####\n");
+        printf("#### user data: %s \n", str);
+        printf("#### status: %d \n", response->status);
+        if (response->payload != NULL)
+            attr_container_dump((attr_container_t *) response->payload);
+    }
+}
+
+void f_aee_event_listener(const char *url, void *event, int fmt)
+{
+    printf("######## event is received. url: %s, fmt:%d ############\n", url,
+            fmt);
+
+    attr_container_t *attr_obj = (attr_container_t *) event;
+
+    attr_container_dump(attr_obj);
+    /*
+     if (0 == strcmp(url, "alert/overheat"))
+     {
+     event_listener_counter++;
+     printf("event :%d \n", event_listener_counter);
+     }
+     */
+}
+
+static int print_menu_and_select(void)
+{
+    char s[256];
+    int choice;
+    do {
+        printf("\n");
+        printf("1. Install TestApplet1\n");
+        printf("2. Install TestApplet2\n");
+        printf("3. Install TestApplet3\n");
+        printf("4. Uninstall TestApplet1\n");
+        printf("5. Uninstall TestApplet2\n");
+        printf("6. Uninstall TestApplet3\n");
+        printf("7. Send Request to TestApplet1\n");
+        printf("8. Register Event to TestApplet1\n");
+        printf("9. UnRegister Event to TestApplet1\n");
+        printf("a. Query Applets\n");
+        printf("t. Auto Test\n");
+        printf("q. Exit\n");
+        printf("Please Select: ");
+
+        if (fgets(s, sizeof(s), stdin)) {
+            if (!strncmp(s, "q", 1))
+                return 0;
+            if (!strncmp(s, "a", 1))
+                return 10;
+            if (!strncmp(s, "t", 1))
+                return 20;
+            choice = atoi(s);
+            if (choice >= 1 && choice <= 9)
+                return choice;
+        }
+    } while (1);
+    return 0;
+}
+
+static void install_applet(int index)
+{
+    char applet_name[64];
+    char applet_file_name[64];
+    char *buf;
+    int size;
+    int ret;
+
+    printf("Installing TestApplet%d...\n", index);
+    snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index);
+    snprintf(applet_file_name, sizeof(applet_file_name), "./TestApplet%d.wasm",
+            index);
+    buf = read_file_to_buffer(applet_file_name, &size);
+    if (!buf) {
+        printf("Install Applet failed: read file %s error.\n",
+                applet_file_name);
+        return;
+    }
+
+    //step2. install applet
+    ret = aee_applet_install(buf, "wasm", size, applet_name, 5000);
+    if (ret) {
+        printf("%s install success\n", applet_name);
+    }
+    free(buf);
+}
+
+static void uninstall_applet(int index)
+{
+    int ret;
+    char applet_name[64];
+    snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index);
+    ret = aee_applet_uninstall(applet_name, "wasm", 5000);
+    if (ret) {
+        printf("uninstall %s success\n", applet_name);
+    } else {
+        printf("uninstall %s failed\n", applet_name);
+    }
+}
+
+static void send_request(int index)
+{
+    char url[64];
+    int ret;
+    aee_request_t req;
+    const char *user_context = "label for request";
+    attr_container_t *attr_obj = attr_container_create(
+            "Send Request to Applet");
+    attr_container_set_string(&attr_obj, "String key", "Hello");
+    attr_container_set_int(&attr_obj, "Int key", 1000);
+    attr_container_set_int64(&attr_obj, "Int64 key", 0x77BBCCDD11223344LL);
+
+    //specify the target wasm app
+    snprintf(url, sizeof(url), "/app/TestApplet%d/url1", index);
+
+    //not specify the target wasm app
+    //snprintf(url, sizeof(url), "url1");
+    aee_request_init(&req, url, COAP_PUT);
+    aee_request_set_payload(&req, attr_obj,
+            attr_container_get_serialize_length(attr_obj),
+            PAYLOAD_FORMAT_ATTRIBUTE_OBJECT);
+    ret = aee_request_send(&req, f_aee_response_handler, (void *) user_context,
+            10000);
+
+    if (ret) {
+        printf("send request to TestApplet1 success\n");
+    }
+}
+
+static void register_event(const char *event_path)
+{
+    hostclient_register_event(event_path, f_aee_event_listener);
+}
+
+static void unregister_event(const char *event_path)
+{
+    hostclient_unregister_event(event_path);
+}
+
+static void query_applets()
+{
+    aee_applet_list_t applet_lst;
+    aee_applet_list_init(&applet_lst);
+    aee_applet_list(5000, &applet_lst);
+    aee_applet_list_clean(&applet_lst);
+}
+
+static char *
+read_file_to_buffer(const char *filename, int *ret_size)
+{
+    FILE *fl = NULL;
+    char *buffer = NULL;
+    int file_size = 0;
+    if (!(fl = fopen(filename, "rb"))) {
+        printf("file open failed\n");
+        return NULL;
+    }
+
+    fseek(fl, 0, SEEK_END);
+    file_size = ftell(fl);
+
+    if (file_size == 0) {
+        printf("file length 0\n");
+        return NULL;
+    }
+
+    if (!(buffer = (char *) malloc(file_size))) {
+        fclose(fl);
+        return NULL;
+    }
+
+    fseek(fl, 0, SEEK_SET);
+
+    if (!fread(buffer, 1, file_size, fl)) {
+        printf("file read failed\n");
+        return NULL;
+    }
+
+    fclose(fl);
+    *ret_size = file_size;
+    return buffer;
+}
+
+static void auto_test()
+{
+    int i;
+    int interval = 1000; /* ms */
+    while (1) {
+        uninstall_applet(1);
+        uninstall_applet(2);
+        uninstall_applet(3);
+        install_applet(1);
+        install_applet(2);
+        install_applet(3);
+
+        for (i = 0; i < 60 * 1000 / interval; i++) {
+            query_applets();
+            send_request(1);
+            send_request(2);
+            send_request(3);
+            usleep(interval * 1000);
+        }
+    }
+}
+
+void exit_program()
+{
+    hostclient_shutdown();
+    exit(0);
+}
+
+int
+
+main()
+{
+    bool ret;
+
+    //step1. host client init
+    ret = hostclient_initialize(host_agent_ip, 3456);
+
+    if (!ret) {
+        printf("host client initialize failed\n");
+        return -1;
+    }
+
+    do {
+        int choice = print_menu_and_select();
+        printf("\n");
+
+        if (choice == 0)
+            exit_program();
+        if (choice <= 3)
+            install_applet(choice);
+        else if (choice <= 6)
+            uninstall_applet(choice - 3);
+        else if (choice <= 7)
+            send_request(1);
+        else if (choice <= 8)
+            register_event("alert/overheat");
+        else if (choice <= 9)
+            unregister_event("alert/overheat");
+        else if (choice == 10)
+            query_applets();
+        else if (choice == 20)
+            auto_test();
+    } while (1);
+
+    return 0;
+}
+
+// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
+// Debug program: F5 or Debug > Start Debugging menu
+
+// Tips for Getting Started:
+//   1. Use the Solution Explorer window to add/manage files
+//   2. Use the Team Explorer window to connect to source control
+//   3. Use the Output window to see build output and other messages
+//   4. Use the Error List window to view errors
+//   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
+//   6. In the future, to open this project again, go to File > Open > Project and select the .sln file

+ 44 - 0
test-tools/component_test/host-clients/src/makefile

@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+CC = gcc
+CFLAGS := -Wall -g
+
+# Add this to make compiler happy
+CFLAGS += -DWASM_ENABLE_INTERP=1
+
+host_api_c=../../../../host-agent/host-api-c
+attr_container_dir=../../../../wamr/core/app-framework/app-native-shared
+coap_dir=../../../../host-agent/coap
+shared_dir=../../../../wamr/core/shared
+
+# core
+INCLUDE_PATH = -I$(host_api_c)/src -I$(attr_container_dir)/ \
+               -I$(coap_dir)/er-coap -I$(coap_dir)/er-coap/extension \
+               -I$(shared_dir)/include \
+               -I$(shared_dir)/utils \
+               -I$(shared_dir)/platform/include/ \
+               -I$(shared_dir)/platform/linux/
+
+LIB := $(host_api_c)/src/libhostapi.a
+EXE := ./hostapp
+
+App_C_Files := host_app_sample.c
+
+OBJS := $(App_C_Files:.c=.o)
+
+all: $(EXE)
+
+%.o: %.c
+	@$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH)
+
+$(EXE): $(OBJS)
+	@rm -f $(EXE)
+	@$(CC) $(OBJS) -o $(EXE) $(LIB) -lpthread -lrt
+	@rm -f $(OBJS)
+
+.PHONY: clean
+clean:
+	rm -f $(OBJS) $(EXE)

+ 7 - 0
test-tools/component_test/set_dev_env.sh

@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+#!/bin/sh
+

+ 151 - 0
test-tools/component_test/start.py

@@ -0,0 +1,151 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+#!/usr/bin/env python
+
+# -*- coding: utf-8 -*-
+"""
+It is the entrance of the iagent test framework.
+
+"""
+
+import argparse
+import datetime
+import os
+import pprint
+import random
+import re
+import shlex
+import subprocess
+import signal
+import sys
+import time
+
+sys.path.append('../../../app-sdk/python')
+from framework.test_utils  import *
+from framework.framework  import *
+
+
+def signal_handler(signal, frame):
+        print('Pressed Ctrl+C!')
+        sys.exit(0)
+
+def Register_signal_handler():
+    signal.signal(signal.SIGINT, signal_handler)
+#    signal.pause()
+
+
+def flatten_args_list(l):
+    if l is None:
+        return None
+
+    return [x for y in l for x in y]
+
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(description = "to run specific case(s) "\
+            "in specific suite(s) with FC test framework")
+    parser.add_argument('-s', dest = 'suite_id', action = 'append',
+            nargs = '+',
+            help = 'one or multiple suite ids, which are also setup ids.'\
+                    'by default if it isn\'t passed from argument, all '\
+                    'suites are going to be run.')
+    parser.add_argument('-t', dest = 'case_id', action = 'append',
+            nargs = '+',
+            help = 'one or multiple cases ids.'\
+                    'by default if it isn\'t passed from argument, all '\
+                    'cases in specific suites are going to be run.')
+    parser.add_argument('-n', dest = 'repeat_time', action = 'store',
+            default = 1,
+            help = 'how many times do you want to run. there is 40s '\
+                    'break time between two rounds. each round includs '\
+                    'init_setup, run_test_case and deinit_setup.')
+    parser.add_argument('--shuffle_all', dest = 'shuffle_all',
+            default = False, action = 'store_true',
+            help = 'shuffle_all test cases in per test suite '\
+                    'by default, all cases under per suite should '\
+                    'be executed by input order.')
+    parser.add_argument('--cases_list', dest='cases_list_file_path',
+            default=None,
+            action='store',
+            help="read cases list from a flie ")
+    parser.add_argument('--skip_proc', dest='skip_proc',
+            default = False, action = 'store_true',
+            help='do not start the test process.'\
+                'sometimes the gw_broker process will be started in eclipse for debug purpose')
+    parser.add_argument('-b', dest = 'binaries', action = 'store',
+            help = 'The path of target folder ')
+    parser.add_argument('-d', dest = 'debug', action = 'store_true',
+            help = 'wait user to  attach the target process after launch processes ')
+    parser.add_argument('--rebuild', dest = 'rebuild', action = 'store_true',
+            help = 'rebuild all test binaries')
+    args = parser.parse_args()
+
+    print "------------------------------------------------------------"
+    print "parsing arguments ... ..."
+    print args
+
+    '''
+    logger = logging.getLogger('coapthon.server.coap')
+    logger.setLevel(logging.DEBUG)
+    console = logging.StreamHandler()
+    console.setLevel(logging.DEBUG)
+    logger.addHandler(console)
+    '''
+    print "------------------------------------------------------------"
+    print "preparing wamr binary and test tools ... ..."
+    os.system("cd ../../samples/simple/ && bash build.sh -p host-interp")
+
+    Register_signal_handler()
+
+    api_init_globals();
+
+    api_create_case_event();
+
+    suites_list = flatten_args_list(args.suite_id)
+    cases_list = flatten_args_list(args.case_id)
+
+    dirname, filename = os.path.split(os.path.abspath(sys.argv[0]))
+    api_set_root_path(dirname);
+
+    framework = CTestFramework(dirname);
+    framework.repeat_time = int(args.repeat_time)
+    framework.shuffle_all = args.shuffle_all
+    framework.skip_proc=args.skip_proc
+
+    api_set_value('keep_env', args.skip_proc)
+    api_set_value('debug', args.debug)
+    api_set_value('rebuild', args.rebuild)
+
+    binary_path = args.binaries
+    if  binary_path is None:
+        binary_path = os.path.abspath(dirname + '/../..')
+
+    print "checking execution binary path: " + binary_path
+    if not os.path.exists(binary_path):
+        print "The execution binary path was not available. quit..."
+        os._exit(0)
+    api_set_value('binary_path', binary_path)
+
+    if suites_list is not None:
+        framework.target_suites = suites_list
+    else:
+        framework.load_suites()
+
+    framework.target_cases = cases_list
+    framework.start_run()
+
+    print "\n\n------------------------------------------------------------"
+    print "The run folder is [" + framework.running_folder +"]"
+    print "that's all. bye"
+
+    print "kill to quit.."
+    t_kill_process_by_name("start.py")
+
+    sys.exit(0)
+    os._exit()
+
+

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/__init__.py


+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/01-install/__init__.py


+ 94 - 0
test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py

@@ -0,0 +1,94 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #uninstall inexistent App1
+        ret = uninstall_app("App1")
+        if (ret != 160):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps([])
+        if (ret == False):
+            return False, ''
+
+        #install App1
+        ret = install_app("App1", "01_install.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1"])
+        if (ret == False):
+            return False, ''
+
+        #install App2
+        ret = install_app("App2", "01_install.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1","App2"])
+        if (ret == False):
+            return False, ''
+
+        #uninstall App2
+        ret = uninstall_app("App2")
+        if (ret != 66):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1"])
+        if (ret == False):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/02-request/__init__.py


+ 73 - 0
test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py

@@ -0,0 +1,73 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #install App1
+        ret = install_app("App1", "02_request.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1"])
+        if (ret == False):
+            return False, ''
+
+        #send request to App1
+        ret = send_request("/res1", "GET", None)
+        if (ret != 69):
+            return False, ''
+        expect_response_payload = {"key1":"value1","key2":"value2"}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        #send request to App1
+        ret = send_request("/res2", "DELETE", None)
+        if (ret != 66):
+            return False, ''
+        expect_response_payload = {}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/03-event/__init__.py


+ 67 - 0
test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py

@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #install App1
+        ret = install_app("App1", "03_event.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1"])
+        if (ret == False):
+            return False, ''
+
+        #register event
+        ret = register("/alert/overheat", 2000, 5000)
+        if (ret != 69):
+            return False, ''
+        ret = check_get_event()
+        if (ret == False):
+            return False, ''
+
+        #deregister event
+        ret = deregister("/alert/overheat")
+        if (ret != 69):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/__init__.py


+ 80 - 0
test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py

@@ -0,0 +1,80 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #install App1
+        ret = install_app("App1", "04_request_internal_resp.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #install App2
+        ret = install_app("App2", "04_request_internal_req.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1","App2"])
+        if (ret == False):
+            return False, ''
+
+        #send request to App2
+        ret = send_request("/res1", "GET", None)
+        if (ret != 69):
+            return False, ''
+        time.sleep(2)
+        expect_response_payload = {"key1":"value1","key2":"value2"}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        #send request to App2
+        ret = send_request("/res2", "GET", None)
+        if (ret != 69):
+            return False, ''
+        time.sleep(2)
+        expect_response_payload = {"key1":"value1","key2":"value2"}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/__init__.py


+ 70 - 0
test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py

@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #install App1
+        ret = install_app("App1", "05_event_internal_provider.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #install App2
+        ret = install_app("App2", "05_event_internal_subscriber.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1","App2"])
+        if (ret == False):
+            return False, ''
+
+        #send request to App2
+        ret = send_request("/res1", "GET", None)
+        if (ret != 69):
+            return False, ''
+        time.sleep(2)
+        expect_response_payload = {"key1":"value1","key2":"value2"}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/06-timer/__init__.py


+ 70 - 0
test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py

@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #install App1
+        ret = install_app("App1", "06_timer.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1"])
+        if (ret == False):
+            return False, ''
+
+        #send request to App1
+        ret = send_request("/res1", "GET", None)
+        if (ret != 69):
+            return False, ''
+
+        time.sleep(3)
+
+        ret = send_request("/check_timer", "GET", None)
+        if (ret != 69):
+            return False, ''
+        expect_response_payload = {"num":2}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/07-sensor/__init__.py


+ 65 - 0
test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py

@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #install App1
+        ret = install_app("App1", "07_sensor.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1"])
+        if (ret == False):
+            return False, ''
+
+        #send request to App1
+        ret = send_request("/res1", "GET", None)
+        if (ret != 69):
+            return False, ''
+        time.sleep(2)
+        expect_response_payload = {"key1":"value1","key2":"value2"}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/__init__.py


+ 78 - 0
test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py

@@ -0,0 +1,78 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import sys
+import time
+import random
+import logging
+import json
+
+from framework.case_base import *
+from framework.test_api import *
+from harness.harness_api import *
+
+class CTestCase(CTestCaseBase):
+    def __init__(self, suite):
+        CTestCaseBase.__init__(self, suite)
+
+    def get_case_name(self):
+        case_path = os.path.dirname(os.path.abspath( __file__ ))
+        return os.path.split(case_path)[1]
+
+    def on_get_case_description(self):
+        return "startup the executables"
+
+    def on_setup_case(self):
+        os.chdir(self.get_case_name())
+        start_env()
+        api_log_error("on_setup_case OK")
+        return True, ''
+
+    def on_cleanup_case(self):
+        stop_env()
+        api_log_error("on_cleanup_case OK")
+        return True, ''
+
+    # called by the framework
+    def on_run_case(self):
+        time.sleep(0.5)
+
+        #install App1
+        ret = install_app("App1", "08_on_destroy.wasm")
+        if (ret != 65):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps(["App1"])
+        if (ret == False):
+            return False, ''
+
+        #send request to App1
+        ret = send_request("/res1", "GET", None)
+        if (ret != 69):
+            return False, ''
+        time.sleep(2)
+        expect_response_payload = {"key1":"value1"}
+        ret = check_response_payload(expect_response_payload)
+        if (ret == False):
+            return False, ''
+
+        #uninstall App1
+        ret = uninstall_app("App1")
+        if (ret != 66):
+            return False, ''
+
+        #query Apps
+        ret = query_app()
+        if (ret != 69):
+            return False, ''
+        ret = check_query_apps([])
+        if (ret == False):
+            return False, ''
+
+        return True, ''

+ 0 - 0
test-tools/component_test/suites/01-life-cycle/cases/__init__.py


+ 56 - 0
test-tools/component_test/suites/01-life-cycle/suite_setup.py

@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import os
+import shutil
+import types
+import time
+import glob
+
+from framework.test_api import *
+from framework.test_utils import *
+from harness.harness_api import *
+from framework.suite import *
+
+class CTestSuite(CTestSuiteBase):
+    setup_path = ""
+    def __init__(self, name, suite_path, run_path):
+            CTestSuiteBase.__init__(self, name, suite_path, run_path)
+
+    def on_suite_setup(self):
+        global setup_path
+        setup_path = os.getcwd()
+        cases = os.listdir(self.suite_path + "/cases/")
+        cases.sort()
+
+        if api_get_value("rebuild", False):
+                  path_tmp = os.getcwd()
+                  os.chdir(self.suite_path + "/test-app")
+                  os.system(self.suite_path + "/test-app" + "/build.sh")
+                  os.chdir(path_tmp)
+
+        os.makedirs(self.run_path + "/test-app")
+
+        for case in cases:
+            if case != "__init__.pyc" and case != "__init__.py":
+                os.makedirs(self.run_path + "/" + case)
+                #copy each case's host_tool, simple, wasm files, start/stop scripts to the run directory,
+                shutil.copy(setup_path + "/../../samples/simple/out/simple", self.run_path + "/" + case)
+                shutil.copy(setup_path + "/../../samples/simple/out/host_tool", self.run_path + "/" + case)
+                for file in glob.glob(self.suite_path + "/test-app/" + "/*.wasm"):
+                  shutil.copy(file, self.run_path + "/test-app")
+                shutil.copy(self.suite_path + "/tools/product/start.sh", self.run_path + "/" + case)
+                shutil.copy(self.suite_path + "/tools/product/stop.sh", self.run_path + "/" + case)
+
+        os.chdir(self.run_path)
+
+        return True, 'OK'
+
+    def on_suite_cleanup(self):
+        global setup_path
+        os.chdir(setup_path)
+        api_log("stopping env..")
+
+        return True, 'OK'

+ 16 - 0
test-tools/component_test/suites/01-life-cycle/test-app/01_install.c

@@ -0,0 +1,16 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+
+void on_init()
+{
+    printf("Hello, I was installed.\n");
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 62 - 0
test-tools/component_test/suites/01-life-cycle/test-app/02_request.c

@@ -0,0 +1,62 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/request.h"
+
+void res1_handler(request_t *request)
+{
+    response_t response[1];
+    attr_container_t *payload;
+
+    printf("### user resource 1 handler called\n");
+
+    printf("###### dump request ######\n");
+    printf("sender: %lu\n", request->sender);
+    printf("url: %s\n", request->url);
+    printf("action: %d\n", request->action);
+    printf("payload:\n");
+    if (request->payload
+            != NULL&& request->payload_len > 0 && request->fmt == FMT_ATTR_CONTAINER)
+        attr_container_dump((attr_container_t *) request->payload);
+    printf("#### dump request end ###\n");
+
+    payload = attr_container_create("wasm app response payload");
+    if (payload == NULL)
+        return;
+
+    attr_container_set_string(&payload, "key1", "value1");
+    attr_container_set_string(&payload, "key2", "value2");
+
+    make_response_for_request(request, response);
+    set_response(response, CONTENT_2_05,
+    FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
+    printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
+    api_response_send(response);
+
+    attr_container_destroy(payload);
+}
+
+void res2_handler(request_t *request)
+{
+    response_t response[1];
+    make_response_for_request(request, response);
+    set_response(response, DELETED_2_02, 0, NULL, 0);
+    api_response_send(response);
+
+    printf("### user resource 2 handler called\n");
+}
+
+void on_init()
+{
+    /* register resource uri */
+    api_register_resource_handler("/res1", res1_handler);
+    api_register_resource_handler("/res2", res2_handler);
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 53 - 0
test-tools/component_test/suites/01-life-cycle/test-app/03_event.c

@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/timer_wasm_app.h"
+#include "wa-inc/request.h"
+
+int num = 0;
+
+void publish_overheat_event()
+{
+    attr_container_t *event;
+
+    event = attr_container_create("event");
+    attr_container_set_string(&event, "warning", "temperature is over high");
+
+    printf("###app publish event begin ###\n");
+
+    api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event,
+            attr_container_get_serialize_length(event));
+
+    printf("###app publish event end ###\n");
+
+    attr_container_destroy(event);
+}
+
+/* Timer callback */
+void timer1_update(user_timer_t timer)
+{
+    printf("Timer update %d\n", num++);
+    publish_overheat_event();
+}
+
+void start_timer()
+{
+    user_timer_t timer;
+
+    /* set up a timer */
+    timer = api_timer_create(1000, true, false, timer1_update);
+    api_timer_restart(timer, 1000);
+}
+
+void on_init()
+{
+    start_timer();
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 66 - 0
test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c

@@ -0,0 +1,66 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/request.h"
+
+uint32 mid;
+unsigned long sender;
+
+void my_response_handler(response_t *response, void *user_data)
+{
+    attr_container_t *payload;
+    printf("### user resource 1 handler called\n");
+
+    payload = attr_container_create("wasm app response payload");
+    if (payload == NULL)
+        return;
+
+    attr_container_set_string(&payload, "key1", "value1");
+    attr_container_set_string(&payload, "key2", "value2");
+
+    response->mid = mid;
+    response->reciever = sender;
+    set_response(response, CONTENT_2_05,
+    FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
+    printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
+    api_response_send(response);
+
+    attr_container_destroy(payload);
+}
+
+static void test_send_request(const char *url, const char *tag)
+{
+    request_t request[1];
+
+    init_request(request, (char *)url, COAP_PUT, 0, NULL, 0);
+    api_send_request(request, my_response_handler, (void *)tag);
+}
+
+void res1_handler(request_t *request)
+{
+    mid = request->mid;
+    sender = request->sender;
+    test_send_request("url1", "a general request");
+}
+
+void res2_handler(request_t *request)
+{
+    mid = request->mid;
+    sender = request->sender;
+    test_send_request("/app/App1/url1", "a general request");
+}
+
+void on_init()
+{
+    /* register resource uri */
+    api_register_resource_handler("/res1", res1_handler);
+    api_register_resource_handler("/res2", res2_handler);
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 52 - 0
test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c

@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/request.h"
+
+void res1_handler(request_t *request)
+{
+    response_t response[1];
+    attr_container_t *payload;
+
+    printf("[resp] ### user resource 1 handler called\n");
+
+    printf("[resp] ###### dump request ######\n");
+    printf("[resp] sender: %lu\n", request->sender);
+    printf("[resp] url: %s\n", request->url);
+    printf("[resp] action: %d\n", request->action);
+    printf("[resp] payload:\n");
+    if (request->payload != NULL && request->fmt == FMT_ATTR_CONTAINER)
+        attr_container_dump((attr_container_t *) request->payload);
+    printf("[resp] #### dump request end ###\n");
+
+    payload = attr_container_create("wasm app response payload");
+    if (payload == NULL)
+        return;
+
+    attr_container_set_string(&payload, "key1", "value1");
+    attr_container_set_string(&payload, "key2", "value2");
+
+    make_response_for_request(request, response);
+    set_response(response, CONTENT_2_05,
+    FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
+    printf("[resp] response payload len %d\n",
+            attr_container_get_serialize_length(payload));
+    printf("[resp] reciver: %lu, mid:%d\n", response->reciever, response->mid);
+    api_response_send(response);
+
+    attr_container_destroy(payload);
+}
+
+void on_init()
+{
+    /* register resource uri */
+    api_register_resource_handler("/url1", res1_handler);
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 53 - 0
test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c

@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/timer_wasm_app.h"
+#include "wa-inc/request.h"
+
+int num = 0;
+
+void publish_overheat_event()
+{
+    attr_container_t *event;
+
+    event = attr_container_create("event");
+    attr_container_set_string(&event, "warning", "temperature is over high");
+
+    printf("###app publish event begin ###\n");
+
+    api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event,
+            attr_container_get_serialize_length(event));
+
+    printf("###app publish event end ###\n");
+
+    attr_container_destroy(event);
+}
+
+/* Timer callback */
+void timer1_update(user_timer_t timer)
+{
+    printf("Timer update %d\n", num++);
+    publish_overheat_event();
+}
+
+void start_timer()
+{
+    user_timer_t timer;
+
+    /* set up a timer */
+    timer = api_timer_create(1000, true, false, timer1_update);
+    api_timer_restart(timer, 1000);
+}
+
+void on_init()
+{
+    start_timer();
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 50 - 0
test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c

@@ -0,0 +1,50 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/request.h"
+
+uint32 mid;
+unsigned long sender;
+
+void over_heat_event_handler(request_t *request)
+{
+    response_t response[1];
+    attr_container_t *payload;
+
+    payload = attr_container_create("wasm app response payload");
+    if (payload == NULL)
+        return;
+
+    attr_container_set_string(&payload, "key1", "value1");
+    attr_container_set_string(&payload, "key2", "value2");
+
+    response->mid = mid;
+    response->reciever = sender;
+    set_response(response, CONTENT_2_05,
+    FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
+    printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
+    api_response_send(response);
+
+    attr_container_destroy(payload);
+}
+
+void res1_handler(request_t *request)
+{
+    mid = request->mid;
+    sender = request->sender;
+    api_subscribe_event("alert/overheat", over_heat_event_handler);
+}
+
+void on_init()
+{
+    /* register resource uri */
+    api_register_resource_handler("/res1", res1_handler);
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 76 - 0
test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c

@@ -0,0 +1,76 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/request.h"
+#include "wa-inc/timer_wasm_app.h"
+
+/* User global variable */
+int num = 0;
+
+/* Timer callback */
+void timer1_update(user_timer_t timer)
+{
+    if (num < 2)
+        num++;
+}
+
+void res1_handler(request_t *request)
+{
+    user_timer_t timer;
+
+    /* set up a timer */
+    timer = api_timer_create(1000, true, false, timer1_update);
+    api_timer_restart(timer, 1000);
+
+    response_t response[1];
+
+    make_response_for_request(request, response);
+
+    set_response(response, CONTENT_2_05,
+    FMT_ATTR_CONTAINER, NULL, 0);
+
+    api_response_send(response);
+}
+
+void res2_handler(request_t *request)
+{
+    response_t response[1];
+    attr_container_t *payload;
+
+    if (num == 2) {
+        attr_container_t *payload;
+        printf("### user resource 1 handler called\n");
+
+        payload = attr_container_create("wasm app response payload");
+        if (payload == NULL)
+            return;
+
+        attr_container_set_int(&payload, "num", num);
+
+        make_response_for_request(request, response);
+
+        set_response(response, CONTENT_2_05,
+        FMT_ATTR_CONTAINER, (const char *)payload,
+                attr_container_get_serialize_length(payload));
+        printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
+        api_response_send(response);
+
+        attr_container_destroy(payload);
+    }
+
+}
+
+void on_init()
+{
+    /* register resource uri */
+    api_register_resource_handler("/res1", res1_handler);
+    api_register_resource_handler("/check_timer", res2_handler);
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 69 - 0
test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c

@@ -0,0 +1,69 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/request.h"
+#include "wa-inc/sensor.h"
+
+uint32 mid;
+unsigned long sender;
+
+/* Sensor event callback*/
+void sensor_event_handler(sensor_t sensor, attr_container_t *event,
+        void *user_data)
+{
+    printf("### app get sensor event\n");
+
+    response_t response[1];
+    attr_container_t *payload;
+
+    payload = attr_container_create("wasm app response payload");
+    if (payload == NULL)
+        return;
+
+    attr_container_set_string(&payload, "key1", "value1");
+    attr_container_set_string(&payload, "key2", "value2");
+
+    response->mid = mid;
+    response->reciever = sender;
+    set_response(response, CONTENT_2_05,
+    FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
+    printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
+    api_response_send(response);
+
+    attr_container_destroy(payload);
+}
+
+void res1_handler(request_t *request)
+{
+    mid = request->mid;
+    sender = request->sender;
+
+    sensor_t sensor;
+    char *user_data;
+    attr_container_t *config;
+
+    printf("### app on_init 1\n");
+    /* open a sensor */
+    user_data = malloc(100);
+    printf("### app on_init 2\n");
+    sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data);
+    printf("### app on_init 3\n");
+
+    /* config the sensor */
+    sensor_config(sensor, 2000, 0, 0);
+    printf("### app on_init 4\n");
+}
+
+void on_init()
+{
+    /* register resource uri */
+    api_register_resource_handler("/res1", res1_handler);
+}
+
+void on_destroy()
+{
+    /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}

+ 67 - 0
test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c

@@ -0,0 +1,67 @@
+/*
+* Copyright (C) 2019 Intel Corporation.  All rights reserved.
+* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+*/
+
+#include "wasm_app.h"
+#include "wa-inc/request.h"
+#include "wa-inc/sensor.h"
+
+uint32 mid;
+unsigned long sender;
+sensor_t sensor;
+
+/* Sensor event callback*/
+void sensor_event_handler(sensor_t sensor, attr_container_t *event, void *user_data) {
+  printf("### app get sensor event\n");
+
+  response_t response[1];
+  attr_container_t *payload;
+
+  payload = attr_container_create("wasm app response payload");
+  if (payload == NULL)
+    return;
+
+  attr_container_set_string(&payload, "key1", "value1");
+
+  response->mid = mid;
+  response->reciever = sender;
+  set_response(response,
+               CONTENT_2_05,
+               FMT_ATTR_CONTAINER,
+               (const char *)payload,
+               attr_container_get_serialize_length(payload));
+  printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
+  api_response_send(response);
+
+  attr_container_destroy(payload);
+}
+
+void res1_handler(request_t *request)
+{
+  mid = request->mid;
+  sender = request->sender;
+
+  char *user_data;
+  attr_container_t *config;
+
+  printf("### app on_init 1\n");
+  /* open a sensor */
+  user_data = malloc(100);
+  printf("### app on_init 2\n");
+  sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data);
+  printf("### app on_init 3\n");
+}
+
+void on_init()
+{
+  /* register resource uri */
+  api_register_resource_handler("/res1", res1_handler);
+}
+
+void on_destroy()
+{
+  if(NULL != sensor){
+    sensor_close(sensor);
+  }
+}

+ 39 - 0
test-tools/component_test/suites/01-life-cycle/test-app/build.sh

@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+. ../../../set_dev_env.sh
+
+CC=/opt/wasi-sdk/bin/clang
+APP_DIR=$PWD
+WAMR_DIR=${APP_DIR}/../../../../../
+SDK_DIR=${WAMR_DIR}/wamr-sdk/out/simple-host-interp
+APP_FRAMEWORK_DIR=${SDK_DIR}/app-sdk/wamr-app-framework
+DEPS_DIR=${WAMR_DIR}/core/deps
+
+for i in `ls *.c`
+do
+APP_SRC="$i"
+OUT_FILE=${i%.*}.wasm
+/opt/wasi-sdk/bin/clang -O3 \
+                        -Wno-int-conversion \
+                        -I${APP_FRAMEWORK_DIR}/include \
+                        -I${DEPS_DIR} \
+                        --target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \
+                        --sysroot=${SDK_DIR}/app-sdk/libc-builtin-sysroot       \
+                        -L${APP_FRAMEWORK_DIR}/lib -lapp_framework      \
+                        -Wl,--allow-undefined-file=${SDK_DIR}/app-sdk/libc-builtin-sysroot/share/defined-symbols.txt        \
+                        -Wl,--no-threads,--strip-all,--no-entry -nostdlib \
+                        -Wl,--export=on_init -Wl,--export=on_destroy \
+                        -Wl,--export=on_request -Wl,--export=on_response \
+                        -Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \
+                        -Wl,--export=on_connection_data \
+                        -o ${OUT_FILE} \
+                        ${APP_SRC}
+if [ -f ${OUT_FILE} ]; then
+        echo "build ${OUT_FILE} success"
+else
+        echo "build ${OUT_FILE} fail"
+fi
+done

+ 10 - 0
test-tools/component_test/suites/01-life-cycle/tools/product/start.sh

@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+#!/bin/bash
+
+cd $(dirname "$0")
+
+./simple -s > /dev/null 2>&1 &

+ 9 - 0
test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh

@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+#!/bin/bash
+
+ps aux | grep -ie host_tool | awk '{print $2}' | xargs kill -9 &
+ps aux | grep -ie simple | awk '{print $2}' | xargs kill -9 &

+ 0 - 0
test-tools/component_test/suites/__init__.py


+ 19 - 0
test-tools/component_test/suites/readme.txt

@@ -0,0 +1,19 @@
+The description of each case in the test suites, should add descriptions in this file when new cases created in the future.
+
+suite 01-life-cycle:
+case 01-install:
+    install or uninstall apps for times and query apps to see if the app list is expected.
+case 02-request:
+    send request to an app, the app will respond specific attribute objects, host side should get them.
+case 03-event:
+    register event to an app, the app will send event back periodically, host side should get some payload.
+case 04-request_internal:
+    install 2 apps, host sends request to app2, then app2 sends request to app1, finally app1 respond specific payload to host, host side will check it.
+case 05-event_internal:
+    install 2 apps, host sends request to app2, then app2 subscribe app1's event, finally app1 respond specific payload to host, host side will check it.
+case 06-timer:
+    host send request to an app, the app then start a timer, when time goes by 2 seconds, app will respond specific payload to host, host side will check it.
+case 07-sensor:
+    open sensor in app and then config the sensor in on_init, finally app will respond specific payload to host, host side will check it.
+case 08-on_destroy:
+    open sensor in app in on_init, and close the sensor in on_destroy, host should install and uninstall the app successfully.

+ 4 - 1
wamr-compiler/CMakeLists.txt

@@ -34,6 +34,9 @@ elseif (WAMR_BUILD_TARGET STREQUAL "AMD_64")
   add_definitions(-DBUILD_TARGET_AMD_64)
 elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
   add_definitions(-DBUILD_TARGET_X86_32)
+elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
+  add_definitions(-DBUILD_TARGET_AARCH64)
+  add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
 elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
   add_definitions(-DBUILD_TARGET_ARM)
   add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
@@ -44,7 +47,7 @@ endif ()
 message ("-- Build as target ${WAMR_BUILD_TARGET}")
 
 if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-  if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+  if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
     # Add -fPIC flag if build as 64-bit
     set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
     set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")

+ 1 - 1
wamr-compiler/main.c

@@ -14,7 +14,7 @@ print_help()
 {
   printf("Usage: wamrc [options] -o output_file wasm_file\n");
   printf("  --target=<arch-name>      Set the target arch, which has the general format: <arch><sub>\n");
-  printf("                            <arch> = x86_64, i386, arm, thumb, mips.\n");
+  printf("                            <arch> = x86_64, i386, aarch64, arm, thumb, mips.\n");
   printf("                              Default is host arch, e.g. x86_64\n");
   printf("                            <sub> = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n");
   printf("                            Use --target=help to list supported targets\n");