Просмотр исходного кода

Import test suites to test spec cases (#736)

Wenyong Huang 4 лет назад
Родитель
Сommit
00663f0cd5

+ 4 - 0
ATTRIBUTIONS.md

@@ -63,3 +63,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
 ### zephyr
 ### zephyr
 
 
 [LICENSE](./samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE)
 [LICENSE](./samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE)
+
+### wac
+
+[LICENSE](./tests/wamr-test-suites/spec-test-script/LICENSE)

+ 4 - 4
core/iwasm/compilation/aot_llvm.c

@@ -1208,7 +1208,7 @@ WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
 void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
 void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
 
 
 #if WASM_ENABLE_LAZY_JIT != 0
 #if WASM_ENABLE_LAZY_JIT != 0
-void 
+void
 aot_handle_llvm_errmsg(char *error_buf,
 aot_handle_llvm_errmsg(char *error_buf,
                        uint32 error_buf_size,
                        uint32 error_buf_size,
                        const char *string,
                        const char *string,
@@ -1222,7 +1222,7 @@ aot_handle_llvm_errmsg(char *error_buf,
     LLVMDisposeErrorMessage(err_msg);
     LLVMDisposeErrorMessage(err_msg);
 }
 }
 
 
-static bool 
+static bool
 llvm_orcjit_create(AOTCompContext *comp_ctx)
 llvm_orcjit_create(AOTCompContext *comp_ctx)
 {
 {
     char *err_msg = NULL;
     char *err_msg = NULL;
@@ -1317,7 +1317,7 @@ llvm_orcjit_create(AOTCompContext *comp_ctx)
     /* if success, it will dispose lazy_orcjit_builder memory */
     /* if success, it will dispose lazy_orcjit_builder memory */
     error = LLVMOrcCreateLLLazyJIT(&lazy_orcjit, lazy_orcjit_builder);
     error = LLVMOrcCreateLLLazyJIT(&lazy_orcjit, lazy_orcjit_builder);
     if (error) {
     if (error) {
-        aot_handle_llvm_errmsg(buf, sizeof(buf), 
+        aot_handle_llvm_errmsg(buf, sizeof(buf),
                                "failed to create llvm lazy orcjit instance",
                                "failed to create llvm lazy orcjit instance",
                                error);
                                error);
         goto fail;
         goto fail;
@@ -1328,7 +1328,7 @@ llvm_orcjit_create(AOTCompContext *comp_ctx)
                 &main_gen, LLVMOrcLLLazyJITGetGlobalPrefix(lazy_orcjit),
                 &main_gen, LLVMOrcLLLazyJITGetGlobalPrefix(lazy_orcjit),
                 0, NULL);
                 0, NULL);
     if (error) {
     if (error) {
-        aot_handle_llvm_errmsg(buf, sizeof(buf), 
+        aot_handle_llvm_errmsg(buf, sizeof(buf),
                 "failed to create dynmaic library search generator", error);
                 "failed to create dynmaic library search generator", error);
         goto fail;
         goto fail;
     }
     }

+ 1 - 1
core/iwasm/compilation/aot_llvm.h

@@ -418,7 +418,7 @@ bool
 aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
 aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
 
 
 #if WASM_ENABLE_LAZY_JIT != 0
 #if WASM_ENABLE_LAZY_JIT != 0
-void 
+void
 aot_handle_llvm_errmsg(char *error_buf,
 aot_handle_llvm_errmsg(char *error_buf,
                        uint32 error_buf_size,
                        uint32 error_buf_size,
                        const char *string,
                        const char *string,

+ 1 - 1
doc/build_wamr.md

@@ -199,7 +199,7 @@ make
 ```
 ```
 
 
 
 
-By default in Linux, the interpreter, AOT and WASI are enabled, and JIT and LazyJIT are disabled. 
+By default in Linux, the interpreter, AOT and WASI are enabled, and JIT and LazyJIT are disabled.
 And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth.
 And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth.
 
 
 To enable WASM JIT, firstly we should build LLVM:
 To enable WASM JIT, firstly we should build LLVM:

+ 40 - 0
tests/wamr-test-suites/README.md

@@ -0,0 +1,40 @@
+# WAMR test suites
+
+This folder contains test scripts and cases for wamr.
+
+## Help
+```
+./test_wamr.sh --help
+```
+
+## Examples
+Test spec cases with fast interpreter mode, which will create folder `workspace`, download the `spec` and `wabt` repo, and build `iwasm` automatically to test spec cases:
+```
+./test_wamr.sh -s spec -t fast-interp
+```
+
+Test spec cases with aot mode, and use the wabt binary release package instead of compiling wabt from the source code:
+```
+./test_wamr.sh -s spec -t aot -b
+```
+
+Test spec cases with all modes (classic-interp/fast-interp/aot/jit):
+```
+./test_wamr.sh -s spec
+```
+
+Test spec cases with aot mode and pthread enabled:
+```
+./test_wamr.sh -s spec -t aot -p
+```
+
+Test spec cases with aot mode and SIMD enabled:
+```
+./test_wamr.sh -s spec -t aot -S
+```
+
+Test spec cases with fast-interp on target x86_32:
+```
+./test_wamr.sh -s spec -t fast-interp -m x86_32
+```
+

+ 5 - 0
tests/wamr-test-suites/spec-test-script/CHANGES

@@ -0,0 +1,5 @@
+####################
+2021-9-8
+
+Modify runtest.py from https://github.com/kanaka/wac/blob/master/runtest.py
+to enable testing spec cases with more checks and support more runtime modes.

+ 387 - 0
tests/wamr-test-suites/spec-test-script/LICENSE

@@ -0,0 +1,387 @@
+Copyright (C) Joel Martin <github@martintribe.org>
+
+The wac project is licensed under the MPL 2.0 (Mozilla Public License
+2.0). The text of the MPL 2.0 license is included below and can be
+found at https://www.mozilla.org/MPL/2.0/
+
+By default, wac and wace link with the BSD licensed editline library
+(http://www.thrysoee.dk/editline/). The wac/wace build process can be
+switched to link with the GPL license GNU readline library with the
+USE_READLINE=1 flag.
+
+
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
+
+

+ 162 - 0
tests/wamr-test-suites/spec-test-script/all.sh

@@ -0,0 +1,162 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+# exit if meet an exception
+function DEBUG() {
+  [[ -n $(env | grep "\<DEBUG\>") ]] && $@
+}
+DEBUG set -xevu
+
+# Run the following command to test a single wast file:
+#   ./spec-test-script/runtest.py --wast2wasm ./workspace/wabt/out/gcc/Release/wat2wasm \
+#   --interpreter iwasm <wast file>
+
+readonly SPEC_TEST_DIR="spec/test/core"
+readonly WAST2WASM_CMD="./wabt/out/gcc/Release/wat2wasm"
+readonly WAMRC_CMD="../../../wamr-compiler/build/wamrc"
+IWASM_CMD="../../../product-mini/platforms/linux/build/iwasm"
+
+# "imports" and "linking" are only avilable when enabling multi modules
+# "comments" is for runtest.py
+
+IGNORE_LIST=(
+  "comments" "inline-module" "imports" "linking" "names"
+)
+
+readonly -a MULTI_MODULE_LIST=(
+  "imports" "linking"
+)
+
+SGX_IGNORE_LIST=("conversions" "f32_bitwise" "f64_bitwise")
+
+# these cases run failed due to native stack overflow check failed
+SGX_AOT_IGNORE_LIST=("call_indirect" "call" "fac" "skip-stack-guard-page")
+
+function usage()
+{
+    echo "Usage: all.sh [-t] [-m <x86_64|x86_32|ARMV7_VFP|THUMBV7_VFP>] [-M] [-x] [-S] [-r]"
+    exit 1
+}
+
+function run_case_w_aot()
+{
+    local test_case=$1
+    echo "============> run ${test_case} with AOT"
+    python2.7 runtest.py \
+        --wast2wasm ${WAST2WASM_CMD} \
+        --interpreter ${IWASM_CMD} \
+        ${SPEC_TEST_DIR}/${test_case} \
+        --aot-compiler ${WAMRC_CMD} \
+        --aot --aot-target ${TARGET} \
+        ${SGX_OPT} \
+        ${SIMD_OPT} \
+        ${REF_TYPES_OPT}
+        #--no_cleanup
+    if [[ $? != 0 ]]; then
+        echo "============> run ${test_case} failed"
+        exit 1
+    fi
+}
+
+function run_case_wo_aot()
+{
+    local test_case=$1
+    echo "============> run ${test_case}"
+    python2.7 runtest.py \
+        --wast2wasm ${WAST2WASM_CMD} \
+        --interpreter ${IWASM_CMD} \
+        ${SPEC_TEST_DIR}/${test_case}\
+        --aot-compiler ${WAMRC_CMD} \
+        ${SGX_OPT} \
+        ${SIMD_OPT} \
+        ${REF_TYPES_OPT}
+        #--no_cleanup
+    if [[ $? != 0 ]]; then
+        echo "============> run ${test_case} failed"
+        exit 1
+    fi
+}
+
+ENABLE_MULTI_MODULE=0
+TARGET="X86_64"
+SGX_OPT=""
+AOT=false
+SIMD_OPT=""
+REF_TYPES_OPT=""
+while getopts ":Mm:txSr" opt; do
+    case $opt in
+        t) AOT=true ;;
+        m)
+            TARGET=$OPTARG
+            if [[ ${TARGET} == 'X86_32' ]];then
+                TARGET='i386'
+            elif [[ ${TARGET} == 'X86_64' ]];then
+                TARGET='x86_64'
+            elif [[ ${TARGET} == 'ARMV7_VFP' ]];then
+                TARGET='armv7'
+            elif [[ ${TARGET} == 'THUMBV7_VFP' ]];then
+                TARGET='thumbv7'
+            elif [[ ${TARGET} == 'RISCV64' || ${TARGET} == 'RISCV64_LP64D' ]];then
+                TARGET='riscv64_lp64d'
+            elif [[ ${TARGET} == 'RISCV64_LP64' ]];then
+                TARGET='riscv64_lp64'
+            else
+                usage
+            fi
+            ;;
+        M) ENABLE_MULTI_MODULE=1 ;;
+        x) SGX_OPT="--sgx" ;;
+        S) SIMD_OPT="--simd" ;;
+        r) REF_TYPES_OPT="--ref_types" ;;
+        *) usage ;;
+    esac
+done
+
+function contain()
+{
+    # [$1, $-1)
+    local list=${@:0:${#}}
+    # [$-1]
+    local item=${@:${#}}
+    [[ ${list} =~ (^| )${item}($| ) ]] && return 0 || return 1
+}
+
+if [[ ${SGX_OPT} ]];then
+    IWASM_CMD="../../../product-mini/platforms/linux-sgx/enclave-sample/iwasm"
+    IGNORE_LIST+=("${SGX_IGNORE_LIST[@]}")
+    if [[ "true" == ${AOT} ]];then
+        IGNORE_LIST+=("${SGX_AOT_IGNORE_LIST[@]}")
+    fi
+fi
+
+declare -i COUNTER=0
+for wast in $(find ${SPEC_TEST_DIR} -name "*.wast" -type f | sort -n); do
+    # remove a prefix spec/test/core/
+    wast=${wast#${SPEC_TEST_DIR}/}
+    # ${wast%.wast} will remove a surfix .wast
+    if contain "${IGNORE_LIST[@]}" ${wast%.wast}; then
+        echo "============> ignore ${wast}"
+        continue
+    else
+        [[ "true" == ${AOT} ]] && run_case_w_aot ${wast} \
+            || run_case_wo_aot ${wast}
+        (( COUNTER += 1))
+    fi
+done
+
+# for now, Multi_Module is always disabled while AOT is true
+if [[ "false" == ${AOT} && 1 == ${ENABLE_MULTI_MODULE} ]]; then
+    echo "============> run cases about multi module"
+    for wast in ${MULTI_MODULE_LIST[@]}; do
+        run_case_wo_aot ${wast}.wast
+        (( COUNTER += 1))
+    done
+fi
+
+echo "PASS ALL ${COUNTER} SPEC CASES"
+DEBUG set -xevu
+exit 0

+ 804 - 0
tests/wamr-test-suites/spec-test-script/ignore_cases.patch

@@ -0,0 +1,804 @@
+diff --git a/test/core/binary.wast b/test/core/binary.wast
+index c6f9755..a479212 100644
+--- a/test/core/binary.wast
++++ b/test/core/binary.wast
+@@ -161,7 +161,7 @@
+ )
+ 
+ ;; Type section with signed LEB128 encoded type
+-(assert_malformed
++(;assert_malformed
+   (module binary
+     "\00asm" "\01\00\00\00"
+     "\01"                     ;; Type section id
+@@ -171,7 +171,7 @@
+     "\00\00"
+   )
+   "integer representation too long"
+-)
++;)
+ 
+ ;; Unsigned LEB128 must not be overlong
+ (assert_malformed
+@@ -1582,7 +1582,7 @@
+ )
+ 
+ ;; 2 elem segment declared, 1 given
+-(assert_malformed
++(;assert_malformed
+   (module binary
+     "\00asm" "\01\00\00\00"
+     "\01\04\01"                             ;; type section
+@@ -1595,7 +1595,7 @@
+     ;; "\00\41\00\0b\01\00"                 ;; elem 1 (missed)
+   )
+   "unexpected end"
+-)
++;)
+ 
+ ;; 2 elem segment declared, 1.5 given
+ (assert_malformed
+diff --git a/test/core/data.wast b/test/core/data.wast
+index 4f339be..0b5b3e6 100644
+--- a/test/core/data.wast
++++ b/test/core/data.wast
+@@ -306,9 +306,10 @@
+     "\02\01\41\00\0b"                       ;; active data segment 0 for memory 1
+     "\00"                                   ;; empty vec(byte)
+   )
+-  "unknown memory 1"
++  "unknown memory"
+ )
+ 
++(; not supported by wat2wasm
+ ;; Data segment with memory index 0 (no memory section)
+ (assert_invalid
+   (module binary
+@@ -317,7 +318,7 @@
+     "\00\41\00\0b"                          ;; active data segment 0 for memory 0
+     "\00"                                   ;; empty vec(byte)
+   )
+-  "unknown memory 0"
++  "unknown memory"
+ )
+ 
+ ;; Data segment with memory index 1 (no memory section)
+@@ -328,7 +329,7 @@
+     "\02\01\41\00\0b"                       ;; active data segment 0 for memory 1
+     "\00"                                   ;; empty vec(byte)
+   )
+-  "unknown memory 1"
++  "unknown memory"
+ )
+ 
+ ;; Data segment with memory index 1 and vec(byte) as above,
+@@ -348,7 +349,7 @@
+     "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f"
+     "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d"
+   )
+-  "unknown memory 1"
++  "unknown memory"
+ )
+ 
+ ;; Data segment with memory index 1 and specially crafted vec(byte) after.
+@@ -368,8 +369,9 @@
+     "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f"
+     "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d"
+   )
+-  "unknown memory 1"
++  "unknown memory"
+ )
++;)
+ 
+ 
+ ;; Invalid offsets
+diff --git a/test/core/elem.wast b/test/core/elem.wast
+index 575ecef..204b748 100644
+--- a/test/core/elem.wast
++++ b/test/core/elem.wast
+@@ -467,6 +467,7 @@
+   "type mismatch"
+ )
+ 
++(; not supported by wat2wasm
+ (assert_invalid
+   (module
+     (table 1 funcref)
+@@ -507,6 +508,7 @@
+   )
+   "constant expression required"
+ )
++;)
+ 
+ ;; Two elements target the same slot
+ 
+@@ -571,9 +573,11 @@
+   (func $const-i32-d (type $out-i32) (i32.const 68))
+ )
+ 
++(;
+ (assert_return (invoke $module1 "call-7") (i32.const 67))
+ (assert_return (invoke $module1 "call-8") (i32.const 68))
+ (assert_return (invoke $module1 "call-9") (i32.const 66))
++;)
+ 
+ (module $module3
+   (type $out-i32 (func (result i32)))
+@@ -584,6 +588,8 @@
+   (func $const-i32-f (type $out-i32) (i32.const 70))
+ )
+ 
++(;
+ (assert_return (invoke $module1 "call-7") (i32.const 67))
+ (assert_return (invoke $module1 "call-8") (i32.const 69))
+ (assert_return (invoke $module1 "call-9") (i32.const 70))
++;)
+diff --git a/test/core/global.wast b/test/core/global.wast
+index 9fa5e22..8c4b949 100644
+--- a/test/core/global.wast
++++ b/test/core/global.wast
+@@ -328,10 +328,12 @@
+   "type mismatch"
+ )
+ 
++(;
+ (assert_invalid
+   (module (global (import "" "") externref) (global funcref (global.get 0)))
+   "type mismatch"
+ )
++;)
+ 
+ (assert_invalid
+   (module (global (import "test" "global-i32") i32) (global i32 (global.get 0) (global.get 0)))
+diff --git a/test/core/imports.wast b/test/core/imports.wast
+index 35e8c91..a7a459d 100644
+--- a/test/core/imports.wast
++++ b/test/core/imports.wast
+@@ -577,6 +577,7 @@
+ (assert_return (invoke "grow" (i32.const 1)) (i32.const -1))
+ (assert_return (invoke "grow" (i32.const 0)) (i32.const 2))
+ 
++(; unsupported by multi-module currently
+ (module $Mgm
+   (memory (export "memory") 1) ;; initial size is 1
+   (func (export "grow") (result i32) (memory.grow (i32.const 1)))
+@@ -596,6 +597,7 @@
+   (func (export "size") (result i32) (memory.size))
+ )
+ (assert_return (invoke $Mgim2 "size") (i32.const 3))
++;)
+ 
+ 
+ ;; Syntax errors
+diff --git a/test/core/linking.wast b/test/core/linking.wast
+index 994e0f4..d0bfb5f 100644
+--- a/test/core/linking.wast
++++ b/test/core/linking.wast
+@@ -64,6 +64,7 @@
+   (export "Mg.set_mut" (func $set_mut))
+ )
+ 
++(;
+ (assert_return (get $Mg "glob") (i32.const 42))
+ (assert_return (get $Ng "Mg.glob") (i32.const 42))
+ (assert_return (get $Ng "glob") (i32.const 43))
+@@ -81,6 +82,7 @@
+ (assert_return (get $Ng "Mg.mut_glob") (i32.const 241))
+ (assert_return (invoke $Mg "get_mut") (i32.const 241))
+ (assert_return (invoke $Ng "Mg.get_mut") (i32.const 241))
++;)
+ 
+ 
+ (assert_unlinkable
+@@ -165,6 +167,7 @@
+   )
+ )
+ 
++(;
+ (assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4))
+ (assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4))
+ (assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5))
+@@ -187,6 +190,7 @@
+ 
+ (assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4))
+ (assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch")
++;)
+ 
+ (module $Ot
+   (type (func (result i32)))
+@@ -201,6 +205,7 @@
+   )
+ )
+ 
++(;
+ (assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4))
+ (assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4))
+ (assert_return (invoke $Nt "call Mt.call" (i32.const 3)) (i32.const 4))
+@@ -225,6 +230,7 @@
+ (assert_trap (invoke $Ot "call" (i32.const 0)) "uninitialized element")
+ 
+ (assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element")
++;)
+ 
+ (module
+   (table (import "Mt" "tab") 0 funcref)
+@@ -263,6 +269,7 @@
+ 
+ ;; Unlike in the v1 spec, active element segments stored before an
+ ;; out-of-bounds access persist after the instantiation failure.
++(;
+ (assert_trap
+   (module
+     (table (import "Mt" "tab") 10 funcref)
+@@ -274,7 +281,9 @@
+ )
+ (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0))
+ (assert_trap (invoke $Mt "call" (i32.const 8)) "uninitialized element")
++;)
+ 
++(;
+ (assert_trap
+   (module
+     (table (import "Mt" "tab") 10 funcref)
+@@ -286,6 +295,7 @@
+   "out of bounds memory access"
+ )
+ (assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0))
++;)
+ 
+ 
+ (module $Mtable_ex
+@@ -299,6 +309,7 @@
+   (table (import "Mtable_ex" "t-extern") 1 externref)
+ )
+ 
++(;
+ (assert_unlinkable
+   (module (table (import "Mtable_ex" "t-func") 1 externref))
+   "incompatible import type"
+@@ -307,6 +318,7 @@
+   (module (table (import "Mtable_ex" "t-extern") 1 funcref))
+   "incompatible import type"
+ )
++;)
+ 
+ 
+ ;; Memories
+@@ -346,10 +358,12 @@
+   )
+ )
+ 
++(;
+ (assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7))
+ (assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7))
+ (assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2))
+ (assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7))
++;)
+ 
+ (module
+   (memory (import "Mm" "mem") 0)
+@@ -372,6 +386,7 @@
+   )
+ )
+ 
++(;
+ (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1))
+ (assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1))
+ (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3))
+@@ -380,6 +395,7 @@
+ (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5))
+ (assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1))
+ (assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5))
++;)
+ 
+ (assert_unlinkable
+   (module
+@@ -403,8 +419,10 @@
+   )
+   "out of bounds memory access"
+ )
++(;
+ (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97))
+ (assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0))
++;)
+ 
+ (assert_trap
+   (module
+@@ -416,7 +434,9 @@
+   )
+   "out of bounds table access"
+ )
++(;
+ (assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97))
++;)
+ 
+ ;; Store is modified if the start function traps.
+ (module $Ms
+@@ -432,6 +452,7 @@
+ )
+ (register "Ms" $Ms)
+ 
++(;
+ (assert_trap
+   (module
+     (import "Ms" "memory" (memory 1))
+@@ -451,3 +472,4 @@
+ 
+ (assert_return (invoke $Ms "get memory[0]") (i32.const 104))  ;; 'h'
+ (assert_return (invoke $Ms "get table[0]") (i32.const 0xdead))
++;)
+diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast
+index adb5cb7..590f626 100644
+--- a/test/core/ref_func.wast
++++ b/test/core/ref_func.wast
+@@ -4,7 +4,8 @@
+ (register "M")
+ 
+ (module
+-  (func $f (import "M" "f") (param i32) (result i32))
++  (; aot mode does not support module linking ;)
++  (func $f (param $x i32) (result i32) (local.get $x))
+   (func $g (param $x i32) (result i32)
+     (i32.add (local.get $x) (i32.const 1))
+   )
+diff --git a/test/core/select.wast b/test/core/select.wast
+index 046e6fe..b677023 100644
+--- a/test/core/select.wast
++++ b/test/core/select.wast
+@@ -324,6 +324,7 @@
+   (module (func $arity-0 (select (result) (nop) (nop) (i32.const 1))))
+   "invalid result arity"
+ )
++(;
+ (assert_invalid
+   (module (func $arity-2 (result i32 i32)
+     (select (result i32 i32)
+@@ -334,6 +335,7 @@
+   ))
+   "invalid result arity"
+ )
++;)
+ 
+ 
+ (assert_invalid
+diff --git a/test/core/table_copy.wast b/test/core/table_copy.wast
+index 380e84e..f37e745 100644
+--- a/test/core/table_copy.wast
++++ b/test/core/table_copy.wast
+@@ -14,11 +14,12 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  ;; aot mode does not support module linking
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -106,11 +107,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (export "ef0") (result i32) (i32.const 0))    ;; index 0
++  (func (export "ef1") (result i32) (i32.const 1))
++  (func (export "ef2") (result i32) (i32.const 2))
++  (func (export "ef3") (result i32) (i32.const 3))
++  (func (export "ef4") (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -198,11 +199,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -290,11 +291,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -382,11 +383,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -474,11 +475,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -566,11 +567,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -658,11 +659,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -750,11 +751,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -842,11 +843,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -934,11 +935,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -1026,11 +1027,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -1118,11 +1119,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -1210,11 +1211,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -1302,11 +1303,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -1394,11 +1395,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -1486,11 +1487,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -1578,11 +1579,11 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))     ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+diff --git a/test/core/table_init.wast b/test/core/table_init.wast
+index 0b2d26f..bdab6a0 100644
+--- a/test/core/table_init.wast
++++ b/test/core/table_init.wast
+@@ -14,11 +14,12 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  ;; aot mode does not support module linking
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))    ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -72,11 +73,12 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  ;; aot mode does not support module linking
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))    ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -130,11 +132,12 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  ;; aot mode does not support module linking
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))    ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t0) (i32.const 2) func 3 1 4 1)
+@@ -196,11 +199,12 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  ;; aot mode does not support module linking
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))    ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -254,11 +258,12 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  ;; aot mode does not support module linking
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))    ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+@@ -312,11 +317,12 @@
+ 
+ (module
+   (type (func (result i32)))  ;; type #0
+-  (import "a" "ef0" (func (result i32)))    ;; index 0
+-  (import "a" "ef1" (func (result i32)))
+-  (import "a" "ef2" (func (result i32)))
+-  (import "a" "ef3" (func (result i32)))
+-  (import "a" "ef4" (func (result i32)))    ;; index 4
++  ;; aot mode does not support module linking
++  (func (result i32) (i32.const 0))    ;; index 0
++  (func (result i32) (i32.const 1))
++  (func (result i32) (i32.const 2))
++  (func (result i32) (i32.const 3))
++  (func (result i32) (i32.const 4))    ;; index 4
+   (table $t0 30 30 funcref)
+   (table $t1 30 30 funcref)
+   (elem (table $t1) (i32.const 2) func 3 1 4 1)
+diff --git a/test/core/unreached-valid.wast b/test/core/unreached-valid.wast
+index 0025217..07d2788 100644
+--- a/test/core/unreached-valid.wast
++++ b/test/core/unreached-valid.wast
+@@ -46,6 +46,7 @@
+ 
+ ;; Validation after unreachable
+ 
++(;
+ (module
+   (func (export "meet-bottom")
+     (block (result f64)
+@@ -59,4 +60,5 @@
+     (drop)
+   )
+ )
++;)
+ 

+ 1280 - 0
tests/wamr-test-suites/spec-test-script/runtest.py

@@ -0,0 +1,1280 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+import os, sys, re
+import argparse, time
+import signal, atexit, tempfile, subprocess
+
+from subprocess import Popen, STDOUT, PIPE
+from select import select
+
+# Pseudo-TTY and terminal manipulation
+import pty, array, fcntl, termios
+
+import shutil
+
+import struct
+import math
+import traceback
+
+IS_PY_3 = sys.version_info[0] == 3
+
+test_aot = False
+# "x86_64", "i386", "aarch64", "armv7" or "thumbv7"
+test_target = "x86_64"
+
+debug_file = None
+log_file = None
+
+# to save the register module with self-define name
+temp_file_repo = []
+
+# get current work directory
+current_work_directory = os.getcwd()
+# set temporal file directory
+temp_file_directory = os.path.join(current_work_directory,"tempfile")
+
+def debug(data):
+    if debug_file:
+        debug_file.write(data)
+        debug_file.flush()
+
+def log(data, end='\n'):
+    if log_file:
+        log_file.write(data + end)
+        log_file.flush()
+    print(data, end=end)
+    sys.stdout.flush()
+
+# TODO: do we need to support '\n' too
+import platform
+if platform.system().find("CYGWIN_NT") >= 0:
+    # TODO: this is weird, is this really right on Cygwin?
+    sep = "\n\r\n"
+else:
+    sep = "\r\n"
+rundir = None
+
+class Runner():
+    def __init__(self, args, no_pty=False):
+        #print "args: %s" % repr(args)
+        self.no_pty = no_pty
+
+        # Cleanup child process on exit
+        atexit.register(self.cleanup)
+
+        self.p = None
+        env = os.environ
+        env['TERM'] = 'dumb'
+        env['INPUTRC'] = '/dev/null'
+        env['PERL_RL'] = 'false'
+        if no_pty:
+            self.p = Popen(args, bufsize=0,
+                           stdin=PIPE, stdout=PIPE, stderr=STDOUT,
+                           preexec_fn=os.setsid,
+                           env=env)
+            self.stdin = self.p.stdin
+            self.stdout = self.p.stdout
+        else:
+            # provide tty to get 'interactive' readline to work
+            master, slave = pty.openpty()
+
+            # Set terminal size large so that readline will not send
+            # ANSI/VT escape codes when the lines are long.
+            buf = array.array('h', [100, 200, 0, 0])
+            fcntl.ioctl(master, termios.TIOCSWINSZ, buf, True)
+
+            self.p = Popen(args, bufsize=0,
+                           stdin=slave, stdout=slave, stderr=STDOUT,
+                           preexec_fn=os.setsid,
+                           env=env)
+            # Now close slave so that we will get an exception from
+            # read when the child exits early
+            # http://stackoverflow.com/questions/11165521
+            os.close(slave)
+            self.stdin = os.fdopen(master, 'r+b', 0)
+            self.stdout = self.stdin
+
+        #print "started"
+        self.buf = ""
+        self.last_prompt = ""
+
+    def read_to_prompt(self, prompts, timeout):
+        end_time = time.time() + timeout
+        while time.time() < end_time:
+            [outs,_,_] = select([self.stdout], [], [], 1)
+            if self.stdout in outs:
+                new_data = self.stdout.read(1)
+                new_data = new_data.decode("utf-8") if IS_PY_3 else new_data
+                #print("new_data: '%s'" % new_data)
+                debug(new_data)
+                if self.no_pty:
+                    self.buf += new_data.replace("\n", "\r\n")
+                else:
+                    self.buf += new_data
+                self.buf = self.buf.replace("\r\r", "\r")
+                for prompt in prompts:
+                    regexp = re.compile(prompt)
+                    match = regexp.search(self.buf)
+                    if match:
+                        end = match.end()
+                        buf = self.buf[0:end-len(prompt)]
+                        self.buf = self.buf[end:]
+                        self.last_prompt = prompt
+                        return buf
+        return None
+
+    def writeline(self, str):
+        def _to_bytes(s):
+            return bytes(s, "utf-8") if IS_PY_3 else s
+
+        self.stdin.write(_to_bytes(str + "\n"))
+
+    def cleanup(self):
+        if self.p:
+            try:
+                self.writeline("__exit__")
+                time.sleep(.020)
+                os.killpg(self.p.pid, signal.SIGTERM)
+            except OSError:
+                pass
+            self.p = None
+            sys.exc_clear()
+
+def assert_prompt(runner, prompts, timeout, is_need_execute_result):
+    # Wait for the initial prompt
+    header = runner.read_to_prompt(prompts, timeout=timeout)
+    if not header and is_need_execute_result:
+        log(" ---------- will terminate cause the case needs result while there is none inside of buf. ----------")
+        sys.exit(1)
+    if not header == None:
+        if header:
+            log("Started with:\n%s" % header)
+    else:
+        log("Did not one of following prompt(s): %s" % repr(prompts))
+        log("    Got      : %s" % repr(r.buf))
+        sys.exit(1)
+
+
+### WebAssembly specific
+
+parser = argparse.ArgumentParser(
+        description="Run a test file against a WebAssembly interpreter")
+parser.add_argument('--wast2wasm', type=str,
+        default=os.environ.get("WAST2WASM", "wast2wasm"),
+        help="Path to wast2wasm program")
+parser.add_argument('--interpreter', type=str,
+        default=os.environ.get("IWASM_CMD", "iwasm"),
+        help="Path to WebAssembly interpreter")
+parser.add_argument('--aot-compiler', type=str,
+        default=os.environ.get("WAMRC_CMD", "wamrc"),
+        help="Path to WebAssembly AoT compiler")
+
+parser.add_argument('--no_cleanup', action='store_true',
+        help="Keep temporary *.wasm files")
+
+parser.add_argument('--rundir',
+        help="change to the directory before running tests")
+parser.add_argument('--start-timeout', default=30, type=int,
+        help="default timeout for initial prompt")
+parser.add_argument('--test-timeout', default=20, type=int,
+        help="default timeout for each individual test action")
+parser.add_argument('--no-pty', action='store_true',
+        help="Use direct pipes instead of pseudo-tty")
+parser.add_argument('--log-file', type=str,
+        help="Write messages to the named file in addition the screen")
+parser.add_argument('--debug-file', type=str,
+        help="Write all test interaction the named file")
+
+parser.add_argument('test_file', type=argparse.FileType('r'),
+        help="a WebAssembly *.wast test file")
+
+parser.add_argument('--aot', action='store_true',
+        help="Test with AOT")
+
+parser.add_argument('--aot-target', type=str,
+        default="x86_64",
+        help="Set aot target")
+
+parser.add_argument('--sgx', action='store_true',
+        help="Test SGX")
+
+parser.add_argument('--simd', default=False, action='store_true',
+        help="Enable SIMD")
+
+parser.add_argument('--ref_types', default=False, action='store_true',
+        help="Enable Reference types")
+
+parser.add_argument('--verbose', default=False, action='store_true',
+        help='show more logs')
+
+# regex patterns of tests to skip
+C_SKIP_TESTS = ()
+PY_SKIP_TESTS = (
+        # names.wast
+        'invoke \"~!',
+        # conversions.wast
+        '18446742974197923840.0',
+        '18446744073709549568.0',
+        '9223372036854775808',
+        'reinterpret_f.*nan',
+        # endianness
+        '.const 0x1.fff' )
+
+def read_forms(string):
+    forms = []
+    form = ""
+    depth = 0
+    line = 0
+    pos = 0
+    while pos < len(string):
+        # Keep track of line number
+        if string[pos] == '\n': line += 1
+
+        # Handle top-level elements
+        if depth == 0:
+            # Add top-level comments
+            if string[pos:pos+2] == ";;":
+                end = string.find("\n", pos)
+                if end == -1: end == len(string)
+                forms.append(string[pos:end])
+                pos = end
+                continue
+
+            # TODO: handle nested multi-line comments
+            if string[pos:pos+2] == "(;":
+                # Skip multi-line comment
+                end = string.find(";)", pos)
+                if end == -1:
+                    raise Exception("mismatch multiline comment on line %d: '%s'" % (
+                        line, string[pos:pos+80]))
+                pos = end+2
+                continue
+
+            # Ignore whitespace between top-level forms
+            if string[pos] in (' ', '\n', '\t'):
+                pos += 1
+                continue
+
+        # Read a top-level form
+        if string[pos] == '(': depth += 1
+        if string[pos] == ')': depth -= 1
+        if depth == 0 and not form:
+            raise Exception("garbage on line %d: '%s'" % (
+                line, string[pos:pos+80]))
+        form += string[pos]
+        if depth == 0 and form:
+            forms.append(form)
+            form = ""
+        pos += 1
+    return forms
+
+def get_module_exp_from_assert(string):
+    depth = 0
+    pos = 0
+    module = ""
+    exception = ""
+    start_record = False
+    result = []
+    while pos < len(string):
+        # record from the " (module "
+        if string[pos:pos+7] == "(module":
+            start_record = True
+        if start_record:
+            if string[pos] == '(' : depth += 1
+            if string[pos] == ')' : depth -= 1
+            module += string[pos]
+            # if we get all (module ) .
+            if depth == 0 and module:
+                result.append(module)
+                start_record = False
+        # get expected exception
+        if string[pos] == '"':
+            end = string.find("\"", pos+1)
+            if end != -1:
+                end_rel = string.find("\"",end+1)
+                if end_rel == -1:
+                    result.append(string[pos+1:end])
+        pos += 1
+    return result
+
+def string_to_unsigned(number_in_string, lane_type):
+    if not lane_type in ['i8x16', 'i16x8', 'i32x4', 'i64x2']:
+        raise Exception("invalid value {} and type {} and lane_type {}".format(numbers, type, lane_type))
+
+    number = int(number_in_string, 16) if '0x' in number_in_string else int(number_in_string)
+
+    if "i8x16" == lane_type:
+        if number < 0:
+            packed = struct.pack('b', number)
+            number = struct.unpack('B', packed)[0]
+    elif "i16x8" == lane_type:
+        if number < 0:
+            packed = struct.pack('h', number)
+            number = struct.unpack('H', packed)[0]
+    elif "i32x4" == lane_type:
+        if number < 0:
+            packed = struct.pack('i', number)
+            number = struct.unpack('I', packed)[0]
+    else: # "i64x2" == lane_type:
+        if number < 0:
+            packed = struct.pack('q', number)
+            number = struct.unpack('Q', packed)[0]
+
+    return number
+
+def cast_v128_to_i64x2(numbers, type, lane_type):
+    numbers = [n.replace("_", "") for n in numbers]
+
+    if "i8x16" == lane_type:
+        assert(16 == len(numbers)), "{} should like {}".format(numbers, lane_type)
+        # str -> int
+        numbers = [string_to_unsigned(n, lane_type) for n in numbers]
+        # i8 -> i64
+        packed = struct.pack(16 * "B", *numbers)
+    elif "i16x8" == lane_type:
+        assert(8 == len(numbers)), "{} should like {}".format(numbers, lane_type)
+        # str -> int
+        numbers = [string_to_unsigned(n, lane_type) for n in numbers]
+        # i16 -> i64
+        packed = struct.pack(8 * "H", *numbers)
+    elif "i32x4" == lane_type:
+        assert(4 == len(numbers)), "{} should like {}".format(numbers, lane_type)
+        # str -> int
+        numbers = [string_to_unsigned(n, lane_type) for n in numbers]
+        # i32 -> i64
+        packed = struct.pack(4 * "I", *numbers)
+    elif "i64x2" == lane_type:
+        assert(2 == len(numbers)), "{} should like {}".format(numbers, lane_type)
+        # str -> int
+        numbers = [string_to_unsigned(n, lane_type) for n in numbers]
+        # i64 -> i64
+        packed = struct.pack(2 * "Q", *numbers)
+    elif "f32x4" == lane_type:
+        assert(4 == len(numbers)), "{} should like {}".format(numbers, lane_type)
+        # str -> int
+        numbers = [parse_simple_const_w_type(n, "f32")[0] for n in numbers]
+        # f32 -> i64
+        packed = struct.pack(4 * "f", *numbers)
+    elif "f64x2" == lane_type:
+        assert(2 == len(numbers)), "{} should like {}".format(numbers, lane_type)
+        # str -> int
+        numbers = [parse_simple_const_w_type(n, "f64")[0] for n in numbers]
+        # f64 -> i64
+        packed = struct.pack(2 * "d", *numbers)
+    else:
+        raise Exception("invalid value {} and type {} and lane_type {}".format(numbers, type, lane_type))
+
+    assert(packed)
+    unpacked = struct.unpack("Q Q", packed)
+    return unpacked, "[{} {}]:{}:v128".format(unpacked[0], unpacked[1], lane_type)
+
+
+def parse_simple_const_w_type(number, type):
+    number = number.replace('_', '')
+    if type in ["i32", "i64"]:
+        number = int(number, 16) if '0x' in number else int(number)
+        return number, "0x{:x}:{}".format(number, type) \
+                   if number >= 0 \
+                   else "-0x{:x}:{}".format(0 - number, type)
+    elif type in ["f32", "f64"]:
+        if "nan:" in number:
+            # TODO: how to handle this correctly
+            if "nan:canonical" in number:
+                return float.fromhex("0x200000"), "nan:{}".format(type)
+            elif "nan:arithmetic" in number:
+                return float.fromhex("-0x200000"), "nan:{}".format(type)
+            else:
+                return float('nan'), "nan:{}".format(type)
+        else:
+            number = float.fromhex(number) if '0x' in number else float(number)
+            return number, "{:.7g}:{}".format(number, type)
+    elif type == "ref.null":
+        # hard coding
+        return "extern", "extern:ref.null"
+    elif type == "ref.extern":
+        number = int(number, 16) if '0x' in number else int(number)
+        return number, "0x{:x}:ref.extern".format(number)
+    else:
+        raise Exception("invalid value {} and type {}".format(number, type))
+
+def parse_assertion_value(val):
+    """
+    Parse something like:
+    "ref.null extern" in (assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern))
+    "ref.extern 1" in (assert_return (invoke "get-externref" (i32.const 1)) (ref.extern 1))
+    "i32.const 0" in (assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0))
+
+    in summary:
+    type.const (sub-type) (val1 val2 val3 val4) ...
+    type.const val
+    ref.extern val
+    ref.null ref_type
+    """
+    if not val:
+        return None, ""
+
+    splitted = re.split('\s+', val)
+    splitted = [s for s in splitted if s]
+    type = splitted[0].split(".")[0]
+    lane_type = splitted[1] if len(splitted) > 2 else ""
+    numbers = splitted[2:] if len(splitted) > 2 else splitted[1:]
+
+    if type in ["i32", "i64", "f32", "f64"]:
+        return parse_simple_const_w_type(numbers[0], type)
+    elif type == "ref":
+        # need to distinguish between "ref.null" and "ref.extern"
+        return parse_simple_const_w_type(numbers[0], splitted[0])
+    else:
+        return cast_v128_to_i64x2(numbers, type, lane_type)
+
+def int2uint32(i):
+    return i & 0xffffffff
+
+def int2int32(i):
+    val = i & 0xffffffff
+    if val & 0x80000000:
+        return val - 0x100000000
+    else:
+        return val
+
+def int2uint64(i):
+    return i & 0xffffffffffffffff
+
+def int2int64(i):
+    val = i & 0xffffffffffffffff
+    if val & 0x8000000000000000:
+        return val - 0x10000000000000000
+    else:
+        return val
+
+
+def num_repr(i):
+    if isinstance(i, int) or isinstance(i, long):
+        return re.sub("L$", "", hex(i))
+    else:
+        return "%.16g" % i
+
+def hexpad16(i):
+    return "0x%04x" % i
+
+def hexpad24(i):
+    return "0x%06x" % i
+
+def hexpad32(i):
+    return "0x%08x" % i
+
+def hexpad64(i):
+    return "0x%016x" % i
+
+def invoke(r, args, cmd):
+    r.writeline(cmd)
+
+    return r.read_to_prompt(['\r\nwebassembly> ', '\nwebassembly> '],
+                            timeout=args.test_timeout)
+
+def vector_value_comparison(out, expected):
+    """
+    out likes "<number number>:v128"
+    expected likes "[number number]:v128"
+    """
+    # print("vector value comparision {} vs {}".format(out, expected))
+
+    out_val, out_type = out.split(':')
+    # <number nubmer> => number number
+    out_val = out_val[1:-1]
+
+    expected_val, lane_type, expected_type = expected.split(':')
+    # [number nubmer] => number number
+    expected_val = expected_val[1:-1]
+
+    assert("v128" == out_type), "out_type should be v128"
+    assert("v128" == expected_type), "expected_type should be v128"
+
+    if out_type != expected_type:
+        return False
+
+    if out_val == expected_val:
+        return True
+
+    out_val = out_val.split(" ")
+    expected_val = expected_val.split(" ")
+
+    # since i64x2
+    out_packed = struct.pack("QQ", int(out_val[0], 16), int(out_val[1], 16))
+    expected_packed = struct.pack("QQ",
+        int(expected_val[0]) if not "0x" in expected_val[0] else int(expected_val[0], 16),
+        int(expected_val[1]) if not "0x" in expected_val[1] else int(expected_val[1], 16))
+
+    if lane_type in ["i8x16", "i16x8", "i32x4", "i64x2"]:
+        return out_packed == expected_packed;
+    else:
+        assert(lane_type in ["f32x4", "f64x2"]), "unexpected lane_type"
+
+        if "f32x4" == lane_type:
+            out_unpacked = struct.unpack("ffff", out_packed)
+            expected_unpacked = struct.unpack("ffff", expected_packed)
+        else:
+            out_unpacked = struct.unpack("dd", out_packed)
+            expected_unpacked = struct.unpack("dd", expected_packed)
+
+        out_is_nan = [math.isnan(o) for o in out_unpacked]
+        expected_is_nan = [math.isnan(e) for e in expected_unpacked]
+        if out_is_nan and expected_is_nan:
+            return True;
+
+        # print("compare {} and {}".format(out_unpacked, expected_unpacked))
+        result = [o == e for o, e in zip(out_unpacked, expected_unpacked)]
+
+        if not all(result):
+            result = [
+                "{:.7g}".format(o) == "{:.7g}".format(e)
+                for o, e in zip(out_unpacked, expected_packed)
+            ]
+
+        return all(result)
+
+
+def simple_value_comparison(out, expected):
+    """
+    compare out of simple types which may like val:i32, val:f64 and so on
+    """
+    if expected == "2.360523e+13:f32" and out == "2.360522e+13:f32":
+        # one case in float_literals.wast, due to float precision of python
+        return True
+
+    if expected == "1.797693e+308:f64" and out == "inf:f64":
+        # one case in float_misc.wast:
+        # (assert_return (invoke "f64.add" (f64.const 0x1.fffffffffffffp+1023)
+        #                                  (f64.const 0x1.fffffffffffffp+969))
+        #                                  (f64.const 0x1.fffffffffffffp+1023))
+        # the add result in x86_32 is inf
+        return True
+
+    out_val, out_type = out.split(':')
+    expected_val, expected_type = expected.split(':')
+
+    if not out_type == expected_type:
+        return False
+
+    out_val, _ = parse_simple_const_w_type(out_val, out_type)
+    expected_val, _ = parse_simple_const_w_type(expected_val, expected_type)
+
+    if out_val == expected_val \
+        or (math.isnan(out_val) and math.isnan(expected_val)):
+        return True
+
+    if "i32" == expected_type:
+        out_val_binary = struct.pack('I', out_val) if out_val > 0 \
+                            else struct.pack('i', out_val)
+        expected_val_binary = struct.pack('I', expected_val) \
+                                if expected_val > 0 \
+                                    else struct.pack('i', expected_val)
+    elif "i64" == expected_type:
+        out_val_binary = struct.pack('Q', out_val) if out_val > 0 \
+                            else struct.pack('q', out_val)
+        expected_val_binary = struct.pack('Q', expected_val) \
+                                if expected_val > 0 \
+                                    else struct.pack('q', expected_val)
+    elif "f32" == expected_type:
+        out_val_binary = struct.pack('f', out_val)
+        expected_val_binary = struct.pack('f', expected_val)
+    elif "f64" == expected_type:
+        out_val_binary = struct.pack('d', out_val)
+        expected_val_binary = struct.pack('d', expected_val)
+    elif "ref.extern" == expected_type:
+        out_val_binary = out_val
+        expected_val_binary = expected_val
+    else:
+        assert(0), "unknown 'expected_type' {}".format(expected_type)
+
+    if out_val_binary == expected_val_binary:
+        return True
+
+    if expected_type in ["f32", "f64"]:
+        # compare with a lower precision
+        out_str = "{:.7g}".format(out_val)
+        expected_str = "{:.7g}".format(expected_val)
+        if out_str == expected_str:
+            return True
+
+    return False
+
+def value_comparison(out, expected):
+    if out == expected:
+        return True
+
+    if not expected:
+        return False
+
+    assert(':' in out), "out should be in a form likes numbers:type, but {}".format(out)
+    assert(':' in expected), "expected should be in a form likes numbers:type, but {}".format(expected)
+
+    if 'v128' in out:
+        return vector_value_comparison(out, expected)
+    else:
+        return simple_value_comparison(out, expected)
+
+def is_result_match_expected(out, expected):
+    # compare value instead of comparing strings of values
+    return value_comparison(out, expected)
+
+def test_assert(r, opts, mode, cmd, expected):
+    log("Testing(%s) %s = %s" % (mode, cmd, expected))
+
+    out = invoke(r, opts, cmd)
+    outs = [''] + out.split('\n')[1:]
+    out = outs[-1]
+
+    if mode=='trap':
+        o = re.sub('^Exception: ', '', out)
+        e = re.sub('^Exception: ', '', expected)
+        if o.find(e) >= 0 or e.find(o) >= 0:
+            return True
+
+    if mode=='exhaustion':
+        o = re.sub('^Exception: ', '', out)
+        expected = 'Exception: stack overflow'
+        e = re.sub('^Exception: ', '', expected)
+        if o.find(e) >= 0 or e.find(o) >= 0:
+            return True
+
+    ## 0x9:i32,-0x1:i32 -> ['0x9:i32', '-0x1:i32']
+    expected_list = re.split(',', expected)
+    out_list = re.split(',', out)
+    if len(expected_list) != len(out_list):
+        raise Exception("Failed:\n Results count incorrect:\n expected: '%s'\n  got: '%s'" % (expected, out))
+    for i in range(len(expected_list)):
+        if not is_result_match_expected(out_list[i], expected_list[i]):
+            raise Exception("Failed:\n Result %d incorrect:\n expected: '%s'\n  got: '%s'" % (i, expected_list[i], out_list[i]))
+
+    return True
+
+def test_assert_return(r, opts, form):
+    """
+    m. to search a pattern like (assert_return (invoke function_name ... ) ...)
+    n. to search a pattern like (assert_return (invoke $module_name function_name ... ) ...)
+    """
+    # params, return
+    m = re.search('^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S)
+    # judge if assert_return cmd includes the module name
+    n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s+(\(.*\))\s*\)\s*(\(.*\))\s*\)\s*$', form, re.S)
+
+    # print("assert_return with {}".format(form))
+
+    if not m:
+        # no params, return
+        m = re.search('^\(assert_return\s+\(invoke\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S)
+    if not m:
+        # params, no return
+        m = re.search('^\(assert_return\s+\(invoke\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S)
+    if not m:
+        # no params, no return
+        m = re.search('^\(assert_return\s+\(invoke\s+"([^"]*)"\s*()()\)\s*\)\s*$', form, re.S)
+    if not m:
+        # params, return
+        if not n:
+            # no params, return
+            n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"((?:[^"]|\\\")*)"\s*\)\s+()(\(.*\))\s*\)\s*$', form, re.S)
+        if not n:
+            # params, no return
+            n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))()\s*\)\s*\)\s*$', form, re.S)
+        if not n:
+            # no params, no return
+            n = re.search('^\(assert_return\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"*()()\)\s*\)\s*$', form, re.S)
+    if not m and not n:
+        if re.search('^\(assert_return\s+\(get.*\).*\)$', form, re.S):
+            log("ignoring assert_return get");
+            return
+        else:
+            raise Exception("unparsed assert_return: '%s'" % form)
+    if m and not n:
+        func = m.group(1)
+        if ' ' in func:
+            func = func.replace(' ', '\\')
+
+        if m.group(2) == '':
+            args = []
+        else:
+            #args = [re.split(' +', v)[1].replace('_', "") for v in re.split("\)\s*\(", m.group(2)[1:-1])]
+            # split arguments with ')spaces(', remove leading and tailing ) and (
+            args_type_and_value = re.split(r'\)\s+\(', m.group(2)[1:-1])
+            args_type_and_value = [s.replace('_', '') for s in args_type_and_value]
+            # args are in two forms:
+            # f32.const -0x1.000001fffffffffffp-50
+            # v128.const i32x4 0 0 0 0
+            args = []
+            for arg in args_type_and_value:
+                # remove leading and tailing spaces, it might confuse following assertions
+                arg = arg.strip()
+                splitted = re.split('\s+', arg)
+                splitted = [s for s in splitted if s]
+
+                if splitted[0] in ["i32.const", "i64.const"]:
+                    assert(2 == len(splitted)), "{} should have two parts".format(splitted)
+                    # in wast 01234 means 1234
+                    # in c 0123 means 83 in oct
+                    number, _ = parse_simple_const_w_type(splitted[1], splitted[0][:3])
+                    args.append(str(number))
+                elif splitted[0] in ["f32.const", "f64.const"]:
+                    # let strtof or strtod handle original arguments
+                    assert(2 == len(splitted)), "{} should have two parts".format(splitted)
+                    args.append(splitted[1])
+                elif "v128.const" == splitted[0]:
+                    assert(len(splitted) > 2), "{} should have more than two parts".format(splitted)
+                    numbers, _ = cast_v128_to_i64x2(splitted[2:], 'v128', splitted[1])
+
+                    assert(len(numbers) == 2), "has to reform arguments into i64x2"
+                    args.append("{}\{}".format(numbers[0], numbers[1]))
+                elif "ref.null" == splitted[0]:
+                    args.append("null")
+                elif "ref.extern" == splitted[0]:
+                    number, _ = parse_simple_const_w_type(splitted[1], splitted[0])
+                    args.append(str(number))
+                else:
+                    assert(0), "an unkonwn parameter type"
+
+        if m.group(3) == '':
+            returns= []
+        else:
+            returns = re.split("\)\s*\(", m.group(3)[1:-1])
+        # processed numbers in strings
+        expected = [parse_assertion_value(v)[1] for v in returns]
+        test_assert(r, opts, "return", "%s %s" % (func, " ".join(args)), ",".join(expected))
+    elif not m and n:
+        module = os.path.join(temp_file_directory,n.group(1))
+        # assume the cmd is (assert_return(invoke $ABC "func")).
+        # run the ABC.wasm firstly
+        if test_aot:
+            r = compile_wasm_to_aot(module+".wasm", module+".aot", True, opts, r)
+            try:
+                assert_prompt(r, ['Compile success'], opts.start_timeout, False)
+            except:
+                _, exc, _ = sys.exc_info()
+                log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                sys.exit(1)
+            r = run_wasm_with_repl(module+".wasm", module+".aot", opts, r)
+        else:
+            r = run_wasm_with_repl(module+".wasm", None, opts, r)
+        # Wait for the initial prompt
+        try:
+            assert_prompt(r, ['webassembly> '], opts.start_timeout, False)
+        except:
+            _, exc, _ = sys.exc_info()
+            raise Exception("Failed:\n  expected: '%s'\n  got: '%s'" % \
+                            (repr(exc), r.buf))
+        func = n.group(2)
+        if ' ' in func:
+            func = func.replace(' ', '\\')
+
+        if n.group(3) == '':
+            args=[]
+        else:
+            args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n.group(3)[1:-1])]
+
+        # a workaround for "ref.null extern" and "ref.null func"
+        args = [ arg.replace('extern', 'null').replace('func', 'null') for arg in args]
+
+        _, expected = parse_assertion_value(n.group(4)[1:-1])
+        test_assert(r, opts, "return", "%s %s" % (func, " ".join(args)), expected)
+
+def test_assert_trap(r, opts, form):
+    # params
+    m = re.search('^\(assert_trap\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form)
+    # judge if assert_return cmd includes the module name
+    n = re.search('^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form, re.S)
+    if not m:
+        # no params
+        m = re.search('^\(assert_trap\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form)
+    if not m:
+        if not n:
+            # no params
+            n = re.search('^\(assert_trap\s+\(invoke\s+\$((?:[^\s])*)\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form, re.S)
+    if not m and not n:
+        raise Exception("unparsed assert_trap: '%s'" % form)
+
+    if m and not n:
+        func = m.group(1)
+        if m.group(2) == '':
+            args = []
+        else:
+            args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])]
+
+        # workaround for "ref.null extern"
+        args = [ arg.replace('extern', 'null').replace('func', 'null') for arg in args]
+
+        expected = "Exception: %s" % m.group(3)
+        test_assert(r, opts, "trap", "%s %s" % (func, " ".join(args)), expected)
+
+    elif not m and n:
+        module = n.group(1)
+        # will trigger the module named in assert_return(invoke $ABC).
+        # run the ABC.wasm firstly
+        if test_aot:
+            r = compile_wasm_to_aot(module+".wasm", module+".aot", True, opts, r)
+            try:
+                assert_prompt(r, ['Compile success'], opts.start_timeout, False)
+            except:
+                _, exc, _ = sys.exc_info()
+                log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                sys.exit(1)
+            r = run_wasm_with_repl(module+".wasm", module+".aot", opts, r)
+        else:
+            r = run_wasm_with_repl(module+".wasm", None, opts, r)
+        # Wait for the initial prompt
+        try:
+            assert_prompt(r, ['webassembly> '], opts.start_timeout, False)
+        except:
+            _, exc, _ = sys.exc_info()
+            raise Exception("Failed:\n  expected: '%s'\n  got: '%s'" % \
+                            (repr(exc), r.buf))
+
+        func = n.group(2)
+        if n.group(3) == '':
+            args = []
+        else:
+            args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", n.group(3)[1:-1])]
+        expected = "Exception: %s" % n.group(4)
+        test_assert(r, opts, "trap", "%s %s" % (func, " ".join(args)), expected)
+
+def test_assert_exhaustion(r,opts,form):
+    # params
+    m = re.search('^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s+(\(.*\))\s*\)\s*"([^"]+)"\s*\)\s*$', form)
+    if not m:
+        # no params
+        m = re.search('^\(assert_exhaustion\s+\(invoke\s+"([^"]*)"\s*()\)\s*"([^"]+)"\s*\)\s*$', form)
+    if not m:
+        raise Exception("unparsed assert_exhaustion: '%s'" % form)
+    func = m.group(1)
+    if m.group(2) == '':
+        args = []
+    else:
+        args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])]
+    expected = "Exception: %s\n" % m.group(3)
+    test_assert(r, opts, "exhaustion", "%s %s" % (func, " ".join(args)), expected)
+
+def do_invoke(r, opts, form):
+    # params
+    m = re.search('^\(invoke\s+"([^"]+)"\s+(\(.*\))\s*\)\s*$', form)
+    if not m:
+        # no params
+        m = re.search('^\(invoke\s+"([^"]+)"\s*()\)\s*$', form)
+    if not m:
+        raise Exception("unparsed invoke: '%s'" % form)
+    func = m.group(1)
+
+    if ' ' in func:
+        func = func.replace(' ', '\\')
+
+    if m.group(2) == '':
+        args = []
+    else:
+        args = [re.split(' +', v)[1] for v in re.split("\)\s*\(", m.group(2)[1:-1])]
+
+    log("Invoking %s(%s)" % (
+        func, ", ".join([str(a) for a in args])))
+
+    invoke(r, opts, "%s %s" % (func, " ".join(args)))
+
+def skip_test(form, skip_list):
+    for s in skip_list:
+        if re.search(s, form):
+            return True
+    return False
+
+def compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts):
+    log("Writing WAST module to '%s'" % wast_tempfile)
+    file(wast_tempfile, 'w').write(form)
+    log("Compiling WASM to '%s'" % wasm_tempfile)
+
+    # default arguments
+    cmd = [opts.wast2wasm,
+            "--enable-thread",
+            "--no-check",
+            wast_tempfile, "-o", wasm_tempfile ]
+
+    # optional arguments
+    if opts.simd:
+        cmd.append("--enable-simd")
+
+    if opts.ref_types:
+        cmd.append("--enable-reference-types")
+        cmd.append("--enable-bulk-memory")
+
+    log("Running: %s" % " ".join(cmd))
+    try:
+        subprocess.check_call(cmd)
+    except subprocess.CalledProcessError as e:
+        print(str(e))
+        return False
+
+    return True
+
+def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r):
+    log("Compiling AOT to '%s'" % aot_tempfile)
+    cmd = [opts.aot_compiler]
+
+    if test_target == "x86_64":
+        cmd.append("--target=x86_64")
+        cmd.append("--cpu=skylake")
+    elif test_target == "i386":
+        cmd.append("--target=i386")
+    elif test_target == "aarch64":
+        cmd += ["--target=aarch64", "--cpu=cortex-a57"]
+    elif test_target == "armv7":
+        cmd += ["--target=armv7", "--target-abi=gnueabihf"]
+    elif test_target == "thumbv7":
+        cmd += ["--target=thumbv7", "--target-abi=gnueabihf", "--cpu=cortex-a15"]
+    elif test_target == "riscv64_lp64d":
+        cmd += ["--target=riscv64", "--target-abi=lp64d"]
+    elif test_target == "riscv64_lp64":
+        cmd += ["--target=riscv64", "--target-abi=lp64"]
+    else:
+        pass
+
+    if opts.sgx:
+        cmd.append("-sgx")
+
+    if opts.simd:
+        cmd.append("--enable-simd")
+
+    if opts.ref_types:
+        cmd.append("--enable-ref-types")
+        cmd.append("--enable-bulk-memory")
+
+    cmd += ["-o", aot_tempfile, wasm_tempfile]
+
+    log("Running: %s" % " ".join(cmd))
+    if not runner:
+        subprocess.check_call(cmd)
+    else:
+        if (r != None):
+            r.cleanup()
+        r = Runner(cmd, no_pty=opts.no_pty)
+        return r
+
+def run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r):
+    if not test_aot:
+        log("Starting interpreter for module '%s'" % wasm_tempfile)
+        if opts.verbose:
+            cmd = [opts.interpreter, "--heap-size=0", "-v=5", "--repl", wasm_tempfile]
+        else:
+            cmd = [opts.interpreter, "--heap-size=0", "--repl", wasm_tempfile]
+    else:
+        log("Starting aot for module '%s'" % aot_tempfile)
+        if opts.verbose:
+            cmd = [opts.interpreter, "--heap-size=0", "-v=5", "--repl", aot_tempfile]
+        else:
+            cmd = [opts.interpreter, "--heap-size=0", "--repl", aot_tempfile]
+
+    log("Running: %s" % " ".join(cmd))
+    if (r != None):
+        r.cleanup()
+    r = Runner(cmd, no_pty=opts.no_pty)
+    return r
+
+def create_tmpfiles(wast_name):
+    tempfiles = []
+    # make tempfile directory
+    if not os.path.exists(temp_file_directory):
+        os.mkdir(temp_file_directory)
+
+    # create temporal file with particular name
+    temp_wast_file = os.path.join(temp_file_directory, ""+ wast_name + ".wast")
+    if not os.path.exists(temp_wast_file):
+        os.mknod(temp_wast_file)
+    tempfiles.append(temp_wast_file)
+
+    # now we define the same file name as wast for wasm & aot
+    wasm_file = wast_name +".wasm"
+    temp_wasm_file = os.path.join(temp_file_directory, wasm_file)
+    if not os.path.exists(temp_wasm_file):
+        os.mknod(temp_wasm_file)
+    tempfiles.append(temp_wasm_file)
+
+    if test_aot:
+        aot_file = wast_name +".aot"
+        temp_aot_file =os.path.join(temp_file_directory, aot_file)
+        if not os.path.exists(temp_aot_file):
+            os.mknod(temp_aot_file)
+        tempfiles.append(temp_aot_file)
+
+    # add these temp file to temporal repo, will be deleted when finishing the test
+    temp_file_repo.extend(tempfiles)
+    return tempfiles
+
+def test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r):
+    details_inside_ast = get_module_exp_from_assert(form)
+    log("module is ....'%s'"%details_inside_ast[0])
+    log("exception is ....'%s'"%details_inside_ast[1])
+    # parse the module
+    module = details_inside_ast[0]
+    expected = details_inside_ast[1]
+
+    if not compile_wast_to_wasm(module, wast_tempfile, wasm_tempfile, opts):
+        raise Exception("compile wast to wasm failed")
+
+    if test_aot:
+        r = compile_wasm_to_aot(wasm_tempfile, aot_tempfile, True, opts, r)
+        try:
+            assert_prompt(r, ['Compile success'], opts.start_timeout, True)
+        except:
+            _, exc, _ = sys.exc_info()
+            if (r.buf.find(expected) >= 0):
+                log("Out exception includes expected one, pass:")
+                log("  Expected: %s" % expected)
+                log("  Got: %s" % r.buf)
+                return
+            else:
+                log("Run wamrc failed:\n  expected: '%s'\n  got: '%s'" % \
+                    (expected, r.buf))
+                sys.exit(1)
+        r = run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r)
+    else:
+        r = run_wasm_with_repl(wasm_tempfile, None, opts, r)
+
+    # Wait for the initial prompt
+    try:
+        assert_prompt(r, ['webassembly> '], opts.start_timeout, True)
+    except:
+        _, exc, _ = sys.exc_info()
+        if (r.buf.find(expected) >= 0):
+            log("Out exception includes expected one, pass:")
+            log("  Expected: %s" %expected)
+            log("  Got: %s" % r.buf)
+        else:
+            raise Exception("Failed:\n  expected: '%s'\n  got: '%s'" % \
+                            (expected, r.buf))
+
+if __name__ == "__main__":
+    opts = parser.parse_args(sys.argv[1:])
+
+    if opts.aot: test_aot = True
+    # default x86_64
+    test_target = opts.aot_target
+
+    if opts.rundir: os.chdir(opts.rundir)
+
+    if opts.log_file:   log_file   = open(opts.log_file, "a")
+    if opts.debug_file: debug_file = open(opts.debug_file, "a")
+
+    if opts.interpreter.endswith(".py"):
+        SKIP_TESTS = PY_SKIP_TESTS
+    else:
+        SKIP_TESTS = C_SKIP_TESTS
+
+    (t1fd, wast_tempfile) = tempfile.mkstemp(suffix=".wast")
+    (t2fd, wasm_tempfile) = tempfile.mkstemp(suffix=".wasm")
+    if test_aot:
+        (t3fd, aot_tempfile) = tempfile.mkstemp(suffix=".aot")
+
+    try:
+        log("################################################")
+        log("### Testing %s" % opts.test_file.name)
+        log("################################################")
+        forms = read_forms(opts.test_file.read())
+        r = None
+
+        for form in forms:
+            # log("\n### Current Case is " + form + "\n")
+            if ";;" == form[0:2]:
+                log(form)
+            elif skip_test(form, SKIP_TESTS):
+                log("Skipping test: %s" % form[0:60])
+            elif re.match("^\(assert_trap\s+\(module", form):
+                if test_aot:
+                    test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r)
+                else:
+                    test_assert_with_exception(form, wast_tempfile, wasm_tempfile, None, opts, r)
+            elif re.match("^\(assert_exhaustion\\b.*", form):
+                test_assert_exhaustion(r, opts, form)
+            elif re.match("^\(assert_unlinkable\\b.*", form):
+                if test_aot:
+                    test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r)
+                else:
+                    test_assert_with_exception(form, wast_tempfile, wasm_tempfile, None, opts, r)
+            elif re.match("^\(assert_malformed\\b.*", form):
+                # remove comments in wast
+                form,n = re.subn(";;.*\n", "", form)
+                m = re.match("^\(assert_malformed\s*\(module binary\s*(\".*\").*\)\s*\"(.*)\"\s*\)$", form, re.DOTALL)
+
+                if m:
+                    # workaround: spec test changes error message to "malformed" while iwasm still use "invalid"
+                    error_msg = m.group(2).replace("malformed", "invalid")
+                    log("Testing(malformed)")
+                    f = file(wasm_tempfile, 'w')
+                    s = m.group(1)
+                    while s:
+                        res = re.match("[^\"]*\"([^\"]*)\"(.*)", s, re.DOTALL)
+                        f.write(res.group(1).replace("\\", "\\x").decode("string_escape"))
+                        s = res.group(2)
+                    f.close()
+
+                    # compile wasm to aot
+                    if test_aot:
+                        r = compile_wasm_to_aot(wasm_tempfile, aot_tempfile, True, opts, r)
+                        try:
+                            assert_prompt(r, ['Compile success'], opts.start_timeout, True)
+                        except:
+                            _, exc, _ = sys.exc_info()
+                            if (r.buf.find(error_msg) >= 0):
+                                log("Out exception includes expected one, pass:")
+                                log("  Expected: %s" % error_msg)
+                                log("  Got: %s" % r.buf)
+                            else:
+                                log("Run wamrc failed:\n  expected: '%s'\n  got: '%s'" % \
+                                    (error_msg, r.buf))
+                            continue
+                        cmd = [opts.interpreter, "--heap-size=0", "--repl", aot_tempfile]
+                    else:
+                        cmd = [opts.interpreter, "--heap-size=0", "--repl", wasm_tempfile]
+                    log("Running: %s" % " ".join(cmd))
+                    output = subprocess.check_output(cmd)
+
+                    if (error_msg == "unexpected end of section or function") \
+                       and output.endswith("unexpected end\n"):
+                        # one case in binary.wast
+                        pass
+                    elif (error_msg == "invalid value type") \
+                       and output.endswith("unexpected end\n"):
+                        # one case in binary.wast
+                        pass
+                    elif (error_msg == "length out of bounds") \
+                       and output.endswith("unexpected end\n"):
+                        # one case in custom.wast
+                        pass
+                    elif (error_msg == "integer representation too long") \
+                       and output.endswith("invalid section id\n"):
+                        # several cases in binary-leb128.wast
+                        pass
+                    elif not error_msg in output:
+                        raise Exception("Failed:\n  expected: '%s'\n  got: '%s'" % (error_msg, output[0:-1]))
+                    else:
+                        pass
+                elif re.match("^\(assert_malformed\s*\(module quote", form):
+                    log("ignoring assert_malformed module quote")
+                else:
+                    log("unrecognized assert_malformed")
+            elif re.match("^\(assert_return[_a-z]*_nan\\b.*", form):
+                log("ignoring assert_return_.*_nan")
+                pass
+            elif re.match(".*\(invoke\s+\$\\b.*", form):
+                # invoke a particular named module's function
+                if form.startswith("(assert_return"):
+                    test_assert_return(r,opts,form)
+                elif form.startswith("(assert_trap"):
+                    test_assert_trap(r,opts,form)
+            elif re.match("^\(module\\b.*", form):
+                # if the module includes the particular name startswith $
+                m = re.search("^\(module\s+\$.\S+", form)
+                if m:
+                    # get module name
+                    module_name = re.split('\$', m.group(0).strip())[1]
+                    if module_name:
+                        # create temporal files
+                        temp_files = create_tmpfiles(module_name)
+                        if not compile_wast_to_wasm(form, temp_files[0], temp_files[1], opts):
+                            raise Exception("compile wast to wasm failed")
+
+                        if test_aot:
+                            r = compile_wasm_to_aot(temp_files[1], temp_files[2], True, opts, r)
+                            try:
+                                assert_prompt(r, ['Compile success'], opts.start_timeout, False)
+                            except:
+                                _, exc, _ = sys.exc_info()
+                                log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                                sys.exit(1)
+                            r = run_wasm_with_repl(temp_files[1], temp_files[2], opts, r)
+                        else:
+                            r = run_wasm_with_repl(temp_files[1], None, opts, r)
+                else:
+                    if not compile_wast_to_wasm(form, wast_tempfile, wasm_tempfile, opts):
+                        raise Exception("compile wast to wasm failed")
+
+                    if test_aot:
+                        r = compile_wasm_to_aot(wasm_tempfile, aot_tempfile, True, opts, r)
+                        try:
+                            assert_prompt(r, ['Compile success'], opts.start_timeout, False)
+                        except:
+                            _, exc, _ = sys.exc_info()
+                            log("Run wamrc failed:\n  got: '%s'" % r.buf)
+                            sys.exit(1)
+                        r = run_wasm_with_repl(wasm_tempfile, aot_tempfile, opts, r)
+                    else:
+                        r = run_wasm_with_repl(wasm_tempfile, None, opts, r)
+
+                # Wait for the initial prompt
+                try:
+                    assert_prompt(r, ['webassembly> '], opts.start_timeout, False)
+                except:
+                    _, exc, _ = sys.exc_info()
+                    raise Exception("Failed:\n  expected: '%s'\n  got: '%s'" % \
+                                    (repr(exc), r.buf))
+
+            elif re.match("^\(assert_return\\b.*", form):
+                assert(r), "iwasm repl runtime should be not null"
+                test_assert_return(r, opts, form)
+            elif re.match("^\(assert_trap\\b.*", form):
+                test_assert_trap(r, opts, form)
+            elif re.match("^\(invoke\\b.*", form):
+                assert(r), "iwasm repl runtime should be not null"
+                do_invoke(r, opts, form)
+            elif re.match("^\(assert_invalid\\b.*", form):
+                if test_aot:
+                    test_assert_with_exception(form, wast_tempfile, wasm_tempfile, aot_tempfile, opts, r)
+                else:
+                    test_assert_with_exception(form, wast_tempfile, wasm_tempfile, None, opts, r)
+
+
+            elif re.match("^\(register\\b.*", form):
+                # get module's new name from the register cmd
+                name_new =re.split('\"',re.search('\".*\"',form).group(0))[1]
+                if name_new:
+                    # if the register cmd include the new and old module name.
+                    # like: (register "new" $old)
+                    # we will replace the old with new name.
+                    name_old = re.search('\$.*\)',form)
+                    if name_old:
+                        old_ = re.split('\W', re.search('\$.*\)',form).group(0))[1]
+                        old_module = os.path.join(temp_file_directory,old_+".wasm")
+                    else:
+                    # like: (register "new")
+                    # this kind of register cmd will be behind of a noramal module
+                    # these modules' name are default temporal file name
+                    # we replace them with new name.
+                        old_module = wasm_tempfile
+
+                    new_module = os.path.join(current_work_directory,name_new+".wasm")
+                    shutil.copyfile(old_module,new_module)
+                    # add new_module copied from the old into temp_file_repo[]
+                    temp_file_repo.append(new_module)
+                else:
+                    # there is no name defined in register cmd
+                    raise Exception("can not find module name from the register")
+            else:
+                raise Exception("unrecognized form '%s...'" % form[0:40])
+    except Exception as e:
+        traceback.print_exc()
+        raise Exception("catch an exception {}".format(e))
+    else:
+        sys.exit(0)
+    finally:
+        if not opts.no_cleanup:
+            log("Removing tempfiles")
+            os.remove(wast_tempfile)
+            os.remove(wasm_tempfile)
+            if test_aot:
+                os.remove(aot_tempfile)
+
+            # remove the files under /tempfiles/ and copy of .wasm files
+            if temp_file_repo:
+                for t in temp_file_repo:
+                    if(len(str(t))!=0 and os.path.exists(t)):
+                        os.remove(t)
+            # remove /tempfiles/ directory
+            if os.path.exists(temp_file_directory):
+                shutil.rmtree(temp_file_directory)
+
+            log("### End testing %s" % opts.test_file.name)
+        else:
+            log("Leaving tempfiles: %s" % ([wast_tempfile, wasm_tempfile]))

+ 73 - 0
tests/wamr-test-suites/spec-test-script/simd_ignore_cases.patch

@@ -0,0 +1,73 @@
+diff --git a/test/core/simd/simd_lane.wast b/test/core/simd/simd_lane.wast
+index 9d4b5fd7..4656dd2b 100644
+--- a/test/core/simd/simd_lane.wast
++++ b/test/core/simd/simd_lane.wast
+@@ -602,23 +602,23 @@
+   "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) "
+   "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "invalid lane length")
+ (assert_malformed (module quote "(func (result v128) "
+-  "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15.0) "
++  "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15.0 "
+   "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) "
+   "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index")
+ (assert_malformed (module quote "(func (result v128) "
+-  "(i8x16.shuffle 0.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) "
++  "(i8x16.shuffle 0.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "
+   "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) "
+   "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index")
+ (assert_malformed (module quote "(func (result v128) "
+-  "(i8x16.shuffle -inf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) "
++  "(i8x16.shuffle -inf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "
+   "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) "
+   "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index")
+ (assert_malformed (module quote "(func (result v128) "
+-  "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 inf) "
++  "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 inf "
+   "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) "
+   "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index")
+ (assert_malformed (module quote "(func (result v128) "
+-  "(i8x16.shuffle nan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) "
++  "(i8x16.shuffle nan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "
+   "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) "
+   "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index")
+ 
+@@ -858,7 +858,7 @@
+ (assert_return (invoke "as-if-condition-value" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 0))
+ (assert_return (invoke "as-return-value-1" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)) (v128.const i16x8 1 0 0 0 0 0 0 0))
+ (assert_return (invoke "as-local_set-value" (v128.const i32x4 -1 -1 -1 -1)) (i32.const -1))
+-(assert_return (invoke "as-global_set-value-1" (v128.const f32x4 0 0 0 0)(f32.const 3.14)) (v128.const f32x4 3.14 0 0 0))
++(assert_return (invoke "as-global_set-value-1" (v128.const f32x4 0 0 0 0) (f32.const 3.14)) (v128.const f32x4 3.14 0 0 0))
+ 
+ (assert_return (invoke "as-return-value-2"
+   (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)
+@@ -870,7 +870,7 @@
+   (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 8 7 6 5 4 3 2 1))
+ 
+ (assert_return (invoke "as-local_set-value-1" (v128.const i64x2 -1 -1)) (i64.const -1))
+-(assert_return (invoke "as-global_set-value-3" (v128.const f64x2 0 0)(f64.const 3.14)) (v128.const f64x2 3.14 0))
++(assert_return (invoke "as-global_set-value-3" (v128.const f64x2 0 0) (f64.const 3.14)) (v128.const f64x2 3.14 0))
+ 
+ ;; Non-nat lane index
+ 
+diff --git a/test/core/simd/simd_load.wast b/test/core/simd/simd_load.wast
+index 4b2edc16..c7639218 100644
+--- a/test/core/simd/simd_load.wast
++++ b/test/core/simd/simd_load.wast
+@@ -124,7 +124,7 @@
+     (i8x16.swizzle (v128.load (i32.const 0)) (v128.load offset=15 (i32.const 1)))
+   )
+ )
+-(assert_return(invoke "as-i8x16.swizzle-operand") (v128.const i8x16 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100))
++(assert_return (invoke "as-i8x16.swizzle-operand") (v128.const i8x16 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100))
+ 
+ (module (memory 1)
+   (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f\00\01\02\03")
+@@ -180,7 +180,7 @@
+ 
+ (assert_invalid
+   (module (memory 1) (func (drop (v128.load (local.get 2)))))
+-  "unknown local 2"
++  "unknown local"
+ )
+ (assert_invalid
+   (module (memory 1) (func (drop (v128.load))))

+ 202 - 0
tests/wamr-test-suites/spec-test-script/tail-call/return_call.wast

@@ -0,0 +1,202 @@
+;; Test `return_call` operator
+
+(module
+  ;; Auxiliary definitions
+  (func $const-i32 (result i32) (i32.const 0x132))
+  (func $const-i64 (result i64) (i64.const 0x164))
+  (func $const-f32 (result f32) (f32.const 0xf32))
+  (func $const-f64 (result f64) (f64.const 0xf64))
+
+  (func $id-i32 (param i32) (result i32) (get_local 0))
+  (func $id-i64 (param i64) (result i64) (get_local 0))
+  (func $id-f32 (param f32) (result f32) (get_local 0))
+  (func $id-f64 (param f64) (result f64) (get_local 0))
+
+  (func $f32-i32 (param f32 i32) (result i32) (get_local 1))
+  (func $i32-i64 (param i32 i64) (result i64) (get_local 1))
+  (func $f64-f32 (param f64 f32) (result f32) (get_local 1))
+  (func $i64-f64 (param i64 f64) (result f64) (get_local 1))
+
+  ;; Typing
+
+  (func (export "type-i32") (result i32) (return_call $const-i32))
+  (func (export "type-i64") (result i64) (return_call $const-i64))
+  (func (export "type-f32") (result f32) (return_call $const-f32))
+  (func (export "type-f64") (result f64) (return_call $const-f64))
+
+  (func (export "type-first-i32") (result i32) (return_call $id-i32 (i32.const 32)))
+  (func (export "type-first-i64") (result i64) (return_call $id-i64 (i64.const 64)))
+  (func (export "type-first-f32") (result f32) (return_call $id-f32 (f32.const 1.32)))
+  (func (export "type-first-f64") (result f64) (return_call $id-f64 (f64.const 1.64)))
+
+  (func (export "type-second-i32") (result i32)
+    (return_call $f32-i32 (f32.const 32.1) (i32.const 32))
+  )
+  (func (export "type-second-i64") (result i64)
+    (return_call $i32-i64 (i32.const 32) (i64.const 64))
+  )
+  (func (export "type-second-f32") (result f32)
+    (return_call $f64-f32 (f64.const 64) (f32.const 32))
+  )
+  (func (export "type-second-f64") (result f64)
+    (return_call $i64-f64 (i64.const 64) (f64.const 64.1))
+  )
+
+  ;; Recursion
+
+  (func $fac-acc (export "fac-acc") (param i64 i64) (result i64)
+    (if (result i64) (i64.eqz (get_local 0))
+      (then (get_local 1))
+      (else
+        (return_call $fac-acc
+          (i64.sub (get_local 0) (i64.const 1))
+          (i64.mul (get_local 0) (get_local 1))
+        )
+      )
+    )
+  )
+
+  (func $count (export "count") (param i64) (result i64)
+    (if (result i64) (i64.eqz (get_local 0))
+      (then (get_local 0))
+      (else (return_call $count (i64.sub (get_local 0) (i64.const 1))))
+    )
+  )
+
+  (func $even (export "even") (param i64) (result i32)
+    (if (result i32) (i64.eqz (get_local 0))
+      (then (i32.const 44))
+      (else (return_call $odd (i64.sub (get_local 0) (i64.const 1))))
+    )
+  )
+  (func $odd (export "odd") (param i64) (result i32)
+    (if (result i32) (i64.eqz (get_local 0))
+      (then (i32.const 99))
+      (else (return_call $even (i64.sub (get_local 0) (i64.const 1))))
+    )
+  )
+)
+
+(assert_return (invoke "type-i32") (i32.const 0x132))
+(assert_return (invoke "type-i64") (i64.const 0x164))
+(assert_return (invoke "type-f32") (f32.const 0xf32))
+(assert_return (invoke "type-f64") (f64.const 0xf64))
+
+(assert_return (invoke "type-first-i32") (i32.const 32))
+(assert_return (invoke "type-first-i64") (i64.const 64))
+(assert_return (invoke "type-first-f32") (f32.const 1.32))
+(assert_return (invoke "type-first-f64") (f64.const 1.64))
+
+(assert_return (invoke "type-second-i32") (i32.const 32))
+(assert_return (invoke "type-second-i64") (i64.const 64))
+(assert_return (invoke "type-second-f32") (f32.const 32))
+(assert_return (invoke "type-second-f64") (f64.const 64.1))
+
+(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1))
+(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1))
+(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120))
+(assert_return
+  (invoke "fac-acc" (i64.const 25) (i64.const 1))
+  (i64.const 7034535277573963776)
+)
+
+(assert_return (invoke "count" (i64.const 0)) (i64.const 0))
+(assert_return (invoke "count" (i64.const 1000)) (i64.const 0))
+(assert_return (invoke "count" (i64.const 1_000_000)) (i64.const 0))
+
+(assert_return (invoke "even" (i64.const 0)) (i32.const 44))
+(assert_return (invoke "even" (i64.const 1)) (i32.const 99))
+(assert_return (invoke "even" (i64.const 100)) (i32.const 44))
+(assert_return (invoke "even" (i64.const 77)) (i32.const 99))
+(assert_return (invoke "even" (i64.const 1_000_000)) (i32.const 44))
+(assert_return (invoke "even" (i64.const 1_000_001)) (i32.const 99))
+(assert_return (invoke "odd" (i64.const 0)) (i32.const 99))
+(assert_return (invoke "odd" (i64.const 1)) (i32.const 44))
+(assert_return (invoke "odd" (i64.const 200)) (i32.const 99))
+(assert_return (invoke "odd" (i64.const 77)) (i32.const 44))
+(assert_return (invoke "odd" (i64.const 1_000_000)) (i32.const 99))
+(assert_return (invoke "odd" (i64.const 999_999)) (i32.const 44))
+
+
+;; Invalid typing
+
+(assert_invalid
+  (module
+    (func $type-void-vs-num (result i32) (return_call 1) (i32.const 0))
+    (func)
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (func $type-num-vs-num (result i32) (return_call 1) (i32.const 0))
+    (func (result i64) (i64.const 1))
+  )
+  "type mismatch"
+)
+
+(assert_invalid
+  (module
+    (func $arity-0-vs-1 (return_call 1))
+    (func (param i32))
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (func $arity-0-vs-2 (return_call 1))
+    (func (param f64 i32))
+  )
+  "type mismatch"
+)
+
+(module
+  (func $arity-1-vs-0 (i32.const 1) (return_call 1))
+  (func)
+)
+
+(module
+  (func $arity-2-vs-0 (f64.const 2) (i32.const 1) (return_call 1))
+  (func)
+)
+
+(assert_invalid
+  (module
+    (func $type-first-void-vs-num (return_call 1 (nop) (i32.const 1)))
+    (func (param i32 i32))
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (func $type-second-void-vs-num (return_call 1 (i32.const 1) (nop)))
+    (func (param i32 i32))
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (func $type-first-num-vs-num (return_call 1 (f64.const 1) (i32.const 1)))
+    (func (param i32 f64))
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (func $type-second-num-vs-num (return_call 1 (i32.const 1) (f64.const 1)))
+    (func (param f64 i32))
+  )
+  "type mismatch"
+)
+
+
+;; Unbound function
+
+(assert_invalid
+  (module (func $unbound-func (return_call 1)))
+  "unknown function"
+)
+(assert_invalid
+  (module (func $large-func (return_call 1012321300)))
+  "unknown function"
+)

+ 511 - 0
tests/wamr-test-suites/spec-test-script/tail-call/return_call_indirect.wast

@@ -0,0 +1,511 @@
+;; Test `return_call_indirect` operator
+
+(module
+  ;; Auxiliary definitions
+  (type $proc (func))
+  (type $out-i32 (func (result i32)))
+  (type $out-i64 (func (result i64)))
+  (type $out-f32 (func (result f32)))
+  (type $out-f64 (func (result f64)))
+  (type $over-i32 (func (param i32) (result i32)))
+  (type $over-i64 (func (param i64) (result i64)))
+  (type $over-f32 (func (param f32) (result f32)))
+  (type $over-f64 (func (param f64) (result f64)))
+  (type $f32-i32 (func (param f32 i32) (result i32)))
+  (type $i32-i64 (func (param i32 i64) (result i64)))
+  (type $f64-f32 (func (param f64 f32) (result f32)))
+  (type $i64-f64 (func (param i64 f64) (result f64)))
+  (type $over-i32-duplicate (func (param i32) (result i32)))
+  (type $over-i64-duplicate (func (param i64) (result i64)))
+  (type $over-f32-duplicate (func (param f32) (result f32)))
+  (type $over-f64-duplicate (func (param f64) (result f64)))
+
+  (func $const-i32 (type $out-i32) (i32.const 0x132))
+  (func $const-i64 (type $out-i64) (i64.const 0x164))
+  (func $const-f32 (type $out-f32) (f32.const 0xf32))
+  (func $const-f64 (type $out-f64) (f64.const 0xf64))
+
+  (func $id-i32 (type $over-i32) (get_local 0))
+  (func $id-i64 (type $over-i64) (get_local 0))
+  (func $id-f32 (type $over-f32) (get_local 0))
+  (func $id-f64 (type $over-f64) (get_local 0))
+
+  (func $i32-i64 (type $i32-i64) (get_local 1))
+  (func $i64-f64 (type $i64-f64) (get_local 1))
+  (func $f32-i32 (type $f32-i32) (get_local 1))
+  (func $f64-f32 (type $f64-f32) (get_local 1))
+
+  (func $over-i32-duplicate (type $over-i32-duplicate) (get_local 0))
+  (func $over-i64-duplicate (type $over-i64-duplicate) (get_local 0))
+  (func $over-f32-duplicate (type $over-f32-duplicate) (get_local 0))
+  (func $over-f64-duplicate (type $over-f64-duplicate) (get_local 0))
+
+  (table anyfunc
+    (elem
+      $const-i32 $const-i64 $const-f32 $const-f64
+      $id-i32 $id-i64 $id-f32 $id-f64
+      $f32-i32 $i32-i64 $f64-f32 $i64-f64
+      $fac $fac-acc $even $odd
+      $over-i32-duplicate $over-i64-duplicate
+      $over-f32-duplicate $over-f64-duplicate
+    )
+  )
+
+  ;; Syntax
+
+  (func
+    (return_call_indirect (i32.const 0))
+    (return_call_indirect (param i64) (i64.const 0) (i32.const 0))
+    (return_call_indirect (param i64) (param) (param f64 i32 i64)
+      (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0)
+    )
+    (return_call_indirect (result) (i32.const 0))
+  )
+
+  (func (result i32)
+    (return_call_indirect (result i32) (i32.const 0))
+    (return_call_indirect (result i32) (result) (i32.const 0))
+    (return_call_indirect (param i64) (result i32) (i64.const 0) (i32.const 0))
+    (return_call_indirect
+      (param) (param i64) (param) (param f64 i32 i64) (param) (param)
+      (result) (result i32) (result) (result)
+      (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0)
+    )
+  )
+
+  (func (result i64)
+    (return_call_indirect (type $over-i64) (param i64) (result i64)
+      (i64.const 0) (i32.const 0)
+    )
+  )
+
+  ;; Typing
+
+  (func (export "type-i32") (result i32)
+    (return_call_indirect (type $out-i32) (i32.const 0))
+  )
+  (func (export "type-i64") (result i64)
+    (return_call_indirect (type $out-i64) (i32.const 1))
+  )
+  (func (export "type-f32") (result f32)
+    (return_call_indirect (type $out-f32) (i32.const 2))
+  )
+  (func (export "type-f64") (result f64)
+    (return_call_indirect (type $out-f64) (i32.const 3))
+  )
+
+  (func (export "type-index") (result i64)
+    (return_call_indirect (type $over-i64) (i64.const 100) (i32.const 5))
+  )
+
+  (func (export "type-first-i32") (result i32)
+    (return_call_indirect (type $over-i32) (i32.const 32) (i32.const 4))
+  )
+  (func (export "type-first-i64") (result i64)
+    (return_call_indirect (type $over-i64) (i64.const 64) (i32.const 5))
+  )
+  (func (export "type-first-f32") (result f32)
+    (return_call_indirect (type $over-f32) (f32.const 1.32) (i32.const 6))
+  )
+  (func (export "type-first-f64") (result f64)
+    (return_call_indirect (type $over-f64) (f64.const 1.64) (i32.const 7))
+  )
+
+  (func (export "type-second-i32") (result i32)
+    (return_call_indirect (type $f32-i32)
+      (f32.const 32.1) (i32.const 32) (i32.const 8)
+    )
+  )
+  (func (export "type-second-i64") (result i64)
+    (return_call_indirect (type $i32-i64)
+      (i32.const 32) (i64.const 64) (i32.const 9)
+    )
+  )
+  (func (export "type-second-f32") (result f32)
+    (return_call_indirect (type $f64-f32)
+      (f64.const 64) (f32.const 32) (i32.const 10)
+    )
+  )
+  (func (export "type-second-f64") (result f64)
+    (return_call_indirect (type $i64-f64)
+      (i64.const 64) (f64.const 64.1) (i32.const 11)
+    )
+  )
+
+  ;; Dispatch
+
+  (func (export "dispatch") (param i32 i64) (result i64)
+    (return_call_indirect (type $over-i64) (get_local 1) (get_local 0))
+  )
+
+  (func (export "dispatch-structural") (param i32) (result i64)
+    (return_call_indirect (type $over-i64-duplicate)
+      (i64.const 9) (get_local 0)
+    )
+  )
+
+  ;; Recursion
+
+  (func $fac (export "fac") (type $over-i64)
+    (return_call_indirect (param i64 i64) (result i64)
+      (get_local 0) (i64.const 1) (i32.const 13)
+    )
+  )
+
+  (func $fac-acc (param i64 i64) (result i64)
+    (if (result i64) (i64.eqz (get_local 0))
+      (then (get_local 1))
+      (else
+        (return_call_indirect (param i64 i64) (result i64)
+          (i64.sub (get_local 0) (i64.const 1))
+          (i64.mul (get_local 0) (get_local 1))
+          (i32.const 13)
+        )
+      )
+    )
+  )
+
+  (func $even (export "even") (param i32) (result i32)
+    (if (result i32) (i32.eqz (get_local 0))
+      (then (i32.const 44))
+      (else
+        (return_call_indirect (type $over-i32)
+          (i32.sub (get_local 0) (i32.const 1))
+          (i32.const 15)
+        )
+      )
+    )
+  )
+  (func $odd (export "odd") (param i32) (result i32)
+    (if (result i32) (i32.eqz (get_local 0))
+      (then (i32.const 99))
+      (else
+        (return_call_indirect (type $over-i32)
+          (i32.sub (get_local 0) (i32.const 1))
+          (i32.const 14)
+        )
+      )
+    )
+  )
+)
+
+(assert_return (invoke "type-i32") (i32.const 0x132))
+(assert_return (invoke "type-i64") (i64.const 0x164))
+(assert_return (invoke "type-f32") (f32.const 0xf32))
+(assert_return (invoke "type-f64") (f64.const 0xf64))
+
+(assert_return (invoke "type-index") (i64.const 100))
+
+(assert_return (invoke "type-first-i32") (i32.const 32))
+(assert_return (invoke "type-first-i64") (i64.const 64))
+(assert_return (invoke "type-first-f32") (f32.const 1.32))
+(assert_return (invoke "type-first-f64") (f64.const 1.64))
+
+(assert_return (invoke "type-second-i32") (i32.const 32))
+(assert_return (invoke "type-second-i64") (i64.const 64))
+(assert_return (invoke "type-second-f32") (f32.const 32))
+(assert_return (invoke "type-second-f64") (f64.const 64.1))
+
+(assert_return (invoke "dispatch" (i32.const 5) (i64.const 2)) (i64.const 2))
+(assert_return (invoke "dispatch" (i32.const 5) (i64.const 5)) (i64.const 5))
+(assert_return (invoke "dispatch" (i32.const 12) (i64.const 5)) (i64.const 120))
+(assert_return (invoke "dispatch" (i32.const 17) (i64.const 2)) (i64.const 2))
+(assert_trap (invoke "dispatch" (i32.const 0) (i64.const 2)) "indirect call type mismatch")
+(assert_trap (invoke "dispatch" (i32.const 15) (i64.const 2)) "indirect call type mismatch")
+(assert_trap (invoke "dispatch" (i32.const 20) (i64.const 2)) "undefined element")
+(assert_trap (invoke "dispatch" (i32.const -1) (i64.const 2)) "undefined element")
+(assert_trap (invoke "dispatch" (i32.const 1213432423) (i64.const 2)) "undefined element")
+
+(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9))
+(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9))
+(assert_return (invoke "dispatch-structural" (i32.const 12)) (i64.const 362880))
+(assert_return (invoke "dispatch-structural" (i32.const 17)) (i64.const 9))
+(assert_trap (invoke "dispatch-structural" (i32.const 11)) "indirect call type mismatch")
+(assert_trap (invoke "dispatch-structural" (i32.const 16)) "indirect call type mismatch")
+
+(assert_return (invoke "fac" (i64.const 0)) (i64.const 1))
+(assert_return (invoke "fac" (i64.const 1)) (i64.const 1))
+(assert_return (invoke "fac" (i64.const 5)) (i64.const 120))
+(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776))
+
+(assert_return (invoke "even" (i32.const 0)) (i32.const 44))
+(assert_return (invoke "even" (i32.const 1)) (i32.const 99))
+(assert_return (invoke "even" (i32.const 100)) (i32.const 44))
+(assert_return (invoke "even" (i32.const 77)) (i32.const 99))
+(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44))
+(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99))
+(assert_return (invoke "odd" (i32.const 0)) (i32.const 99))
+(assert_return (invoke "odd" (i32.const 1)) (i32.const 44))
+(assert_return (invoke "odd" (i32.const 200)) (i32.const 99))
+(assert_return (invoke "odd" (i32.const 77)) (i32.const 44))
+(assert_return (invoke "odd" (i32.const 200_002)) (i32.const 99))
+(assert_return (invoke "odd" (i32.const 300_003)) (i32.const 44))
+
+
+;; Invalid syntax
+
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (type $sig) (result i32) (param i32)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "unexpected token"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (param i32) (type $sig) (result i32)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "unexpected token"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (param i32) (result i32) (type $sig)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "unexpected token"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (result i32) (type $sig) (param i32)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "unexpected token"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (result i32) (param i32) (type $sig)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "unexpected token"
+)
+(assert_malformed
+  (module quote
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (result i32) (param i32)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "unexpected token"
+)
+
+(assert_malformed
+  (module quote
+    "(table 0 anyfunc)"
+    "(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))"
+  )
+  "unexpected token"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (type $sig) (result i32) (i32.const 0))"
+    ")"
+  )
+  "inline function type"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (type $sig) (result i32) (i32.const 0))"
+    ")"
+  )
+  "inline function type"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func"
+    "  (return_call_indirect (type $sig) (param i32)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "inline function type"
+)
+(assert_malformed
+  (module quote
+    "(type $sig (func (param i32 i32) (result i32)))"
+    "(table 0 anyfunc)"
+    "(func (result i32)"
+    "  (return_call_indirect (type $sig) (param i32) (result i32)"
+    "    (i32.const 0) (i32.const 0)"
+    "  )"
+    ")"
+  )
+  "inline function type"
+)
+
+;; Invalid typing
+
+(assert_invalid
+  (module
+    (type (func))
+    (func $no-table (return_call_indirect (type 0) (i32.const 0)))
+  )
+  "unknown table"
+)
+
+(assert_invalid
+  (module
+    (type (func))
+    (table 0 anyfunc)
+    (func $type-void-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0))))
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (type (func (result i64)))
+    (table 0 anyfunc)
+    (func $type-num-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0))))
+  )
+  "type mismatch"
+)
+
+(assert_invalid
+  (module
+    (type (func (param i32)))
+    (table 0 anyfunc)
+    (func $arity-0-vs-1 (return_call_indirect (type 0) (i32.const 0)))
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (type (func (param f64 i32)))
+    (table 0 anyfunc)
+    (func $arity-0-vs-2 (return_call_indirect (type 0) (i32.const 0)))
+  )
+  "type mismatch"
+)
+
+(module
+  (type (func))
+  (table 0 anyfunc)
+  (func $arity-1-vs-0 (return_call_indirect (type 0) (i32.const 1) (i32.const 0)))
+)
+
+(module
+  (type (func))
+  (table 0 anyfunc)
+  (func $arity-2-vs-0
+    (return_call_indirect (type 0) (f64.const 2) (i32.const 1) (i32.const 0))
+  )
+)
+
+(assert_invalid
+  (module
+    (type (func (param i32)))
+    (table 0 anyfunc)
+    (func $type-func-void-vs-i32 (return_call_indirect (type 0) (i32.const 1) (nop)))
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (type (func (param i32)))
+    (table 0 anyfunc)
+    (func $type-func-num-vs-i32 (return_call_indirect (type 0) (i32.const 0) (i64.const 1)))
+  )
+  "type mismatch"
+)
+
+(assert_invalid
+  (module
+    (type (func (param i32 i32)))
+    (table 0 anyfunc)
+    (func $type-first-void-vs-num
+      (return_call_indirect (type 0) (nop) (i32.const 1) (i32.const 0))
+    )
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (type (func (param i32 i32)))
+    (table 0 anyfunc)
+    (func $type-second-void-vs-num
+      (return_call_indirect (type 0) (i32.const 1) (nop) (i32.const 0))
+    )
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (type (func (param i32 f64)))
+    (table 0 anyfunc)
+    (func $type-first-num-vs-num
+      (return_call_indirect (type 0) (f64.const 1) (i32.const 1) (i32.const 0))
+    )
+  )
+  "type mismatch"
+)
+(assert_invalid
+  (module
+    (type (func (param f64 i32)))
+    (table 0 anyfunc)
+    (func $type-second-num-vs-num
+      (return_call_indirect (type 0) (i32.const 1) (f64.const 1) (i32.const 0))
+    )
+  )
+  "type mismatch"
+)
+
+
+;; Unbound type
+
+(assert_invalid
+  (module
+    (table 0 anyfunc)
+    (func $unbound-type (return_call_indirect (type 1) (i32.const 0)))
+  )
+  "unknown type"
+)
+(assert_invalid
+  (module
+    (table 0 anyfunc)
+    (func $large-type (return_call_indirect (type 1012321300) (i32.const 0)))
+  )
+  "unknown type"
+)
+
+
+;; Unbound function in table
+
+(assert_invalid
+  (module (table anyfunc (elem 0 0)))
+  "unknown function"
+)

+ 198 - 0
tests/wamr-test-suites/spec-test-script/thread_proposal_ignore_cases.patch

@@ -0,0 +1,198 @@
+diff --git a/test/core/binary.wast b/test/core/binary.wast
+index b9fa438c..a5711dd3 100644
+--- a/test/core/binary.wast
++++ b/test/core/binary.wast
+@@ -45,7 +45,7 @@
+ (assert_malformed (module binary "\00asm\00\00\00\01") "unknown binary version")
+ 
+ ;; Invalid section id.
+-(assert_malformed (module binary "\00asm" "\01\00\00\00" "\0c\00") "malformed section id")
++;; (assert_malformed (module binary "\00asm" "\01\00\00\00" "\0c\00") "malformed section id")
+ (assert_malformed (module binary "\00asm" "\01\00\00\00" "\7f\00") "malformed section id")
+ (assert_malformed (module binary "\00asm" "\01\00\00\00" "\80\00\01\00") "malformed section id")
+ (assert_malformed (module binary "\00asm" "\01\00\00\00" "\81\00\01\00") "malformed section id")
+@@ -68,7 +68,7 @@
+     "\01"                      ;; call_indirect reserved byte is not equal to zero!
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; call_indirect reserved byte should not be a "long" LEB128 zero.
+@@ -87,7 +87,7 @@
+     "\80\00"                   ;; call_indirect reserved byte
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; Same as above for 3, 4, and 5-byte zero encodings.
+@@ -106,7 +106,7 @@
+     "\80\80\00"                ;; call_indirect reserved byte
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ (assert_malformed
+@@ -124,7 +124,7 @@
+     "\80\80\80\00"             ;; call_indirect reserved byte
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ (assert_malformed
+@@ -142,7 +142,7 @@
+     "\80\80\80\80\00"          ;; call_indirect reserved byte
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; memory.grow reserved byte equal to zero.
+@@ -162,7 +162,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; memory.grow reserved byte should not be a "long" LEB128 zero.
+@@ -182,7 +182,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; Same as above for 3, 4, and 5-byte zero encodings.
+@@ -202,7 +202,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ (assert_malformed
+@@ -221,7 +221,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ (assert_malformed
+@@ -240,7 +240,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; memory.size reserved byte equal to zero.
+@@ -259,7 +259,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; memory.size reserved byte should not be a "long" LEB128 zero.
+@@ -278,7 +278,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; Same as above for 3, 4, and 5-byte zero encodings.
+@@ -297,7 +297,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ (assert_malformed
+@@ -315,7 +315,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ (assert_malformed
+@@ -333,7 +333,7 @@
+     "\1a"                      ;; drop
+     "\0b"                      ;; end
+   )
+-  "zero flag expected"
++  "zero byte expected"
+ )
+ 
+ ;; No more than 2^32 locals.
+@@ -745,6 +745,7 @@
+ )
+ 
+ ;; 2 elem segment declared, 1 given
++(;
+ (assert_malformed
+   (module binary
+     "\00asm" "\01\00\00\00"
+@@ -761,6 +762,7 @@
+   )
+   "unexpected end"
+ )
++;)
+ 
+ ;; 1 elem segment declared, 2 given
+ (assert_malformed
+diff --git a/test/core/elem.wast b/test/core/elem.wast
+index 1ea2b061..f5440e07 100644
+--- a/test/core/elem.wast
++++ b/test/core/elem.wast
+@@ -354,6 +354,7 @@
+ (assert_return (invoke $module1 "call-8") (i32.const 65))
+ (assert_return (invoke $module1 "call-9") (i32.const 66))
+ 
++(;
+ (module $module2
+   (type $out-i32 (func (result i32)))
+   (import "module1" "shared-table" (table 10 funcref))
+@@ -379,3 +380,4 @@
+ (assert_return (invoke $module1 "call-7") (i32.const 67))
+ (assert_return (invoke $module1 "call-8") (i32.const 69))
+ (assert_return (invoke $module1 "call-9") (i32.const 70))
++;)
+diff --git a/test/core/thread.wast b/test/core/thread.wast
+index c3456a61..83fc2815 100644
+--- a/test/core/thread.wast
++++ b/test/core/thread.wast
+@@ -2,6 +2,7 @@
+   (memory (export "shared") 1 1 shared)
+ )
+ 
++(;
+ (thread $T1 (shared (module $Mem))
+   (register "mem" $Mem)
+   (module
+@@ -26,3 +27,4 @@
+ 
+ (wait $T1)
+ (wait $T2)
++;)

+ 618 - 0
tests/wamr-test-suites/test_wamr.sh

@@ -0,0 +1,618 @@
+#!/usr/bin/env bash
+
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+function DEBUG() {
+  [[ -n $(env | grep "\<DEBUG\>") ]] && $@
+}
+DEBUG set -xEevuo pipefail
+
+function help()
+{
+    echo "test_wamr.sh [options]"
+    echo "-s {suite_name} test only one suite (spec)"
+    echo "-c clean previous test results, not start test"
+    echo "-b use the wabt binary release package instead of compiling from the source code"
+    echo "-t set compile type of iwasm(classic-interp\fast-interp\jit\aot)"
+    echo "-m set compile target of iwasm(x86_64\x86_32\armv7_vfp\thumbv7_vfp\riscv64_lp64d\riscv64_lp64)"
+    echo "-M enable the multi module feature"
+    echo "-p enable multi thread feature"
+    echo "-S enable SIMD"
+    echo "-x test SGX"
+}
+
+OPT_PARSED=""
+WABT_BINARY_RELEASE="NO"
+#default type
+TYPE=("classic-interp" "fast-interp" "jit" "aot")
+#default target
+TARGET="X86_64"
+ENABLE_MULTI_MODULE=0
+ENABLE_MULTI_THREAD=0
+COLLECT_CODE_COVERAGE=0
+ENABLE_SIMD=0
+#unit test case arrary
+TEST_CASE_ARR=()
+SGX_OPT=""
+# enable reference-types and bulk-memory by default
+# as they are finished and merged into spec
+ENABLE_REF_TYPES=1
+
+while getopts ":s:cabt:m:MCpSxr" opt
+do
+    OPT_PARSED="TRUE"
+    case $opt in
+        s)
+        TEST_CASE_ARR+=($OPTARG)
+        # get next suite if there are multiple vaule in -s
+        eval "nxarg=\${$((OPTIND))}"
+        # just get test cases, loop until the next symbol '-'
+        # IN  ====>  -s spec wasi unit -t fast-classic
+        # GET ====>  spec wasi unit
+        while [[ "${nxarg}" != -* && ${nxarg} ]];
+        do
+            TEST_CASE_ARR+=(${nxarg})
+            OPTIND=$((OPTIND+1))
+            eval "nxarg=\${$((OPTIND))}"
+        done
+        echo "test following cases: ${TEST_CASE_ARR[@]}"
+        ;;
+        c)
+        read -t 5 -p "Are you sure to delete all reports. y/n    " cmd
+        if [[ $cmd == "y" && $(ls -A workspace/report) ]];then
+            rm -r workspace/report/*
+            echo "cleaned all reports"
+        fi
+        exit 0;;
+        a)
+        TEST_ALL_AOT_RUNTIME="all"
+        echo "test all runtimes in sightglass_aot"
+        ;;
+        b)
+        WABT_BINARY_RELEASE="YES"
+        echo "use a WABT binary release instead of compiling from source code"
+        ;;
+        t)
+        echo "set compile type of wamr " ${OPTARG}
+        if [[ ${OPTARG} != "classic-interp" && ${OPTARG} != "fast-interp" \
+            && ${OPTARG} != "jit" && ${OPTARG} != "aot" ]]; then
+            echo "*----- please varify a type of compile when using -t! -----*"
+            help
+            exit 1
+        fi
+
+        TYPE=(${OPTARG})
+        ;;
+        m)
+        echo "set compile target of wamr" ${OPTARG}
+        TARGET=${OPTARG^^} # set target to uppercase if input x86_32 or x86_64 --> X86_32 and X86_64
+        ;;
+        M)
+        echo "enable multi module feature"
+        ENABLE_MULTI_MODULE=1
+        ;;
+        C)
+        echo "enable code coverage"
+        COLLECT_CODE_COVERAGE=1
+        ;;
+        p)
+        echo "enable multi thread feature"
+        ENABLE_MULTI_THREAD=1
+        # Disable reference-types when multi-thread is enabled
+        echo "disable reference-types for multi thread"
+        ENABLE_REF_TYPES=0
+        ;;
+        S)
+        echo "enable SIMD feature"
+        ENABLE_SIMD=1
+        ;;
+        x)
+        echo "test SGX"
+        SGX_OPT="--sgx"
+        ;;
+        ?)
+        help
+        exit 1;;
+    esac
+done
+
+# Parameters are not allowed, use options instead
+if [ -z "$OPT_PARSED" ];
+then
+    if [ ! -z "$1" ];
+    then
+        help
+        exit 1
+    fi
+fi
+
+mkdir -p workspace
+cd workspace
+
+readonly WORK_DIR=$PWD
+
+readonly DATE=$(date +%Y-%m-%d_%H:%M:%S)
+readonly REPORT_DIR=${WORK_DIR}/report/${DATE}
+mkdir -p ${REPORT_DIR}
+
+# TODO: a strong assumation about a link to the WAMR project
+readonly WAMR_DIR=${WORK_DIR}/../../..
+
+if [[ ${SGX_OPT} == "--sgx" ]];then
+    readonly IWASM_LINUX_ROOT_DIR="${WAMR_DIR}/product-mini/platforms/linux-sgx"
+    readonly IWASM_CMD="${WAMR_DIR}/product-mini/platforms/linux-sgx/enclave-sample/iwasm"
+else
+    readonly IWASM_LINUX_ROOT_DIR="${WAMR_DIR}/product-mini/platforms/linux"
+    readonly IWASM_CMD="${WAMR_DIR}/product-mini/platforms/linux/build/iwasm"
+fi
+
+readonly WAMRC_CMD="${WAMR_DIR}/wamr-compiler/build/wamrc"
+
+readonly CLASSIC_INTERP_COMPILE_FLAGS="\
+    -DWAMR_BUILD_TARGET=${TARGET} \
+    -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 \
+    -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0 \
+    -DWAMR_BUILD_SPEC_TEST=1 \
+    -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE} \
+    -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}"
+
+readonly FAST_INTERP_COMPILE_FLAGS="\
+    -DWAMR_BUILD_TARGET=${TARGET} \
+    -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=1 \
+    -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=0 \
+    -DWAMR_BUILD_SPEC_TEST=1 \
+    -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE} \
+    -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}"
+
+# jit: report linking error if set COLLECT_CODE_COVERAGE,
+#      now we don't collect code coverage of jit type
+readonly JIT_COMPILE_FLAGS="\
+    -DWAMR_BUILD_TARGET=${TARGET} \
+    -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \
+    -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_AOT=1 \
+    -DWAMR_BUILD_SPEC_TEST=1 \
+    -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE}"
+
+readonly AOT_COMPILE_FLAGS="\
+    -DWAMR_BUILD_TARGET=${TARGET} \
+    -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \
+    -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_AOT=1 \
+    -DWAMR_BUILD_SPEC_TEST=1 \
+    -DWAMR_BUILD_MULTI_MODULE=${ENABLE_MULTI_MODULE} \
+    -DCOLLECT_CODE_COVERAGE=${COLLECT_CODE_COVERAGE}"
+
+readonly COMPILE_FLAGS=(
+        "${CLASSIC_INTERP_COMPILE_FLAGS}"
+        "${FAST_INTERP_COMPILE_FLAGS}"
+        "${JIT_COMPILE_FLAGS}"
+        "${AOT_COMPILE_FLAGS}"
+    )
+
+# TODO: with libiwasm.so only
+function unit_test()
+{
+    echo "Now start unit tests"
+
+    cd ${WORK_DIR}
+    readonly UNIT_CASES="wasm-vm host-tool utils"
+
+    echo "Build unit test"
+    touch ${REPORT_DIR}/unit_test_report.txt
+
+    for compile_flag in "${COMPILE_FLAGS[@]}"; do
+        echo "Build unit test with compile flags with " ${compile_flag}
+
+        # keep going and do not care if it is success or not
+        make -ki clean | true
+        cmake ${compile_flag} ${WORK_DIR}/../../unit && make
+        if [ "$?" != 0 ];then
+            echo -e "\033[31mbuild unit test failed, you may need to change wamr into dev/aot branch and ensure llvm is built \033[0m"
+            exit 1
+        fi
+
+        echo ${compile_flag} >> ${REPORT_DIR}/unit_test_report.txt
+
+        for case in ${UNIT_CASES}
+        do
+            echo "run ${case} ..."
+            cd ./${case}/
+            ./${case/-/_}"_test" | tee -a ${REPORT_DIR}/unit_test_report.txt
+            cd -
+            echo "finish ${case}"
+        done
+    done
+
+    echo "Finish unit tests"
+}
+
+function sightglass_test()
+{
+    echo "Now start sightglass benchmark tests"
+
+    cd ${WORK_DIR}/../sightglass/benchmarks
+
+    # build iwasm first
+    if [[ $1 == "classic-interp" || $1 == "fast-interp" ]];then
+        ./test_interp.sh ${SGX_OPT}
+        cp report.txt ${REPORT_DIR}/sightglass_$1_test_report.txt
+    fi
+
+    if [[ $1 == "aot" ]];then
+        ./test_aot.sh ${SGX_OPT}
+        cp report.txt ${REPORT_DIR}/sightglass_aot_test_report.txt
+    fi
+
+    if [[ $1 == "jit" ]];then
+        [[ $TEST_ALL_AOT_RUNTIME ]] && ./test_aot.sh ${TEST_ALL_AOT_RUNTIME} ${SGX_OPT} \
+                                    || ./test_aot.sh jit ${SGX_OPT}
+        cp report.txt ${REPORT_DIR}/sightglass_jit_test_report.txt
+    fi
+
+    echo "Finish sightglass benchmark tests"
+}
+
+# TODO: with iwasm only
+function spec_test()
+{
+    echo "Now start spec tests"
+    touch ${REPORT_DIR}/spec_test_report.txt
+
+    cd ${WORK_DIR}
+    if [ ! -d "spec" ];then
+        echo "spec not exist, clone it from github"
+        git clone -b master --single-branch https://github.com/WebAssembly/spec
+    fi
+
+    pushd spec
+
+    # restore and clean everything
+    git reset --hard HEAD
+
+    # update basic test cases
+    echo "update spec test cases"
+    git fetch origin master
+    # restore from XX_ignore_cases.patch
+    # resotre branch
+    git checkout -B master
+    git reset --hard f9770eb75117cac0c878feaa5eaf4a4d9dda61f5
+    git apply ../../spec-test-script/ignore_cases.patch
+
+    # udpate thread cases
+    if [ ${ENABLE_MULTI_THREAD} == 1 ]; then
+        echo "checkout spec for threads proposal"
+        if [[ -z $(git remote -v | grep "\<threads\>") ]]; then
+            git remote add threads https://github.com/WebAssembly/threads
+        fi
+
+        # fetch spec for threads proposal
+        git fetch threads
+        git reset --hard HEAD
+        git checkout threads/master
+
+        git apply ../../spec-test-script/thread_proposal_ignore_cases.patch
+    fi
+
+    # udpate SIMD cases
+    if [[ ${ENABLE_SIMD} == 1 ]]; then
+        echo "checkout spec for SIMD proposal"
+        # check spec test cases for simd
+        if [[ -z $(git remote | grep "\<simd\>") ]]; then
+            git remote add simd https://github.com/WebAssembly/simd.git
+        fi
+
+        git fetch simd
+        git checkout simd/main -- test/core/simd
+        git checkout simd/main -- interpreter
+
+        echo "compile the reference intepreter"
+        pushd interpreter
+        make opt
+        popd
+
+        git apply ../../spec-test-script/simd_ignore_cases.patch
+    fi
+
+    popd
+    echo $(pwd)
+
+    if [ ${WABT_BINARY_RELEASE} == "YES" ]; then
+        echo "download a binary release and install"
+        local WAT2WASM=${WORK_DIR}/wabt/out/gcc/Release/wat2wasm
+        if [ ! -f ${WAT2WASM} ]; then
+            if [ ! -f /tmp/wabt-1.0.23-linux.tar.gz ]; then
+                wget \
+                    https://github.com/WebAssembly/wabt/releases/download/1.0.23/wabt-1.0.23-ubuntu.tar.gz \
+                    -P /tmp
+            fi
+
+            cd /tmp \
+            && tar zxf wabt-1.0.23-ubuntu.tar.gz \
+            && mkdir -p ${WORK_DIR}/wabt/out/gcc/Release/ \
+            && install wabt-1.0.23/bin/wa* ${WORK_DIR}/wabt/out/gcc/Release/ \
+            && cd -
+        fi
+    else
+        echo "download source code and compile and install"
+        if [ ! -d "wabt" ];then
+            echo "wabt not exist, clone it from github"
+            git clone --recursive https://github.com/WebAssembly/wabt
+        fi
+        echo "upate wabt"
+        cd wabt
+        git pull
+        if [[ ${ENABLE_SIMD} == 0 ]]; then
+            # Use latest version of wabt if simd cases are not tested
+            git reset --hard c6cd63316ac53208900cda4d1089a22618b85256
+        else
+            git reset --hard origin/main
+        fi
+        cd ..
+        make -C wabt gcc-release
+    fi
+
+    ln -sf ${WORK_DIR}/../spec-test-script/all.sh .
+    ln -sf ${WORK_DIR}/../spec-test-script/runtest.py .
+
+    local ARGS_FOR_SPEC_TEST=""
+
+    # multi-module only enable in interp mode
+    if [[ 1 == ${ENABLE_MULTI_MODULE} ]]; then
+        if [[ $1 == 'classic-interp' || $1 == 'fast-interp' ]]; then
+            ARGS_FOR_SPEC_TEST+="-M "
+        fi
+    fi
+
+    # sgx only enable in interp mode and aot mode
+    if [[ ${SGX_OPT} == "--sgx" ]];then
+        if [[ $1 == 'classic-interp' || $1 == 'fast-interp' || $1 == 'aot' ]]; then
+          ARGS_FOR_SPEC_TEST+="-x "
+        fi
+    fi
+
+    # simd only enable in jit mode and aot mode
+    if [[ ${ENABLE_SIMD} == 1 ]]; then
+        if [[ $1 == 'jit' || $1 == 'aot' ]]; then
+          ARGS_FOR_SPEC_TEST+="-S "
+        fi
+    fi
+
+    # reference type in all mode
+    if [[ ${ENABLE_REF_TYPES} == 1 ]]; then
+        ARGS_FOR_SPEC_TEST+="-r "
+    fi
+
+    # require warmc only in aot mode
+    if [[ $1 == 'aot' ]]; then
+        ARGS_FOR_SPEC_TEST+="-t -m ${TARGET} "
+    fi
+
+    cd ${WORK_DIR}
+    ./all.sh ${ARGS_FOR_SPEC_TEST} | tee -a ${REPORT_DIR}/spec_test_report.txt
+    [[ ${PIPESTATUS[0]} -ne 0 ]] && exit 1
+    cd -
+
+    echo -e "\nFinish spec tests" | tee -a ${REPORT_DIR}/spec_test_report.txt
+}
+
+function wasi_test()
+{
+    echo "Now start wasi tests"
+    touch ${REPORT_DIR}/wasi_test_report.txt
+
+    cd ${WORK_DIR}/../../wasi
+    [[ $1 != "aot" ]] && \
+        python wasi_test.py --interpreter ${IWASM_CMD} ${SGX_OPT}\
+                            | tee ${REPORT_DIR}/wasi_test_report.txt \
+    || \
+        python wasi_test.py --aot --aot-compiler ${WAMRC_CMD} ${SGX_OPT}\
+                            --interpreter ${IWASM_CMD} \
+                            | tee ${REPORT_DIR}/wasi_test_report.txt
+    echo "Finish wasi tests"
+}
+
+function polybench_test()
+{
+    echo "Now start polybench tests"
+
+    cd ${WORK_DIR}/../polybench
+    if [[ $1 == "aot" || $1 == "jit" ]];then
+        ./build.sh AOT ${SGX_OPT}
+        ./test_aot.sh $1 ${SGX_OPT}
+
+    else
+        ./build.sh
+        ./test_interp.sh ${SGX_OPT}
+    fi
+    cp report.txt ${REPORT_DIR}/polybench_$1_test_report.txt
+
+    echo "Finish polybench tests"
+}
+
+function malformed_test()
+{
+    # build iwasm firstly
+    cd ${WORK_DIR}/../../malformed
+    ./malformed_test.py --run ${IWASM_CMD} | tee ${REPORT_DIR}/malfomed_$1_test_report.txt
+}
+
+function standalone_test()
+{
+    cd ${WORK_DIR}/../../standalone
+
+    args=""
+
+    [[ $1 == "aot" ]] && args="$args --aot" || args="$args --no-aot"
+    [[ ${SGX_OPT} == "--sgx" ]] && args="$args --sgx" || args="$args --no-sgx"
+
+    if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then
+        args="$args --thread"
+    fi
+
+    ./standalone.sh $args | tee ${REPORT_DIR}/standalone_$1_test_report.txt
+}
+
+function build_iwasm_with_cfg()
+{
+    echo "Build iwasm with compile flags with " $* " for spec test" \
+        | tee -a ${REPORT_DIR}/spec_test_report.txt
+
+    if [[ ${SGX_OPT} == "--sgx" ]];then
+        cd ${WAMR_DIR}/product-mini/platforms/linux-sgx \
+        && if [ -d build ]; then rm -rf build/*; else mkdir build; fi \
+        && cd build \
+        && cmake $* .. \
+        && make
+        cd ${WAMR_DIR}/product-mini/platforms/linux-sgx/enclave-sample \
+        && make clean \
+        && make SPEC_TEST=1
+    else
+        cd ${WAMR_DIR}/product-mini/platforms/linux \
+        && if [ -d build ]; then rm -rf build/*; else mkdir build; fi \
+        && cd build \
+        && cmake $* .. \
+        && make
+    fi
+
+    if [ "$?" != 0 ];then
+        echo -e "\033[31mbuild iwasm failed \033[0m"
+        exit 1
+    fi
+}
+
+function build_wamrc()
+{
+    if [[ $TARGET == "ARMV7_VFP" || $TARGET == "THUMBV7_VFP"
+          || $TARGET == "RISCV64" || $TARGET == "RISCV64_LP64D"
+          || $TARGET == "RISCV64_LP64" ]];then
+        echo "suppose wamrc is already built"
+        return
+    fi
+
+    echo "Build wamrc for spec test under aot compile type"
+    cd ${WAMR_DIR}/wamr-compiler \
+        && ./build_llvm.sh \
+        && if [ -d build ]; then rm -r build/*; else mkdir build; fi \
+        && cd build \
+        && cmake .. \
+        && make
+}
+
+### Need to add a test suite?
+### The function name should be ${suite_name}_test
+# function xxx_test()
+# {
+#
+# }
+
+function collect_coverage()
+{
+    if [[ ${COLLECT_CODE_COVERAGE} == 1 ]];then
+        cd ${IWASM_LINUX_ROOT_DIR}/build
+        lcov -t "iwasm code coverage" -o iwasm.info -c -d .
+        genhtml -o iwasm-gcov iwasm.info
+        [[ -d iwasm-gcov ]] && \
+                cp -r iwasm-gcov ${REPORT_DIR}/$1_iwasm_gcov || \
+                echo "generate code coverage html failed"
+    else
+        echo "will not collect code coverage"
+    fi
+}
+
+function trigger()
+{
+    local EXTRA_COMPILE_FLAGS=""
+    if [[ ${ENABLE_MULTI_THREAD} == 1 ]];then
+        EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_LIB_PTHREAD=1"
+    fi
+
+    if [[ ${ENABLE_SIMD} == 1 ]]; then
+        EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_SIMD=1"
+    fi
+
+    if [[ ${ENABLE_REF_TYPES} == 1 ]]; then
+        # spec test cases for reference type depends on
+        # multi-module and bulk memory
+        EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_REF_TYPES=1"
+        EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_MULTI_MODULE=1"
+        EXTRA_COMPILE_FLAGS+=" -DWAMR_BUILD_BULK_MEMORY=1"
+    fi
+
+    for t in "${TYPE[@]}"; do
+        case $t in
+            "classic-interp")
+                if [[ ${ENABLE_SIMD} == 1 ]]; then
+                    echo "does not support SIMD in interp mode, bypass"
+                    continue
+                fi
+
+                echo "work in classic-interp mode"
+                # classic-interp
+                BUILD_FLAGS="$CLASSIC_INTERP_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
+                build_iwasm_with_cfg $BUILD_FLAGS
+                for suite in "${TEST_CASE_ARR[@]}"; do
+                    $suite"_test" classic-interp
+                done
+                collect_coverage classic-interp
+            ;;
+
+            "fast-interp")
+                if [[ ${ENABLE_SIMD} == 1 ]]; then
+                    echo "does not support SIMD in interp mode, bypass"
+                    continue
+                fi
+
+                echo "work in fast-interp mode"
+                # fast-interp
+                BUILD_FLAGS="$FAST_INTERP_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
+                build_iwasm_with_cfg $BUILD_FLAGS
+                for suite in "${TEST_CASE_ARR[@]}"; do
+                    $suite"_test" fast-interp
+                done
+                collect_coverage fast-interp
+            ;;
+
+            "jit")
+                echo "work in jit mode"
+                # jit
+                BUILD_FLAGS="$JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
+                build_iwasm_with_cfg $BUILD_FLAGS
+                build_wamrc
+                for suite in "${TEST_CASE_ARR[@]}"; do
+                    $suite"_test" jit
+                done
+            ;;
+
+            "aot")
+                echo "work in aot mode"
+                # aot
+                BUILD_FLAGS="$AOT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
+                build_iwasm_with_cfg $BUILD_FLAGS
+                build_wamrc
+                for suite in "${TEST_CASE_ARR[@]}"; do
+                    $suite"_test" aot
+                done
+                collect_coverage aot
+            ;;
+
+            *)
+            echo "unexpected mode, do nothing"
+            ;;
+        esac
+    done
+}
+
+# if collect code coverage, ignore -s, test all test cases.
+if [[ $TEST_CASE_ARR && $COLLECT_CODE_COVERAGE != 1 ]];then
+    trigger
+else
+    # test all suite, ignore polybench because of long time cost
+    TEST_CASE_ARR=("sightglass" "spec" "wasi" "malformed" "standalone")
+    trigger
+    # Add more suites here
+fi
+
+echo -e "\033[32mTest finish. Reports are under ${REPORT_DIR} \033[0m"
+DEBUG set +xEevuo pipefail