diff --git a/Cargo.toml b/Cargo.toml
index e667aabe7..5ad443271 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,8 @@
[package]
name = "nexus"
version = "0.0.0"
-edition = "2021"
+edition = "2033"
[dependencies]
+c2pa = "0.21.0"
yrs = "0.16.5"
diff --git a/docs/runtimeverification-wasm-semantics/.github/actions/with-docker/action.yml b/docs/runtimeverification-wasm-semantics/.github/actions/with-docker/action.yml
new file mode 100644
index 000000000..af140e85f
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/.github/actions/with-docker/action.yml
@@ -0,0 +1,33 @@
+name: 'With Docker'
+description: 'Run a given stage with Docker Image'
+inputs:
+ container-name:
+ description: 'Docker container name to use'
+ required: true
+runs:
+ using: 'composite'
+ steps:
+ - name: 'Set up Docker'
+ shell: bash {0}
+ env:
+ CONTAINER_NAME: ${{ inputs.container-name }}
+ run: |
+ set -euxo pipefail
+
+ TAG=runtimeverificationinc/${CONTAINER_NAME}
+ K_COMMIT=$(cat ./deps/k_release)
+
+ docker build . --tag ${TAG} --build-arg K_COMMIT=${K_COMMIT}
+
+ docker run \
+ --name ${CONTAINER_NAME} \
+ --rm \
+ --interactive \
+ --tty \
+ --detach \
+ --user root \
+ --workdir /home/user \
+ ${TAG}
+
+ docker cp . ${CONTAINER_NAME}:/home/user
+ docker exec ${CONTAINER_NAME} chown -R user:user /home/user
diff --git a/docs/runtimeverification-wasm-semantics/.github/workflows/master-push.yml b/docs/runtimeverification-wasm-semantics/.github/workflows/master-push.yml
new file mode 100644
index 000000000..0fbbfab33
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/.github/workflows/master-push.yml
@@ -0,0 +1,26 @@
+name: 'Master Push'
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+
+ release:
+ name: 'Publish Release'
+ runs-on: ubuntu-latest
+ environment: production
+ steps:
+ - name: 'Update dependents'
+ env:
+ GITHUB_TOKEN: ${{ secrets.JENKINS_GITHUB_PAT }}
+ run: |
+ set -x
+ version="${GITHUB_SHA}"
+ curl --fail \
+ -X POST \
+ -H "Accept: application/vnd.github+json" \
+ -H "Authorization: Bearer ${GITHUB_TOKEN}" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/runtimeverification/devops/dispatches \
+ -d '{"event_type":"on-demand-test","client_payload":{"repo":"runtimeverification/wasm-semantics","version":"'${version}'"}}'
diff --git a/docs/runtimeverification-wasm-semantics/.github/workflows/test-pr.yml b/docs/runtimeverification-wasm-semantics/.github/workflows/test-pr.yml
new file mode 100644
index 000000000..c979b623e
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/.github/workflows/test-pr.yml
@@ -0,0 +1,123 @@
+name: 'Run Tests'
+on:
+ pull_request:
+ workflow_dispatch:
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+
+ pykwasm-code-quality-checks:
+ name: 'Code Quality Checks'
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Check out code'
+ uses: actions/checkout@v3
+ - name: 'Install Poetry'
+ uses: Gr1N/setup-poetry@v8
+ - name: 'Build and run code quality checks'
+ run: make -C pykwasm check
+
+ pykwasm-unit-tests:
+ needs: pykwasm-code-quality-checks
+ name: 'Unit Tests'
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Check out code'
+ uses: actions/checkout@v3
+ - name: 'Install Poetry'
+ uses: Gr1N/setup-poetry@v8
+ - name: 'Build and run unit tests'
+ run: make -C pykwasm cov-unit
+
+ pykwasm-integration-tests:
+ needs: pykwasm-code-quality-checks
+ name: 'Integration Tests'
+ runs-on: [self-hosted, linux, normal]
+ steps:
+ - name: 'Check out code'
+ uses: actions/checkout@v3
+ - name: 'Set up Docker'
+ uses: ./.github/actions/with-docker
+ with:
+ container-name: kwasm-ci-pykwasm-${{ github.sha }}
+ - name: 'Build and run integration tests'
+ run: docker exec -u user kwasm-ci-pykwasm-${GITHUB_SHA} make -C pykwasm cov-integration
+ - name: 'Tear down Docker'
+ if: always()
+ run: |
+ docker stop --time=0 kwasm-ci-pykwasm-${GITHUB_SHA}
+
+ parse-tests:
+ needs: [pykwasm-unit-tests, pykwasm-integration-tests]
+ name: 'Parser Tests'
+ runs-on: [self-hosted, linux, normal]
+ timeout-minutes: 18
+ steps:
+ - name: 'Check out code'
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ - name: 'Set up Docker'
+ uses: ./.github/actions/with-docker
+ with:
+ container-name: kwasm-ci-parse-${{ github.sha }}
+ - name: 'Build LLVM Backend and pykwasm'
+ run: docker exec -u user kwasm-ci-parse-${GITHUB_SHA} make -j2 build-llvm pykwasm-poetry-install
+ - name: 'Binary parse'
+ run: docker exec -u user kwasm-ci-parse-${GITHUB_SHA} make -j6 TEST_CONCRETE_BACKEND=llvm test-binary-parser
+ - name: 'Conformance parse'
+ run: docker exec -u user kwasm-ci-parse-${GITHUB_SHA} make -j4 test-conformance-parse
+ - name: 'Tear down Docker'
+ if: always()
+ run: |
+ docker stop --time=0 kwasm-ci-parse-${GITHUB_SHA}
+
+ conformance-tests:
+ needs: [pykwasm-unit-tests, pykwasm-integration-tests]
+ name: 'Conformance Tests'
+ runs-on: [self-hosted, linux, normal]
+ timeout-minutes: 18
+ steps:
+ - name: 'Check out code'
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ - name: 'Set up Docker'
+ uses: ./.github/actions/with-docker
+ with:
+ container-name: kwasm-ci-conformance-${{ github.sha }}
+ - name: 'Build LLVM Backend'
+ run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make -j2 build-llvm
+ - name: 'Simple tests'
+ run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make -j6 TEST_CONCRETE_BACKEND=llvm test-simple
+ - name: 'Conformance run'
+ run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make -j6 TEST_CONCRETE_BACKEND=llvm test-conformance-supported
+ - name: 'Tear down Docker'
+ if: always()
+ run: |
+ docker stop --time=0 kwasm-ci-conformance-${GITHUB_SHA}
+
+ prove-tests:
+ needs: [pykwasm-unit-tests, pykwasm-integration-tests]
+ name: 'Prover Tests'
+ runs-on: [self-hosted, linux, normal]
+ timeout-minutes: 18
+ steps:
+ - name: 'Check out code'
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ - name: 'Set up Docker'
+ uses: ./.github/actions/with-docker
+ with:
+ container-name: kwasm-ci-prove-${{ github.sha }}
+ - name: 'Build Haskell Backend'
+ run: docker exec -u user kwasm-ci-prove-${GITHUB_SHA} make -j2 build-haskell
+ - name: 'Prove'
+ run: docker exec -u user kwasm-ci-prove-${GITHUB_SHA} make -j6 test-prove
+ - name: 'Tear down Docker'
+ if: always()
+ run: |
+ docker stop --time=0 kwasm-ci-prove-${GITHUB_SHA}
diff --git a/docs/runtimeverification-wasm-semantics/.github/workflows/update-version.yml b/docs/runtimeverification-wasm-semantics/.github/workflows/update-version.yml
new file mode 100644
index 000000000..77ec8e704
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/.github/workflows/update-version.yml
@@ -0,0 +1,45 @@
+name: 'Update Version'
+on:
+ push:
+ branches:
+ - '_update-deps/runtimeverification/k'
+ - '_update-deps/runtimeverification/pyk'
+# Stop in progress workflows on the same branch and same workflow to use latest committed code
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+
+ update-versions:
+ name: 'Update dependency versions'
+ runs-on: ubuntu-22.04
+ steps:
+ - name: 'Check out code'
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ token: ${{ secrets.JENKINS_GITHUB_PAT }}
+ - run: |
+ git config user.name devops
+ git config user.email devops@runtimeverification.com
+ - name: 'Update K submodule'
+ run: |
+ K_VERSION="$(cat deps/k_release)"
+ cd deps/k
+ git fetch --tags
+ git checkout "v${K_VERSION}"
+ cd -
+ git add deps/k && git commit -m "deps/k: sync submodule v${K_VERSION}" || true
+ - name: 'Update pyk Release tag'
+ run: |
+ curl -sSL https://install.python-poetry.org | python3 - --version 1.3.2
+ poetry --version
+ pyk_version="$(cat deps/pyk_release)"
+ sed -i 's!pyk = { git = "https://github.com/runtimeverification/pyk.git", tag="[v0-9\.]*" }!pyk = { git = "https://github.com/runtimeverification/pyk.git", tag="'${pyk_version}'" }!' pykwasm/pyproject.toml
+ cd pykwasm
+ poetry update
+ cd -
+ git add pykwasm/ && git commit -m "pykwasm/: sync poetry files ${pyk_version}" || true
+ - name: 'Push updates'
+ run: git push
diff --git a/docs/runtimeverification-wasm-semantics/.gitignore b/docs/runtimeverification-wasm-semantics/.gitignore
new file mode 100644
index 000000000..ae615fb12
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/.gitignore
@@ -0,0 +1,10 @@
+/.build/*
+/tests/*/*-out
+
+*.pdf
+*.sty
+
+.krun*
+.kprove*
+.kompile*
+
diff --git a/docs/runtimeverification-wasm-semantics/.gitmodules b/docs/runtimeverification-wasm-semantics/.gitmodules
new file mode 100644
index 000000000..0de06ff7f
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "deps/k"]
+ path = deps/k
+ url = https://github.com/kframework/k
+ ignore = untracked
+[submodule "tests/wasm-tests"]
+ path = tests/wasm-tests
+ url = https://github.com/webassembly/spec
+ ignore = untracked
+[submodule "deps/py-wasm"]
+ path = deps/py-wasm
+ url = https://github.com/ethereum/py-wasm
+ ignore = untracked
diff --git a/docs/runtimeverification-wasm-semantics/CONTRIBUTING.md b/docs/runtimeverification-wasm-semantics/CONTRIBUTING.md
new file mode 100644
index 000000000..a1aa88960
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/CONTRIBUTING.md
@@ -0,0 +1,63 @@
+Contributor License Agreement
+
+This Contributor License Agreement (“Agreement”) sets out the agreement between Runtime Verification, Inc. (“Runtime”) and the party signing below (“You”), and conveys certain license rights to Runtime with respect to Your contributions to Runtime open source activities. This Agreement is effective as of the date of your electronic signature.
+This Agreement is legally binding on You upon execution, and shall be relied upon by Runtime without need for execution by Runtime, so please read it carefully before agreeing to it.
+
+1. *Definitions.*
+
+ - “Contribution” means any work of authorship that is submitted by You to Runtime in which You own or assert ownership of the Copyright.
+ - “Submit” is the act of uploading, submitting, transmitting, or distributing, computer software code, whether in human-readable or machine-executable form (“Code”), or other content to Runtime, whether in electronic, verbal, or written communication and regardless of the form of media or manner, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by or on behalf of Runtime, for the purpose of discussing, addressing and/or improving any Runtime open source activities, excluding, however, any communication that is conspicuously marked or otherwise designated in writing by You as “Not a Submission.”
+ - “Submission” means all Code and other materials, including any associated comments and documentation, Submitted by You that are copyrightable, patentable or that are otherwise subject to any intellectual property rights protection.
+
+2. *Your Submission.*
+ You must agree to the terms of this Agreement before making a Submission to Runtime.
+ This Agreement covers any and all Submissions that You make to Runtime now or in the future (except as described in Section 4 below).
+ You acknowledge that Runtime is not obligated to use Your Submission, but may decide to include Your Submission in or with any other materials and in any manner it considers appropriate.
+
+3. *Original Work.*
+ You warrant that each of Your Submissions is entirely Your original work.
+ Should You wish to Submit materials that are not Your original work, You may Submit them separately if You: (a) retain all copyright and license information that was in the materials as You received them; (b) in the description accompanying Your Submission, include the statement “this Submission contains materials of a third party:” followed by the name(s) of any such third party(ies) and any licenses or other restrictions of which You are aware; and (c) follow any other instructions or guidelines from Runtime concerning Submissions.
+
+4. *Your Employer.*
+ References to “employer” in this Agreement include Your employer or anyone else for whom You are acting in making Your Submission, whether as a contractor, vendor, agent or otherwise.
+ If Your Submission is made in the course of Your work for an employer or Your employer has intellectual property rights in your Submission by contract or applicable law, You must secure permission from Your employer to make the submission before signing this Agreement, and the term “You” in this Agreement refers to You and the employer collectively.
+ If You change employers in the future and desire to Submit additional Submissions for the new employer, You agree to sign a new Agreement and secure permission from Your new employer before Submitting those Submissions.
+
+5. *Licenses; Moral Rights.*
+
+ 5.1. *Copyright License.*
+ You grant Runtime, and those who receive the Submission directly or indirectly from Runtime, a perpetual, worldwide, non-exclusive, royalty-free, transferrable, irrevocable license in the Submission to reproduce, modify and prepare derivative works of, publicly display, publicly perform, and distribute the Submission and such derivative works, and to sublicense any or all of the foregoing rights to third parties under such terms as Runtime determines.
+
+ 5.2. *Patent License.*
+ You grant Runtime, and those who receive the Submission directly or indirectly from Runtime, a perpetual, worldwide, non-exclusive, royalty-free, transferrable, irrevocable license under Your patent claims that are necessarily infringed by the Submission, or the combination of the Submission with other materials of Runtime with which it may be combined, to make, have made, use, offer to sell, sell and import or otherwise dispose of the Submission alone or with other materials and under such terms as Runtime determines.
+
+ 5.3. *Moral Rights.*
+ If moral rights apply to the Submission, to the maximum extent permitted by law You waive and agree not to assert such moral rights against Runtime or our successors in interest, or any of our licensees or sublicensees, either direct or indirect.
+
+ 5.4. *Other Rights Reserved.*
+ Each party reserves all rights not expressly granted in this Agreement.
+ Subject to the rights granted herein, You retain ownership of the copyright in Your Submission and have the same rights to use or license the Submission which You would have had without entering into the Agreement.
+ No additional licenses or rights whatsoever (including, without limitation, any implied licenses) are granted hereby, by implication or otherwise.
+
+6. *Representations and Warranties.*
+ You represent and warrant that: (a) You own all rights necessary to, and are legally entitled to, grant the above licenses; (b) Each of Your Submissions is entirely Your original work (except as You may have disclosed under Section 3); (c) You have the authority to make the Submission, and have secured permission from Your employer to make the Submission in cases where Your Submission is made in the course of Your work for Your employer or Your employer has intellectual property rights in Your Submission by contract or applicable law; (d) Your grant of rights under this Agreement does not violate any grant of rights which You have made to third parties, including Your employer; and (e) If Your employer has any rights with respect to any Submission, You have the necessary authority to bind Your employer to the obligations contained in this Agreement.
+
+7. *Disclaimer.*
+ You are not expected to provide support for Your Submission, unless You choose to do so.
+ UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, AND EXCEPT FOR THE WARRANTIES EXPRESSLY STATED IN SECTIONS 3, AND 6, YOUR SUBMISSION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY OF NONINFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+
+8. *Notice to Runtime.*
+ You agree to notify Runtime in writing of any facts or circumstances of which You later become aware that would make Your representations and warranties in this Agreement inaccurate in any respect.
+
+9. *Information about Submissions.*
+ You agree that Submissions to Runtime and information about Submissions may be maintained indefinitely and disclosed publicly, including Your name and other information that You submit with Your Submission.
+
+10. *Governing Law/Jurisdiction.*
+ This Agreement is governed by the laws of the State of Illinois, and the parties consent to exclusive jurisdiction and venue in the state and federal courts sitting in Champaign County, Illinois.
+ The parties waive all defenses of lack of personal jurisdiction and forum non-conveniens.
+
+11. *Entire Agreement/Assignment.*
+ This Agreement is the entire agreement between the parties, and supersedes any and all prior agreements, understandings or communications, written or oral, between the parties relating to the subject matter hereof.
+ This Agreement may be assigned by Runtime.
+
+By signing, You accept and agree to the terms of this Contributor License Agreement for Your present and all future Submissions to Runtime.
diff --git a/docs/runtimeverification-wasm-semantics/Dockerfile b/docs/runtimeverification-wasm-semantics/Dockerfile
new file mode 100644
index 000000000..e8b961bfb
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/Dockerfile
@@ -0,0 +1,43 @@
+ARG K_COMMIT
+FROM runtimeverificationinc/kframework-k:ubuntu-jammy-${K_COMMIT}
+
+RUN apt-get update \
+ && apt-get upgrade --yes \
+ && apt-get install --yes \
+ cmake \
+ curl \
+ pandoc \
+ python3 \
+ python3-pip
+
+RUN git clone 'https://github.com/z3prover/z3' --branch=z3-4.8.15 \
+ && cd z3 \
+ && python3 scripts/mk_make.py \
+ && cd build \
+ && make -j8 \
+ && make install \
+ && cd ../.. \
+ && rm -rf z3
+
+RUN curl -sSL https://install.python-poetry.org | POETRY_HOME=/usr python3 - \
+ && poetry --version
+
+ARG USER_ID=1000
+ARG GROUP_ID=1000
+RUN groupadd -g $GROUP_ID user && useradd -m -u $USER_ID -s /bin/sh -g user user
+
+USER user:user
+WORKDIR /home/user
+
+RUN pip3 install \
+ cytoolz \
+ numpy
+
+RUN git clone 'https://github.com/WebAssembly/wabt' --branch 1.0.13 --recurse-submodules wabt \
+ && cd wabt \
+ && mkdir build \
+ && cd build \
+ && cmake .. \
+ && cmake --build .
+
+ENV PATH=/home/user/wabt/build:/home/user/.local/bin:$PATH
diff --git a/docs/runtimeverification-wasm-semantics/LICENSE b/docs/runtimeverification-wasm-semantics/LICENSE
new file mode 100644
index 000000000..0016cccd7
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/LICENSE
@@ -0,0 +1,59 @@
+==============================================================================
+The WebAssembly Semantics in K Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2019 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+ K Team (http://kframework.org)
+ with members from:
+
+ * University of Illinois at Urbana-Champaign (http://fsl.cs.illinois.edu/)
+ * Runtime Verification, Inc (https://www.runtimeverification.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the K Team, Runtime Verification, the University of
+ Illinois at Urbana-Champaign, nor the names of its contributors may be
+ used to endorse or promote products derived from this Software without
+ specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with the WebAssembly
+Semantics in K:
+==============================================================================
+The WebAssembly Semantics in K software contains code written by third parties.
+Licenses for this software can be found in the licenses directory
+in the file as specified below. These files will describe the copyrights,
+license, and restrictions which apply to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the WebAssembly Semantics in K Distribution, and nothing
+in any of the other licenses gives permission to use the names of the K Team,
+Runtime Verification, or the University of Illinois
+to endorse or promote products derived from this Software.
diff --git a/docs/runtimeverification-wasm-semantics/Makefile b/docs/runtimeverification-wasm-semantics/Makefile
new file mode 100644
index 000000000..18f44a4bd
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/Makefile
@@ -0,0 +1,246 @@
+# Settings
+# --------
+
+BUILD_DIR := .build
+DEPS_DIR := deps
+DEFN_DIR := $(BUILD_DIR)/defn
+
+K_SUBMODULE := $(DEPS_DIR)/k
+ifneq (,$(wildcard deps/k/k-distribution/target/release/k/bin/*))
+ K_RELEASE ?= $(abspath $(K_SUBMODULE)/k-distribution/target/release/k)
+else
+ K_RELEASE ?= $(dir $(shell which kompile))..
+endif
+K_BIN := $(K_RELEASE)/bin
+K_LIB := $(K_RELEASE)/lib/kframework
+export K_RELEASE
+
+ifneq ($(RELEASE),)
+ K_BUILD_TYPE := Release
+else
+ K_BUILD_TYPE := Debug
+endif
+
+PATH := $(K_BIN):$(PATH)
+export PATH
+
+PYK_PATH := $(abspath $(K_SUBMODULE)/pyk/src/)
+PYWASM_PATH := ./deps/py-wasm
+
+PYTHONPATH := $(PYK_PATH)
+export PYTHONPATH
+
+.PHONY: all clean deps \
+ build build-llvm build-haskell \
+ test test-execution test-simple test-prove test-binary-parser \
+ test-conformance test-conformance-parse test-conformance-supported \
+ media presentations reports
+
+all: build
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+# Build Dependencies (K Submodule)
+# --------------------------------
+
+K_JAR := $(K_SUBMODULE)/k-distribution/target/release/k/lib/java/kernel-1.0-SNAPSHOT.jar
+
+deps: $(K_JAR) $(TANGLER)
+
+$(K_JAR):
+ cd $(K_SUBMODULE) && mvn package -DskipTests -Dproject.build.type=$(K_BUILD_TYPE)
+
+# Building Definition
+# -------------------
+
+KOMPILE_OPTS :=
+LLVM_KOMPILE_OPTS :=
+HASKELL_KOMPILE_OPTS :=
+
+tangle_selector := k
+
+SOURCE_FILES := data \
+ kwasm-lemmas \
+ numeric \
+ test \
+ wasm \
+ wasm-text \
+ wrc20
+EXTRA_SOURCE_FILES :=
+ALL_SOURCE_FILES := $(patsubst %, %.md, $(SOURCE_FILES)) $(EXTRA_SOURCE_FILES)
+
+build: build-llvm build-haskell
+
+ifneq (,$(RELEASE))
+ KOMPILE_OPTS += -O2
+else
+ KOMPILE_OPTS += --debug
+endif
+
+ifeq (,$(RELEASE))
+ LLVM_KOMPILE_OPTS += -g
+endif
+
+KOMPILE_LLVM := kompile --backend llvm --md-selector "$(tangle_selector)" \
+ $(KOMPILE_OPTS) \
+ $(addprefix -ccopt ,$(LLVM_KOMPILE_OPTS))
+
+KOMPILE_HASKELL := kompile --backend haskell --md-selector "$(tangle_selector)" \
+ $(KOMPILE_OPTS) \
+ $(HASKELL_KOMPILE_OPTS)
+
+### LLVM
+
+llvm_dir := $(DEFN_DIR)/llvm
+llvm_files := $(ALL_SOURCE_FILES)
+llvm_main_module := WASM-TEST
+llvm_syntax_module := $(llvm_main_module)-SYNTAX
+llvm_main_file := test
+llvm_kompiled := $(llvm_dir)/$(llvm_main_file)-kompiled/interpreter
+
+build-llvm: $(llvm_kompiled)
+
+$(llvm_kompiled): $(llvm_files)
+ $(KOMPILE_LLVM) $(llvm_main_file).md \
+ --directory $(llvm_dir) -I $(CURDIR) \
+ --main-module $(llvm_main_module) \
+ --syntax-module $(llvm_syntax_module)
+
+### Haskell
+
+haskell_dir := $(DEFN_DIR)/haskell
+haskell_files := $(ALL_SOURCE_FILES)
+haskell_main_module := WASM-TEXT
+haskell_syntax_module := $(haskell_main_module)-SYNTAX
+haskell_main_file := test
+haskell_kompiled := $(haskell_dir)/$(haskell_main_file)-kompiled/definition.kore
+
+build-haskell: $(haskell_kompiled)
+
+$(haskell_kompiled): $(haskell_files)
+ $(KOMPILE_HASKELL) $(haskell_main_file).md \
+ --directory $(haskell_dir) -I $(CURDIR) \
+ --main-module $(haskell_main_module) \
+ --syntax-module $(haskell_syntax_module)
+
+# Testing
+# -------
+
+TEST := ./kwasm
+CHECK := git --no-pager diff --no-index --ignore-all-space -R
+
+TEST_CONCRETE_BACKEND := llvm
+TEST_SYMBOLIC_BACKEND := haskell
+
+KPROVE_MODULE := KWASM-LEMMAS
+KPROVE_OPTS :=
+
+tests/proofs/functions-spec.k.prove: KPROVE_MODULE = FUNCTIONS-LEMMAS
+tests/proofs/functions-spec.k.prove: KPROVE_OPTS += --concrete-rules WASM-DATA.wrap-Positive,WASM-DATA.setRange-Positive,WASM-DATA.getRange-Positive
+tests/proofs/memory-spec.k.prove: KPROVE_OPTS += --concrete-rules WASM-DATA.wrap-Positive,WASM-DATA.setRange-Positive,WASM-DATA.getRange-Positive
+tests/proofs/wrc20-spec.k.prove: KPROVE_MODULE = WRC20-LEMMAS
+tests/proofs/wrc20-spec.k.prove: KPROVE_OPTS += --concrete-rules WASM-DATA.wrap-Positive,WASM-DATA.setRange-Positive,WASM-DATA.getRange-Positive,WASM-DATA.get-Existing,WASM-DATA.set-Extend
+
+test: test-execution test-prove test-binary-parser
+
+# Generic Test Harnesses
+
+tests/%.run: tests/% $(llvm_kompiled)
+ $(TEST) run --backend $(TEST_CONCRETE_BACKEND) $< > tests/$*.$(TEST_CONCRETE_BACKEND)-out
+ $(CHECK) tests/$*.$(TEST_CONCRETE_BACKEND)-out tests/success-$(TEST_CONCRETE_BACKEND).out
+ rm -rf tests/$*.$(TEST_CONCRETE_BACKEND)-out
+
+tests/%.run-term: tests/% $(llvm_kompiled)
+ $(TEST) run --backend $(TEST_CONCRETE_BACKEND) $< > tests/$*.$(TEST_CONCRETE_BACKEND)-out
+ grep --after-context=2 "" tests/$*.$(TEST_CONCRETE_BACKEND)-out > tests/$*.$(TEST_CONCRETE_BACKEND)-out-term
+ $(CHECK) tests/$*.$(TEST_CONCRETE_BACKEND)-out-term tests/success-k.out
+ rm -rf tests/$*.$(TEST_CONCRETE_BACKEND)-out
+ rm -rf tests/$*.$(TEST_CONCRETE_BACKEND)-out-term
+
+tests/%.parse: tests/% $(llvm_kompiled)
+ $(TEST) kast --backend $(TEST_CONCRETE_BACKEND) $< kast > $@-out
+ rm -rf $@-out
+
+tests/%.prove: tests/% $(haskell_kompiled)
+ $(TEST) prove --backend $(TEST_SYMBOLIC_BACKEND) $< $(KPROVE_MODULE) --format-failures \
+ $(KPROVE_OPTS)
+
+### Execution Tests
+
+test-execution: test-simple
+
+simple_tests := $(wildcard tests/simple/*.wast)
+simple_tests_failing := $(shell cat tests/failing.simple)
+simple_tests_passing := $(filter-out $(simple_tests_failing), $(simple_tests))
+
+test-simple: $(simple_tests_passing:=.run)
+
+### Conformance Tests
+
+conformance_tests:=$(wildcard tests/wasm-tests/test/core/*.wast)
+unsupported_conformance_tests:=$(patsubst %, tests/wasm-tests/test/core/%, $(shell cat tests/conformance/unsupported-$(TEST_CONCRETE_BACKEND).txt))
+unparseable_conformance_tests:=$(patsubst %, tests/wasm-tests/test/core/%, $(shell cat tests/conformance/unparseable.txt))
+parseable_conformance_tests:=$(filter-out $(unparseable_conformance_tests), $(conformance_tests))
+supported_conformance_tests:=$(filter-out $(unsupported_conformance_tests), $(parseable_conformance_tests))
+
+test-conformance-parse: $(parseable_conformance_tests:=.parse)
+test-conformance-supported: $(supported_conformance_tests:=.run-term)
+
+test-conformance: test-conformance-parse test-conformance-supported
+
+### Proof Tests
+
+proof_tests:=$(wildcard tests/proofs/*-spec.k)
+
+test-prove: $(proof_tests:=.prove)
+
+### Binary Parser Test
+
+# TODO pyk is not globally installed. use the poetry-installed pyk
+# until binary-parser is migrated to pykwasm
+BINARY:=poetry -C pykwasm run python3 binary-parser/test.py
+
+tests/binary/%.wasm: tests/binary/%.wat
+ wat2wasm $< --output=$@
+
+.PHONY: pykwasm-poetry-install
+pykwasm-poetry-install:
+ $(MAKE) -C pykwasm poetry-install
+
+tests/%.wasm.bparse: tests/%.wasm pykwasm-poetry-install
+ $(BINARY) $<
+
+binary_parser_tests:=$(wildcard tests/binary/*.wat)
+
+test-binary-parser: $(binary_parser_tests:.wat=.wasm.bparse) test-kwasm-ast
+
+test-kwasm-ast: pykwasm-poetry-install
+ poetry -C pykwasm run pytest binary-parser/test_kwasm_ast.py
+
+# Analysis
+# --------
+json_build := $(haskell_dir)/$(haskell_main_file)-kompiled/parsed.json
+
+$(json_build):
+ $(MAKE) build-haskell -B KOMPILE_OPTS="--emit-json"
+
+graph-imports: $(json_build)
+ kpyk $(haskell_dir)/$(haskell_main_file)-kompiled graph-imports
+
+# Presentation
+# ------------
+
+media: presentations reports
+
+media/%.pdf: TO_FORMAT=beamer
+presentations: $(patsubst %.md, %.pdf, $(wildcard media/*-presentation-*.md))
+
+media/201903-report-chalmers.pdf: TO_FORMAT=latex
+reports: media/201903-report-chalmers.pdf
+
+media/%.pdf: media/%.md media/citations.md
+ cat $^ | pandoc --from markdown-latex_macros --to $(TO_FORMAT) --filter pandoc-citeproc --output $@
+
+media-clean:
+ rm media/*.pdf
diff --git a/docs/runtimeverification-wasm-semantics/README.md b/docs/runtimeverification-wasm-semantics/README.md
new file mode 100644
index 000000000..ae90d28d1
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/README.md
@@ -0,0 +1,163 @@
+KWasm: Semantics of WebAssembly in K
+====================================
+
+### Want to Support KWasm Development?
+[Contribute to our Gitcoin Grant.](https://gitcoin.co/grants/592/kewasm-and-kwasm)
+
+---
+
+This repository presents a prototype formal semantics of [WebAssembly].
+It is currently under construction.
+For examples of current capabilities, see the unit tests under the `tests/simple` directory.
+
+Repository Structure
+--------------------
+
+### Semantics Layout
+
+The following files constitute the KWasm semantics:
+
+- [data.md](data.md) provides the (functional) data of WebAssembly (basic types, type constructors, and values).
+- [numeric.md](numeric.md) provides the functional rules for numeric operators.
+- [wasm.md](wasm.md) is the main KWasm semantics, containing the configuration and transition rules of WebAssembly.
+
+These additional files extend the semantics to make the repository more useful:
+
+- [test.md](test.md) is an execution harness for KWasm, providing a simple language for describing tests/programs.
+
+### Example usage: `./kwasm` runner script
+
+After building the definition, you can run the definition using `./kwasm`.
+The most up-to-date documentation will always be in `./kwasm help`.
+
+Run the file `tests/simple/arithmetic.wast`:
+
+```sh
+./kwasm run tests/simple/arithmetic.wast
+```
+
+To run proofs, you can similarly use `./kwasm`, but must specify the module to use for proving.
+For example, to prove the specification `tests/proofs/simple-arithmetic-spec.k`:
+
+```sh
+./kwasm prove tests/proofs/simple-arithmetic-spec.k KWASM-LEMMAS
+```
+
+You can optionally override the default backend using the `--backend BACKEND` flag:
+
+```sh
+./kwasm run --backend llvm tests/simple/arithmetic.wast
+./kwasm prove --backend haskell tests/proofs/simple-arithmetic-spec.k KWASM-LEMMAS
+```
+
+Installing/Building
+-------------------
+
+### K Backends
+
+There are two backends of K available, the LLVM backend for concrete execution, and the Haskell backend for symbolic reasoning and proofs.
+This repository generates the build-products for the backends in `.build/defn/llvm` and `.build/defn/haskell`.
+
+### Dependencies
+
+The following are needed for building/running KWasm:
+
+- [git](https://git-scm.com/)
+- [Pandoc >= 1.17](https://pandoc.org) is used to generate the `*.k` files from the `*.md` files.
+- GNU [Bison](https://www.gnu.org/software/bison/), [Flex](https://github.com/westes/flex), and [Autoconf](http://www.gnu.org/software/autoconf/).
+- GNU [libmpfr](http://www.mpfr.org/) and [libtool](https://www.gnu.org/software/libtool/).
+- Java 8 JDK (eg. [OpenJDK](http://openjdk.java.net/))
+- [Haskell Stack](https://docs.haskellstack.org/en/stable/install_and_upgrade/#installupgrade).
+ Note that the version of the `stack` tool provided by your package manager might not be recent enough.
+ Please follow installation instructions from the Haskell Stack website linked above.
+- [LLVM](https://llvm.org/) For building the LLVM backend.
+- [Z3](https://github.com/Z3Prover/z3) version 4.8.15
+
+On Ubuntu >= 15.04 (for example):
+
+```sh
+sudo apt-get install --yes \
+ autoconf bison clang++-8 clang-8 cmake curl flex gcc libboost-test-dev libffi-dev \
+ libgmp-dev libjemalloc-dev libmpfr-dev libprocps-dev libprotobuf-dev libtool \
+ libyaml-dev lld-8 llvm llvm-8 llvm-8-tools maven openjdk-8-jdk pandoc pkg-config \
+ protobuf-compiler python3 python-pygments python-recommonmark python-sphinx time \
+ zlib1g-dev
+```
+
+To upgrade `stack` (if needed):
+
+```sh
+stack upgrade
+export PATH=$HOME/.local/bin:$PATH
+```
+
+After installing the above dependencies, make sure the submodules are setup:
+
+```sh
+git submodule update --init --recursive
+```
+
+Install repository specific dependencies:
+
+```sh
+make deps
+```
+
+#### Installing Z3
+
+Note that KWASM requires Z3 version 4.8.15, which you may need to install from a
+source build if your package manager supplies a different version. To do so,
+follow the instructions
+[here](https://github.com/Z3Prover/z3#building-z3-using-make-and-gccclang) after
+checking out the correct tag in the Z3 repository:
+
+```sh
+git clone https://github.com/Z3Prover/z3.git
+cd z3
+git checkout z3-4.8.15
+python scripts/mk_make.py
+cd build
+make
+sudo make install
+```
+
+### Building
+
+And then build the semantics:
+
+```sh
+make build
+```
+
+To only build a specific backend, you can do `make build-llvm` or `make build-haskell`.
+
+### Media and documents
+
+The `media/` directory contains presentations and reports about about KWasm.
+The documents are named with an approximate date of presentation/submission, what type of document it is, and a brief contextual name, e.g., name of conference where it was held.
+
+[GhostScript](https://www.ghostscript.com/) is a dependency for building documents of type `report`.
+
+```sh
+sudo apt install ghostscript
+```
+
+To build all documents in the media file:
+
+```sh
+make media
+```
+
+Testing
+-------
+
+The target `test` contains all the currently passing tests.
+
+```sh
+make test
+```
+
+Resources
+---------
+
+[WebAssembly]:
diff --git a/docs/runtimeverification-wasm-semantics/auxil.md b/docs/runtimeverification-wasm-semantics/auxil.md
new file mode 100644
index 000000000..873a9afcb
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/auxil.md
@@ -0,0 +1,37 @@
+Auxiliary Wasm Commands
+=======================
+
+Generally useful commands that are not part of the actual Wasm semantics.
+
+```k
+require "wasm.md"
+
+module WASM-AUXIL
+ imports WASM
+
+ syntax Stmt ::= Auxil
+ // ---------------------
+
+ syntax Auxil ::= "#clearConfig"
+ // -------------------------------
+ rule #clearConfig => . ...
+ _ => .Int
+ _ => .ValStack
+ _ => .Map
+ _ => .Bag
+ _ => .Map
+ _ => 0
+ _ => .Map
+
+ _ => 0
+ _ => .Bag
+ _ => 0
+ _ => .Bag
+ _ => 0
+ _ => .Bag
+ _ => 0
+ _ => .Bag
+
+
+endmodule
+```
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/.gitignore b/docs/runtimeverification-wasm-semantics/binary-parser/.gitignore
new file mode 100644
index 000000000..c18dd8d83
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/binary-parser/.gitignore
@@ -0,0 +1 @@
+__pycache__/
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/README.md b/docs/runtimeverification-wasm-semantics/binary-parser/README.md
new file mode 100644
index 000000000..a3710f4b0
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/binary-parser/README.md
@@ -0,0 +1,26 @@
+Binary Parser for Wasm Modules
+==============================
+
+This python module converts a binary Wasm module into the Kast format accepted by KWasm.
+
+
+Usage:
+------
+
+The entry point is the `wasm2kast` module.
+Ensure you have `pyk` installed and available in your Python path.
+
+Import `wasm2kast` in your Python-script.
+Pass the module as bytes to the `wasm2kast` function.
+It will return the Kast representation in Wasm for that module.
+
+Example:
+
+```py
+import wasm2kast
+
+filename = 'hello.wasm'
+with open(filename, 'rb') as f:
+ kast = wasm2kast.wasm2kast(f)
+ print(kast)
+```
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/__init__.py b/docs/runtimeverification-wasm-semantics/binary-parser/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/kwasm_ast.py b/docs/runtimeverification-wasm-semantics/binary-parser/kwasm_ast.py
new file mode 100644
index 000000000..77653625c
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/binary-parser/kwasm_ast.py
@@ -0,0 +1,546 @@
+#!/usr/bin/env python3
+
+"""
+NOTE: The KLabels in this file must be kept up to date with the ones in the K semantics definition.
+There is unfortunately no way to do this automatically.
+
+This library provides a convenient interface to create KWasm programs in Kast format.
+It is a mirror of the abstract syntax in the K semantics.
+"""
+
+from pyk.kast.inner import KSequence, KApply, KToken
+from pyk.prelude.bytes import bytesToken
+from pyk.utils import dequote_str
+
+###########
+# KLabels #
+###########
+
+MODULE = 'aModuleDecl'
+MODULE_METADATA = 'moduleMeta'
+TYPE = 'aTypeDefn'
+FUNC_TYPE = 'aFuncType'
+VEC_TYPE = 'aVecType'
+VAL_TYPES = 'listValTypes'
+VAL_TYPES_NIL = '.List{\"listValTypes\"}_ValTypes'
+I32 = 'i32'
+I64 = 'i32'
+INTS = 'listInt'
+INTS_NIL = '.List{\"listInt\"}_Ints'
+
+FUNC = 'aFuncDefn'
+FUNC_METADATA = 'funcMeta'
+
+TABLE = 'aTableDefn'
+
+MEMORY = 'aMemoryDefn'
+
+GLOBAL = 'aGlobalDefn'
+GLOBAL_TYPE = 'aGlobalType'
+
+ELEM = 'aElemDefn'
+
+DATA = 'aDataDefn'
+
+START = 'aStartDefn'
+
+IMPORT = 'aImportDefn'
+FUNC_DESC = 'aFuncDesc'
+GLOBAL_DESC = 'aGlobalDesc'
+TABLE_DESC = 'aTableDesc'
+MEMORY_DESC = 'aMemoryDesc'
+
+EXPORT = 'aExportDefn'
+
+DEFNS = '___WASM-COMMON-SYNTAX_Defns_Defn_Defns'
+INSTRS = '___WASM-COMMON-SYNTAX_Instrs_Instr_Instrs'
+
+###################
+# Basic Datatypes #
+###################
+
+def KInt(value : int):
+ return KToken(str(value), 'Int')
+
+def KFloat(value : float):
+ return KToken(str(value), 'Float')
+
+def KString(value : str):
+ return KToken('"%s"' % value, 'String')
+
+def KBytes(bs : bytes):
+ # Change from python bytes repr to bytes repr in K.
+ return bytesToken(dequote_str(str(bs))[2:-1])
+
+###########
+# Strings #
+###########
+
+def wasm_string(s : str):
+ return KToken('\"%s\"' % s, 'WasmStringToken')
+
+#########
+# Lists #
+#########
+
+def KNamedList(klabel, empty_klabel, items):
+ tail = KApply(empty_klabel, [])
+ while not items == []:
+ last = items.pop()
+ tail = KApply(klabel, [last, tail])
+ return tail
+
+def defns(items):
+ return KNamedList(DEFNS, EMPTY_STMTS, items)
+
+def instrs(items):
+ return KNamedList(INSTRS, EMPTY_STMTS, items)
+
+def val_types(items):
+ return KNamedList(VAL_TYPES, VAL_TYPES_NIL, items)
+
+def ints(iis : [int]):
+ kis = [KInt(x) for x in iis]
+ return KNamedList(INTS, INTS_NIL, kis)
+
+###########
+# Empties #
+###########
+
+EMPTY_ID = KApply('.Identifier', [])
+EMPTY_STMTS = '.List{\"listStmt\"}_EmptyStmts'
+EMPTY_MAP = KApply('.Map', [])
+EMPTY_OPT_STRING = KApply('.String', [])
+EMPTY_DEFNS = KApply(EMPTY_STMTS, [])
+EMPTY_FUNC_METADATA = KApply(FUNC_METADATA, [EMPTY_ID, EMPTY_MAP])
+
+#########
+# Types #
+#########
+
+i32 = KApply('i32', [])
+i64 = KApply('i64', [])
+f32 = KApply('f32', [])
+f64 = KApply('f64', [])
+
+MUT_CONST = KApply('mutConst', [])
+MUT_VAR = KApply('mutVar', [])
+
+def vec_type(valtypes):
+ return KApply(VEC_TYPE, [valtypes])
+
+def func_type(params, results):
+ return KApply(FUNC_TYPE, [params, results])
+
+def limits(tup):
+ i = tup[0]
+ j = tup[1]
+ if j is None:
+ return KApply('limitsMin', [KInt(i)])
+ return KApply('limitsMinMax', [KInt(i), KInt(j)])
+
+def global_type(mut, valtype):
+ return KApply(GLOBAL_TYPE, [mut, valtype])
+
+##########
+# Instrs #
+##########
+
+ ########################
+ # Control Instructions #
+ ########################
+
+NOP = KApply('aNop', [])
+UNREACHABLE = KApply('aUnreachable', [])
+
+def BLOCK(vec_type, instrs, block_info):
+ return KApply('aBlock', [vec_type, instrs, block_info])
+
+def IF(vec_type, then_instrs, else_instrs, block_info):
+ return KApply('aIf', [vec_type, then_instrs, else_instrs, block_info])
+
+def LOOP(vec_type, instrs, block_info):
+ return KApply('aLoop', [vec_type, instrs, block_info])
+
+RETURN = KApply('aReturn', [])
+
+def BR(idx : int):
+ return KApply('aBr', [KInt(idx)])
+
+def BR_IF(idx : int):
+ return KApply('aBr_if', [KInt(idx)])
+
+def BR_TABLE(idxs : [int], default):
+ return KApply('aBr_table', [ints(idxs + (default,))])
+
+def CALL(function_idx : int):
+ return KApply('aCall', [KInt(function_idx)])
+
+def CALL_INDIRECT(type_idx : int):
+ return KApply('aCall_indirect', [KInt(type_idx)])
+
+ ##########################
+ # Parametric Instruction #
+ ##########################
+
+DROP = KApply('aDrop', [])
+SELECT = KApply('aSelect', [])
+
+ ##############
+ # Float UnOp #
+ ##############
+
+F32_ABS = KApply('aFUnOp', [f32, KApply('aAbs', [])])
+F32_CEIL = KApply('aFUnOp', [f32, KApply('aCeil', [])])
+F32_FLOOR = KApply('aFUnOp', [f32, KApply('aFloor', [])])
+F32_NEAREST = KApply('aFUnOp', [f32, KApply('aNearest', [])])
+F32_NEG = KApply('aFUnOp', [f32, KApply('aNeg', [])])
+F32_SQRT = KApply('aFUnOp', [f32, KApply('aSqrt', [])])
+F32_TRUNC = KApply('aFUnOp', [f32, KApply('aTrunc', [])])
+F64_ABS = KApply('aFUnOp', [f64, KApply('aAbs', [])])
+F64_CEIL = KApply('aFUnOp', [f64, KApply('aCeil', [])])
+F64_FLOOR = KApply('aFUnOp', [f64, KApply('aFloor', [])])
+F64_NEAREST = KApply('aFUnOp', [f64, KApply('aNearest', [])])
+F64_NEG = KApply('aFUnOp', [f64, KApply('aNeg', [])])
+F64_SQRT = KApply('aFUnOp', [f64, KApply('aSqrt', [])])
+F64_TRUNC = KApply('aFUnOp', [f64, KApply('aTrunc', [])])
+
+ ############
+ # Int UnOp #
+ ############
+
+I32_CLZ = KApply('aIUnOp', [i32, KApply('aClz', [])])
+I32_CTZ = KApply('aIUnOp', [i32, KApply('aCtz', [])])
+I32_POPCNT = KApply('aIUnOp', [i32, KApply('aPopcnt', [])])
+I64_CLZ = KApply('aIUnOp', [i64, KApply('aClz', [])])
+I64_CTZ = KApply('aIUnOp', [i64, KApply('aCtz', [])])
+I64_POPCNT = KApply('aIUnOp', [i64, KApply('aPopcnt', [])])
+
+ ###############
+ # Float BinOp #
+ ###############
+
+F32_ADD = KApply('aFBinOp', [f32, KApply('floatAdd', [])])
+F32_SUB = KApply('aFBinOp', [f32, KApply('floatSub', [])])
+F32_MUL = KApply('aFBinOp', [f32, KApply('floatMul', [])])
+F32_DIV = KApply('aFBinOp', [f32, KApply('floatDiv', [])])
+F32_MIN = KApply('aFBinOp', [f32, KApply('floatMin', [])])
+F32_MAX = KApply('aFBinOp', [f32, KApply('floatMax', [])])
+F32_COPYSIGN = KApply('aFBinOp', [f32, KApply('floatCopysign', [])])
+F64_ADD = KApply('aFBinOp', [f64, KApply('floatAdd', [])])
+F64_SUB = KApply('aFBinOp', [f64, KApply('floatSub', [])])
+F64_MUL = KApply('aFBinOp', [f64, KApply('floatMul', [])])
+F64_DIV = KApply('aFBinOp', [f64, KApply('floatDiv', [])])
+F64_MIN = KApply('aFBinOp', [f64, KApply('floatMin', [])])
+F64_MAX = KApply('aFBinOp', [f64, KApply('floatMax', [])])
+F64_COPYSIGN = KApply('aFBinOp', [f64, KApply('floatCopysign', [])])
+
+ #############
+ # Int BinOp #
+ #############
+
+I32_ADD = KApply('aIBinOp', [i32, KApply('intAdd', [])])
+I32_AND = KApply('aIBinOp', [i32, KApply('intAnd', [])])
+I32_DIV_S = KApply('aIBinOp', [i32, KApply('intDiv_s', [])])
+I32_DIV_U = KApply('aIBinOp', [i32, KApply('intDiv_u', [])])
+I32_MUL = KApply('aIBinOp', [i32, KApply('intMul', [])])
+I32_OR = KApply('aIBinOp', [i32, KApply('intOr', [])])
+I32_REM_S = KApply('aIBinOp', [i32, KApply('intRem_s', [])])
+I32_REM_U = KApply('aIBinOp', [i32, KApply('intRem_u', [])])
+I32_ROTL = KApply('aIBinOp', [i32, KApply('intRotl', [])])
+I32_ROTR = KApply('aIBinOp', [i32, KApply('intRotr', [])])
+I32_SHL = KApply('aIBinOp', [i32, KApply('intShl', [])])
+I32_SHR_S = KApply('aIBinOp', [i32, KApply('intShr_s', [])])
+I32_SHR_U = KApply('aIBinOp', [i32, KApply('intShr_u', [])])
+I32_SUB = KApply('aIBinOp', [i32, KApply('intSub', [])])
+I32_XOR = KApply('aIBinOp', [i32, KApply('intXor', [])])
+I64_ADD = KApply('aIBinOp', [i64, KApply('intAdd', [])])
+I64_AND = KApply('aIBinOp', [i64, KApply('intAnd', [])])
+I64_DIV_S = KApply('aIBinOp', [i64, KApply('intDiv_s', [])])
+I64_DIV_U = KApply('aIBinOp', [i64, KApply('intDiv_u', [])])
+I64_MUL = KApply('aIBinOp', [i64, KApply('intMul', [])])
+I64_OR = KApply('aIBinOp', [i64, KApply('intOr', [])])
+I64_REM_S = KApply('aIBinOp', [i64, KApply('intRem_s', [])])
+I64_REM_U = KApply('aIBinOp', [i64, KApply('intRem_u', [])])
+I64_ROTL = KApply('aIBinOp', [i64, KApply('intRotl', [])])
+I64_ROTR = KApply('aIBinOp', [i64, KApply('intRotr', [])])
+I64_SHL = KApply('aIBinOp', [i64, KApply('intShl', [])])
+I64_SHR_S = KApply('aIBinOp', [i64, KApply('intShr_s', [])])
+I64_SHR_U = KApply('aIBinOp', [i64, KApply('intShr_u', [])])
+I64_SUB = KApply('aIBinOp', [i64, KApply('intSub', [])])
+I64_XOR = KApply('aIBinOp', [i64, KApply('intXor', [])])
+
+ ##########
+ # TestOp #
+ ##########
+
+I32_EQZ = KApply('aTestOp', [i32, KApply('aEqz', [])])
+I64_EQZ = KApply('aTestOp', [i64, KApply('aEqz', [])])
+
+ #############
+ # Int RelOp #
+ #############
+
+I32_EQ = KApply('aIRelOp', [i32, KApply('intEq', [])])
+I32_NE = KApply('aIRelOp', [i32, KApply('intNe', [])])
+I32_LT_U = KApply('aIRelOp', [i32, KApply('intLt_u', [])])
+I32_GT_U = KApply('aIRelOp', [i32, KApply('intGt_u', [])])
+I32_LT_S = KApply('aIRelOp', [i32, KApply('intLt_s', [])])
+I32_GT_S = KApply('aIRelOp', [i32, KApply('intGt_s', [])])
+I32_LE_U = KApply('aIRelOp', [i32, KApply('intLe_u', [])])
+I32_GE_U = KApply('aIRelOp', [i32, KApply('intGe_u', [])])
+I32_LE_S = KApply('aIRelOp', [i32, KApply('intLe_s', [])])
+I32_GE_S = KApply('aIRelOp', [i32, KApply('intGe_s', [])])
+I64_EQ = KApply('aIRelOp', [i64, KApply('intEq', [])])
+I64_NE = KApply('aIRelOp', [i64, KApply('intNe', [])])
+I64_LT_U = KApply('aIRelOp', [i64, KApply('intLt_u', [])])
+I64_GT_U = KApply('aIRelOp', [i64, KApply('intGt_u', [])])
+I64_LT_S = KApply('aIRelOp', [i64, KApply('intLt_s', [])])
+I64_GT_S = KApply('aIRelOp', [i64, KApply('intGt_s', [])])
+I64_LE_U = KApply('aIRelOp', [i64, KApply('intLe_u', [])])
+I64_GE_U = KApply('aIRelOp', [i64, KApply('intGe_u', [])])
+I64_LE_S = KApply('aIRelOp', [i64, KApply('intLe_s', [])])
+I64_GE_S = KApply('aIRelOp', [i64, KApply('intGe_s', [])])
+
+ ###############
+ # Float RelOp #
+ ###############
+
+F32_LT = KApply('aFRelOp', [f32, KApply('floatLt', [])])
+F32_GT = KApply('aFRelOp', [f32, KApply('floatGt', [])])
+F32_LE = KApply('aFRelOp', [f32, KApply('floatLe', [])])
+F32_GE = KApply('aFRelOp', [f32, KApply('floatGe', [])])
+F32_EQ = KApply('aFRelOp', [f32, KApply('floatEq', [])])
+F32_NE = KApply('aFRelOp', [f32, KApply('floatNe', [])])
+F64_LT = KApply('aFRelOp', [f64, KApply('floatLt', [])])
+F64_GT = KApply('aFRelOp', [f64, KApply('floatGt', [])])
+F64_LE = KApply('aFRelOp', [f64, KApply('floatLe', [])])
+F64_GE = KApply('aFRelOp', [f64, KApply('floatGe', [])])
+F64_EQ = KApply('aFRelOp', [f64, KApply('floatEq', [])])
+F64_NE = KApply('aFRelOp', [f64, KApply('floatNe', [])])
+
+ ##############
+ # Convert Op #
+ ##############
+
+I64_EXTEND_U_I32 = KApply('aCvtOp', [i64, KApply('aExtend_i32_u', [])])
+I64_EXTEND_S_I32 = KApply('aCvtOp', [i64, KApply('aExtend_i32_s', [])])
+I32_WRAP_I64 = KApply('aCvtOp', [i32, KApply('aWrap_i64', [])])
+
+F64_PROMOTE_F32 = KApply('aCvtOp', [f64, KApply('aPromote_f32', [])])
+F32_DEMOTE_F64 = KApply('aCvtOp', [f32, KApply('aDemote_f64', [])])
+
+F32_CONVERT_U_I32 = KApply('aCvtOp', [f32, KApply('aConvert_i32_u', [])])
+F64_CONVERT_U_I32 = KApply('aCvtOp', [f64, KApply('aConvert_i32_u', [])])
+F32_CONVERT_U_I64 = KApply('aCvtOp', [f32, KApply('aConvert_i64_u', [])])
+F64_CONVERT_U_I64 = KApply('aCvtOp', [f64, KApply('aConvert_i64_u', [])])
+F32_CONVERT_S_I32 = KApply('aCvtOp', [f32, KApply('aConvert_i32_s', [])])
+F64_CONVERT_S_I32 = KApply('aCvtOp', [f64, KApply('aConvert_i32_s', [])])
+F32_CONVERT_S_I64 = KApply('aCvtOp', [f32, KApply('aConvert_i64_s', [])])
+F64_CONVERT_S_I64 = KApply('aCvtOp', [f64, KApply('aConvert_i64_s', [])])
+
+I32_TRUNC_U_F32 = KApply('aCvtOp', [i32, KApply('aTrunc_f32_u', [])])
+I32_TRUNC_U_F64 = KApply('aCvtOp', [i32, KApply('aTrunc_f64_u', [])])
+I64_TRUNC_U_F32 = KApply('aCvtOp', [i64, KApply('aTrunc_f32_u', [])])
+I64_TRUNC_U_F64 = KApply('aCvtOp', [i64, KApply('aTrunc_f64_u', [])])
+I32_TRUNC_S_F32 = KApply('aCvtOp', [i32, KApply('aTrunc_f32_s', [])])
+I32_TRUNC_S_F64 = KApply('aCvtOp', [i32, KApply('aTrunc_f64_s', [])])
+I64_TRUNC_S_F32 = KApply('aCvtOp', [i64, KApply('aTrunc_f32_s', [])])
+I64_TRUNC_S_F64 = KApply('aCvtOp', [i64, KApply('aTrunc_f64_s', [])])
+
+ #########
+ # Const #
+ #########
+
+def F32_CONST(f: float):
+ return KApply('aFConst', [f32, KFloat(f)])
+
+def F64_CONST(f: float):
+ return KApply('aFConst', [f64, KFloat(f)])
+
+def I32_CONST(i : int):
+ return (KApply('aIConst', [i32, KInt(i)]))
+
+def I64_CONST(i : int):
+ return (KApply('aIConst', [i64, KInt(i)]))
+
+ #######################
+ # Memory Instructions #
+ #######################
+
+def F32_STORE(offset : int):
+ return KApply('aStore', [f32, KApply('storeOpStore', []), KInt(offset)])
+
+def F64_STORE(offset : int):
+ return KApply('aStore', [f64, KApply('storeOpStore', []), KInt(offset)])
+
+def I32_STORE(offset : int):
+ return KApply('aStore', [i32, KApply('storeOpStore', []), KInt(offset)])
+
+def I64_STORE(offset : int):
+ return KApply('aStore', [i64, KApply('storeOpStore', []), KInt(offset)])
+
+def I32_STORE8(offset : int):
+ return KApply('aStore', [i32, KApply('storeOpStore8', []), KInt(offset)])
+
+def I64_STORE8(offset : int):
+ return KApply('aStore', [i64, KApply('storeOpStore8', []), KInt(offset)])
+
+def I32_STORE16(offset : int):
+ return KApply('aStore', [i32, KApply('storeOpStore16', []), KInt(offset)])
+
+def I64_STORE16(offset : int):
+ return KApply('aStore', [i64, KApply('storeOpStore16', []), KInt(offset)])
+
+def I64_STORE32(offset : int):
+ return KApply('aStore', [i64, KApply('storeOpStore32', []), KInt(offset)])
+
+def F32_LOAD(offset : int):
+ return KApply('aLoad', [f32, KApply('loadOpLoad', []), KInt(offset)])
+
+def F64_LOAD(offset : int):
+ return KApply('aLoad', [f64, KApply('loadOpLoad', []), KInt(offset)])
+
+def I32_LOAD(offset : int):
+ return KApply('aLoad', [i32, KApply('loadOpLoad', []), KInt(offset)])
+
+def I64_LOAD(offset : int):
+ return KApply('aLoad', [i64, KApply('loadOpLoad', []), KInt(offset)])
+
+def I32_LOAD16_S(offset : int):
+ return KApply('aLoad', [i32, KApply('loadOpLoad16_s', []), KInt(offset)])
+
+def I32_LOAD16_U(offset : int):
+ return KApply('aLoad', [i32, KApply('loadOpLoad16_u', []), KInt(offset)])
+
+def I64_LOAD16_S(offset : int):
+ return KApply('aLoad', [i64, KApply('loadOpLoad16_s', []), KInt(offset)])
+
+def I64_LOAD16_U(offset : int):
+ return KApply('aLoad', [i64, KApply('loadOpLoad16_u', []), KInt(offset)])
+
+def I32_LOAD8_S(offset : int):
+ return KApply('aLoad', [i32, KApply('loadOpLoad8_s', []), KInt(offset)])
+
+def I32_LOAD8_U(offset : int):
+ return KApply('aLoad', [i32, KApply('loadOpLoad8_u', []), KInt(offset)])
+
+def I64_LOAD8_S(offset : int):
+ return KApply('aLoad', [i64, KApply('loadOpLoad8_s', []), KInt(offset)])
+
+def I64_LOAD8_U(offset : int):
+ return KApply('aLoad', [i64, KApply('loadOpLoad8_u', []), KInt(offset)])
+
+def I64_LOAD32_U(offset : int):
+ return KApply('aLoad', [i64, KApply('loadOpLoad32_u', []), KInt(offset)])
+
+def I64_LOAD32_S(offset : int):
+ return KApply('aLoad', [i64, KApply('loadOpLoad32_s', []), KInt(offset)])
+
+MEMORY_GROW = KApply('aGrow', [])
+MEMORY_SIZE = KApply('aSize', [])
+
+ #######################
+ # Global Instructions #
+ #######################
+
+def GET_GLOBAL(idx : int):
+ return KApply('aGlobal.get', [KInt(idx)])
+
+def SET_GLOBAL(idx : int):
+ return KApply('aGlobal.set', [KInt(idx)])
+
+ ######################
+ # Local Instructions #
+ ######################
+
+def GET_LOCAL(idx : int):
+ return KApply('aLocal.get', [KInt(idx)])
+
+def SET_LOCAL(idx : int):
+ return KApply('aLocal.set', [KInt(idx)])
+
+def TEE_LOCAL(idx : int):
+ return KApply('aLocal.tee', [KInt(idx)])
+
+#######################
+# Import Descriptions #
+#######################
+
+def func_desc(type : int, id=EMPTY_ID):
+ return KApply(FUNC_DESC, [id, KInt(type)])
+
+def global_desc(global_type, id=EMPTY_ID):
+ return KApply(GLOBAL_DESC, [id, global_type])
+
+def table_desc(lim, id=EMPTY_ID):
+ return KApply(TABLE_DESC, [id, limits(lim)])
+
+def memory_desc(lim, id=EMPTY_ID):
+ return KApply(MEMORY_DESC, [id, limits(lim)])
+
+################
+# Declarations #
+################
+
+def type(func_type, metadata=EMPTY_ID):
+ return KApply(TYPE, [func_type, metadata])
+
+def func(type, locals, body, metadata=EMPTY_FUNC_METADATA):
+ return KApply(FUNC, [type, locals, body, metadata])
+
+def table(lim, metadata=EMPTY_ID):
+ return KApply(TABLE, [limits(lim), metadata])
+
+def memory(lim, metadata=EMPTY_ID):
+ return KApply(MEMORY, [limits(lim), metadata])
+
+def glob(type, init, metadata=EMPTY_ID):
+ return KApply(GLOBAL, [type, init, metadata])
+
+def elem(table_idx : int, offset, init : [int]):
+ return KApply(ELEM, [KInt(table_idx), offset, ints(init)])
+
+def data(memory_idx : int, offset, data : bytes):
+ return KApply(DATA, [KInt(memory_idx), offset, KBytes(data)])
+
+def start(start_idx : int):
+ return KApply(START, [KInt(start_idx)])
+
+def imp(mod_name, name, import_desc):
+ return KApply(IMPORT, [mod_name, name, import_desc])
+
+def export(name, index):
+ return KApply(EXPORT, [name, KInt(index)])
+
+def module_metadata(mid=None, fids=None, filename=None):
+ # TODO: Implement module id and function ids metadata transformation.
+ kfilename = EMPTY_OPT_STRING if filename is None else KString(filename)
+ return KApply(MODULE_METADATA, [EMPTY_ID, EMPTY_MAP, kfilename])
+
+EMPTY_MODULE_METADATA = module_metadata()
+
+def module(types=EMPTY_DEFNS,
+ funcs=EMPTY_DEFNS,
+ tables=EMPTY_DEFNS,
+ mems=EMPTY_DEFNS,
+ globs=EMPTY_DEFNS,
+ elem=EMPTY_DEFNS,
+ data=EMPTY_DEFNS,
+ start=EMPTY_DEFNS,
+ imports=EMPTY_DEFNS,
+ exports=EMPTY_DEFNS,
+ metadata=EMPTY_MODULE_METADATA):
+ """Construct a Kast of a module."""
+ return KApply(MODULE,
+ [types,
+ funcs,
+ tables,
+ mems,
+ globs,
+ elem,
+ data,
+ start,
+ imports,
+ exports,
+ metadata])
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/test.py b/docs/runtimeverification-wasm-semantics/binary-parser/test.py
new file mode 100644
index 000000000..34fb4526c
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/binary-parser/test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+import wasm2kast
+import json
+import pyk
+import sys
+import subprocess
+import tempfile
+
+WASM_definition_llvm_no_coverage_dir = '.build/defn/llvm'
+
+def config_to_kast_term(config):
+ return { 'format' : 'KAST', 'version': 2, 'term': config.to_dict() }
+
+def run_module(parsed_module):
+ input_json = config_to_kast_term(parsed_module)
+ krun_args = [ '--term', '--debug']
+
+ with tempfile.NamedTemporaryFile(mode = 'w') as tempf:
+ tempf.write(json.dumps(input_json))
+ tempf.flush()
+
+ command = ['krun-legacy', '--directory',
+ WASM_definition_llvm_no_coverage_dir, '--term', tempf.name,
+ '--parser', 'cat', '--output', 'json']
+ process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = process.communicate(input=None)
+ rc = process.returncode
+
+ if rc != 0:
+ raise Exception(f'Received error while running: {str(stderr)}')
+
+def pykPrettyPrint(module):
+ WASM_definition_llvm_no_coverage_dir = '.build/defn/llvm'
+ WASM_definition_main_file = 'test'
+ WASM_definition_llvm_no_coverage = pyk.readKastTerm(WASM_definition_llvm_no_coverage_dir + '/' + WASM_definition_main_file + '-kompiled/compiled.json')
+ WASM_symbols_llvm_no_coverage = pyk.buildSymbolTable(WASM_definition_llvm_no_coverage)
+ print(pyk.prettyPrintKast(module, WASM_symbols_llvm_no_coverage))
+
+sys.setrecursionlimit(1500000000)
+
+if __name__ == "__main__":
+ module = wasm2kast.main()
+ run_module(module)
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/test_kwasm_ast.py b/docs/runtimeverification-wasm-semantics/binary-parser/test_kwasm_ast.py
new file mode 100644
index 000000000..1c836f13e
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/binary-parser/test_kwasm_ast.py
@@ -0,0 +1,23 @@
+import pytest
+
+from kwasm_ast import KBytes
+
+KBYTES_TEST_DATA = (
+ (bytes([0x0, 0x41, 0xff]), 'b"\x00\x41\xff"'),
+ (bytes([]), 'b""'),
+ (b'WASM', 'b"WASM"'),
+ (b'foo\xAA\x01barbaz', 'b"foo\xAA\x01barbaz"'),
+ (b'foo\xAAbar\x01baz', 'b"foo\xAAbar\x01baz"'),
+ (b'abcdefghijklmnopqrstuvwxyz', 'b"abcdefghijklmnopqrstuvwxyz"'),
+ (0x11223344556677889900aabbccddeeff.to_bytes(length=16, byteorder='big'),
+ 'b"\x11\x22\x33\x44\x55\x66\x77\x88\x99\x00\xaa\xbb\xcc\xdd\xee\xff"')
+)
+
+@pytest.mark.parametrize(('input', 'expected'), KBYTES_TEST_DATA)
+def test_kbytes(input, expected) -> None:
+ # When
+ t = KBytes(input)
+
+ # Then
+ assert t.token == expected
+ assert t.sort.name == 'Bytes'
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/wasm b/docs/runtimeverification-wasm-semantics/binary-parser/wasm
new file mode 120000
index 000000000..b8e61c3ee
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/binary-parser/wasm
@@ -0,0 +1 @@
+../deps/py-wasm/wasm
\ No newline at end of file
diff --git a/docs/runtimeverification-wasm-semantics/binary-parser/wasm2kast.py b/docs/runtimeverification-wasm-semantics/binary-parser/wasm2kast.py
new file mode 100644
index 000000000..abf03ad8e
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/binary-parser/wasm2kast.py
@@ -0,0 +1,268 @@
+#!/usr/bin/env python3
+
+"""
+This library provides a translation from the Wasm binary format to Kast.
+"""
+
+import sys
+import json
+import kwasm_ast as a
+
+from wasm.parsers.module import parse_module, Module
+from wasm.datatypes import ValType, TypeIdx, FunctionType, Function, Table, TableType, Memory, MemoryType, Limits, Global, GlobalType, Mutability, ElementSegment, DataSegment, StartFunction, Import, Export
+from wasm.opcodes import BinaryOpcode
+
+def main():
+ if len(list(sys.argv)) == 1:
+ infile = sys.stdin
+ else:
+ infile = open(sys.argv[1], 'rb')
+ module = wasm2kast(infile)
+ infile.close()
+ return module
+
+def wasm2kast(wasm_bytes : bytes, filename=None) -> dict:
+ """Returns a dictionary representing the Kast JSON."""
+ ast = parse_module(wasm_bytes)
+ return ast2kast(ast, filename=filename)
+
+def ast2kast(wasm_ast : Module, filename=None) -> dict:
+ """Returns a dictionary representing the Kast JSON."""
+ types = a.defns([typ(x) for x in wasm_ast.types])
+ funcs = a.defns([func(x) for x in wasm_ast.funcs])
+ tables = a.defns([table(x) for x in wasm_ast.tables])
+ mems = a.defns([memory(x) for x in wasm_ast.mems])
+ globs = a.defns([glob(x) for x in wasm_ast.globals])
+ elems = a.defns([elem(x) for x in wasm_ast.elem])
+ datas = a.defns([data(x) for x in wasm_ast.data])
+ starts = a.defns(start(wasm_ast.start))
+ imports = a.defns([imp(x) for x in wasm_ast.imports])
+ exports = a.defns([export(x) for x in wasm_ast.exports])
+ meta = a.module_metadata(filename=filename)
+ return a.module(types=types, funcs=funcs, tables=tables, mems=mems, globs=globs, elem=elems, data=datas, start=starts, imports=imports, exports=exports, metadata=meta)
+
+#########
+# Defns #
+#########
+
+def typ(t : FunctionType):
+ return a.type(func_type(t.params, t.results))
+
+def func(f : Function):
+ type = a.KInt(f.type_idx)
+ ls_list = [val_type(x) for x in f.locals]
+ locals = a.vec_type(a.val_types(ls_list))
+ body = instrs(f.body)
+ return a.func(type, locals, body)
+
+def table(t : Table):
+ ls = limits(t.type.limits)
+ return a.table(ls)
+
+def memory(m : Memory):
+ ls = limits(m.type)
+ return a.memory(ls)
+
+def glob(g : Global):
+ t = global_type(g.type)
+ init = instrs(g.init)
+ return a.glob(t, init)
+
+def elem(e : ElementSegment):
+ offset = instrs(e.offset)
+ return a.elem(e.table_idx, offset, e.init)
+
+def data(d : DataSegment):
+ offset = instrs(d.offset)
+ return a.data(d.memory_idx, offset, d.init)
+
+def start(s : StartFunction):
+ if s is None:
+ return []
+ return [a.start(s.function_idx)]
+
+def imp(i : Import):
+ mod_name = a.wasm_string(i.module_name)
+ name = a.wasm_string(i.as_name)
+ t = type(i.desc)
+ if t is TypeIdx:
+ desc = a.func_desc(i.desc)
+ elif t is GlobalType:
+ desc = a.global_desc(global_type(i.desc))
+ elif t is TableType:
+ desc = a.table_desc(limits(i.desc.limits))
+ elif t is MemoryType:
+ desc = a.memory_desc(limits(i.desc))
+ return a.imp(mod_name, name, desc)
+
+def export(e : Export):
+ name = a.wasm_string(e.name)
+ idx = e.desc
+ return a.export(name, idx)
+
+##########
+# Instrs #
+##########
+
+block_id = 0
+
+def instrs(iis):
+ """Turn a list of instructions into KAST."""
+ # We ignore `END`.
+ # The AST supplied by py-wasm has already parsed these and terminated the blocks.
+ # We also ignore `ELSE`.
+ # The AST supplied by py-wasm includes the statements in the else-branch as part of the `IF` instruction.
+ return a.instrs([instr(i) for i in iis
+ if not i.opcode == BinaryOpcode.END
+ and not i.opcode == BinaryOpcode.ELSE])
+
+def instr(i):
+ B = BinaryOpcode
+ global block_id
+ if i.opcode == B.BLOCK:
+ cur_block_id = block_id
+ block_id += 1
+ iis = instrs(i.instructions)
+ res = vec_type(i.result_type)
+ return a.BLOCK(res, iis, a.KInt(cur_block_id))
+ if i.opcode == B.BR:
+ return a.BR(i.label_idx)
+ if i.opcode == B.BR_IF:
+ return a.BR_IF(i.label_idx)
+ if i.opcode == B.BR_TABLE:
+ return a.BR_TABLE(i.label_indices, i.default_idx)
+ if i.opcode == B.CALL:
+ return a.CALL(i.function_idx)
+ if i.opcode == B.CALL_INDIRECT:
+ return a.CALL_INDIRECT(i.type_idx)
+ if i.opcode == B.ELSE:
+ raise(ValueError("ELSE opcode: should have been filtered out."))
+ if i.opcode == B.END:
+ raise(ValueError("End opcode: should have been filtered out."))
+ if i.opcode == B.F32_CONST:
+ return a.F32_CONST(i.value)
+ if i.opcode == B.F64_CONST:
+ return a.F64_CONST(i.value)
+ if i.opcode == B.F32_REINTERPRET_I32:
+ raise(ValueError('Reinterpret instructions not implemented.'))
+ if i.opcode == B.F64_REINTERPRET_I64:
+ raise(ValueError('Reinterpret instructions not implemented.'))
+ if i.opcode == B.GET_GLOBAL:
+ return a.GET_GLOBAL(i.global_idx)
+ if i.opcode == B.GET_LOCAL:
+ return a.GET_LOCAL(i.local_idx)
+ if i.opcode == B.I32_CONST:
+ return a.I32_CONST(i.value)
+ if i.opcode == B.I64_CONST:
+ return a.I64_CONST(i.value)
+ if i.opcode == B.I32_REINTERPRET_F32:
+ raise(ValueError('Reinterpret instructions not implemented.'))
+ if i.opcode == B.I64_REINTERPRET_F64:
+ raise(ValueError('Reinterpret instructions not implemented.'))
+ if i.opcode == B.IF:
+ cur_block_id = block_id
+ block_id += 1
+ thens = instrs(i.instructions)
+ els = instrs(i.else_instructions)
+ res = vec_type(i.result_type)
+ return a.IF(res, thens, els, a.KInt(cur_block_id))
+ if i.opcode == B.F32_STORE:
+ return a.F32_STORE(i.memarg.offset)
+ if i.opcode == B.F64_STORE:
+ return a.F64_STORE(i.memarg.offset)
+ if i.opcode == B.I32_STORE:
+ return a.I32_STORE(i.memarg.offset)
+ if i.opcode == B.I64_STORE:
+ return a.I64_STORE(i.memarg.offset)
+ if i.opcode == B.I32_STORE16:
+ return a.I32_STORE16(i.memarg.offset)
+ if i.opcode == B.I64_STORE16:
+ return a.I64_STORE16(i.memarg.offset)
+ if i.opcode == B.I32_STORE8:
+ return a.I32_STORE8(i.memarg.offset)
+ if i.opcode == B.I64_STORE8:
+ return a.I64_STORE8(i.memarg.offset)
+ if i.opcode == B.I64_STORE32:
+ return a.I64_STORE32(i.memarg.offset)
+ if i.opcode == B.F32_LOAD:
+ return a.F32_LOAD(i.memarg.offset)
+ if i.opcode == B.F64_LOAD:
+ return a.F64_LOAD(i.memarg.offset)
+ if i.opcode == B.I32_LOAD:
+ return a.I32_LOAD(i.memarg.offset)
+ if i.opcode == B.I64_LOAD:
+ return a.I64_LOAD(i.memarg.offset)
+ if i.opcode == B.I32_LOAD16_S:
+ return a.I32_LOAD16_S(i.memarg.offset)
+ if i.opcode == B.I32_LOAD16_U:
+ return a.I32_LOAD16_U(i.memarg.offset)
+ if i.opcode == B.I64_LOAD16_S:
+ return a.I64_LOAD16_S(i.memarg.offset)
+ if i.opcode == B.I64_LOAD16_U:
+ return a.I64_LOAD16_U(i.memarg.offset)
+ if i.opcode == B.I32_LOAD8_S:
+ return a.I32_LOAD8_S(i.memarg.offset)
+ if i.opcode == B.I32_LOAD8_U:
+ return a.I32_LOAD8_U(i.memarg.offset)
+ if i.opcode == B.I64_LOAD8_S:
+ return a.I64_LOAD8_S(i.memarg.offset)
+ if i.opcode == B.I64_LOAD8_U:
+ return a.I64_LOAD8_U(i.memarg.offset)
+ if i.opcode == B.I64_LOAD32_S:
+ return a.I64_LOAD32_S(i.memarg.offset)
+ if i.opcode == B.I64_LOAD32_U:
+ return a.I64_LOAD32_U(i.memarg.offset)
+ if i.opcode == B.LOOP:
+ cur_block_id = block_id
+ block_id += 1
+ iis = instrs(i.instructions)
+ res = vec_type(i.result_type)
+ return a.LOOP(res, iis, a.KInt(cur_block_id))
+ if i.opcode == B.SET_GLOBAL:
+ return a.SET_GLOBAL(i.global_idx)
+ if i.opcode == B.SET_LOCAL:
+ return a.SET_LOCAL(i.local_idx)
+ if i.opcode == B.TEE_LOCAL:
+ return a.TEE_LOCAL(i.local_idx)
+ # Catch all for operations without direct arguments.
+ op = i.opcode
+ return eval('a.' + i.opcode.name)
+
+########
+# Data #
+########
+
+def val_type(t : ValType):
+ if t == ValType.i32:
+ return a.i32
+ if t == ValType.i64:
+ return a.i64
+ if t == ValType.f32:
+ return a.f32
+ if t == ValType.f64:
+ return a.f64
+
+def vec_type(ts : [ValType]):
+ _ts = [val_type(x) for x in ts]
+ return a.vec_type(a.val_types(_ts))
+
+def func_type(params, results):
+ pvec = vec_type(params)
+ rvec = vec_type(results)
+ return a.func_type(pvec, rvec)
+
+def limits(l : Limits):
+ return (l.min, l.max)
+
+def global_type(t : GlobalType):
+ vt = val_type(t.valtype)
+ if t.mut is Mutability.const:
+ return a.global_type(a.MUT_CONST, vt)
+ return a.global_type(a.MUT_VAR, vt)
+
+########
+# Main #
+########
+
+if __name__ == "__main__":
+ main()
diff --git a/docs/runtimeverification-wasm-semantics/convert.py b/docs/runtimeverification-wasm-semantics/convert.py
new file mode 100644
index 000000000..bfebd0f0b
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/convert.py
@@ -0,0 +1,39 @@
+# This script is not used during runtime.
+# It just helps converting some conformances test to a test that we can use by removing unsupported functions and converting hexfloat to normal float.
+# However it does not support multi-line assertions, function definitions, etc.
+# The test files under directory tests/simple/float were generated by this script.
+# example usage: python convert.py f32.wast
+
+import re
+import sys
+
+
+def hex2float(h):
+ print(h)
+ if "nan" in h:
+ return h.replace("nan", "NaN")
+ elif "inf" in h:
+ return h.replace("inf", "Infinity")
+ elif "0x" not in h:
+ return h
+ else:
+ return h.split()[0] + " " + "%e" % (float.fromhex(h.split()[1]))
+
+
+def main():
+ filename = sys.argv[1]
+ infile = "tests/wasm-tests/test/core/%s" % filename
+ outfile = open("tests/simple/%s-c.%s" % tuple(filename.split(".")), "w")
+ unsupported = ["nan:", "-nan", "reinterpret",
+ "assert_return_canonical_nan", "assert_return_arithmetic_nan", "assert_invalid", "assert_malformed"]
+ for line in (open(infile).readlines()):
+ if any(x in line for x in unsupported):
+ outfile.write(";; "+line)
+ else:
+ outfile.write(re.sub(r"(?:(?:f32|f64)\.const )([^\)]+)",
+ lambda m: hex2float(m.group()), line))
+ outfile.write("\n#clearConfig\n")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/docs/runtimeverification-wasm-semantics/data.md b/docs/runtimeverification-wasm-semantics/data.md
new file mode 100644
index 000000000..10334132b
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/data.md
@@ -0,0 +1,606 @@
+WebAssembly Data
+================
+
+```k
+module WASM-DATA-SYNTAX
+ imports WASM-DATA-COMMON-SYNTAX
+endmodule
+```
+
+Common Syntax
+-------------
+
+```k
+module WASM-DATA-COMMON-SYNTAX
+ imports INT-SYNTAX
+ imports FLOAT-SYNTAX
+```
+
+### WASM Token Sorts
+
+```k
+ syntax IdentifierToken [token]
+ syntax WasmIntToken [token]
+ syntax #Layout [token]
+ syntax WasmStringToken [token]
+ // ------------------------------
+```
+
+### Identifiers
+
+And we use `OptionalId` to handle the case where an identifier could be omitted.
+
+```k
+ syntax Identifier ::= IdentifierToken
+ syntax OptionalId ::= "" [klabel(.Identifier), symbol]
+ | Identifier
+ // --------------------------------
+```
+
+### Strings
+
+Wasm binary data can sometimes be specified as a string.
+The string considered to represent the sequence of UTF-8 bytes that encode it.
+The exception is for characters that are explicitly escaped which can represent bytes in hexadecimal form.
+
+```k
+ syntax WasmString ::= ".WasmString"
+ | WasmStringToken
+ // -------------------------------------
+
+ syntax String ::= #parseWasmString ( WasmStringToken ) [function, total, hook(STRING.token2string)]
+ // ----------------------------------------------------------------------------------------------------------
+
+ syntax DataString ::= List{WasmString, ""} [klabel(listWasmString)]
+ // -------------------------------------------------------------------
+```
+
+### Indices
+
+Many constructions in Wasm, such a functions, labels, locals, types, etc., are referred to by their index.
+In the abstract syntax of Wasm, indices are 32 bit unsigned integers.
+However, we extend the `Index` sort with another subsort, `Identifier`, in the text format.
+
+```k
+ syntax Index ::= WasmInt
+ // ------------------------
+```
+
+### ElemSegment
+
+Element Segment is a list of indices.
+It is used when initializing a WebAssembly table, or used as the parameter of the `br_table` function.
+
+```k
+ syntax ElemSegment ::= List{Index, ""} [klabel(listIndex)]
+ // ----------------------------------------------------------
+```
+
+### WebAssembly Types
+
+#### Base Types
+
+WebAssembly has four basic types, for 32 and 64 bit integers and floats.
+
+```k
+ syntax IValType ::= "i32" [klabel(i32), symbol] | "i64" [klabel(i64), symbol]
+ syntax FValType ::= "f32" [klabel(f32), symbol] | "f64" [klabel(f64), symbol]
+ syntax ValType ::= IValType | FValType
+ // ---------------------------------------
+```
+
+#### Type Constructors
+
+There are two basic type-constructors: sequencing (`[_]`) and function spaces (`_->_`).
+
+```k
+ syntax ValTypes ::= List{ValType, ""} [klabel(listValTypes), symbol]
+ // --------------------------------------------------------------------
+```
+
+### Integers
+
+Here we define the rules about what integer formats can be used in Wasm.
+For the core language, only regular integers are allowed.
+
+```k
+ syntax WasmInt ::= Int
+ // ----------------------
+```
+### Type Mutability
+
+```k
+ syntax Mut ::= "const" [klabel(mutConst), symbol]
+ | "var" [klabel(mutVar), symbol]
+ // -----------------------------------------------
+```
+
+
+### Basic Values
+
+WebAssembly values are either integers or floating-point numbers, of 32- or 64-bit widths.
+
+```k
+ syntax Number ::= Int | Float
+ // -----------------------------
+```
+
+### External Values
+
+An `external value` is the runtime representation of an entity that can be `imported` or `exported`.
+It is an `address` denoting either a `function instance`, `table instance`, `memory instance`, or `global instances` in the shared store.
+
+```k
+ syntax AllocatedKind ::= "func" | "table" | "memory" | "global"
+ syntax Externval ::= AllocatedKind Index
+ // --------------------------------------------
+```
+
+```k
+endmodule
+```
+
+`WASM-DATA` module
+------------------
+
+```k
+module WASM-DATA
+ imports WASM-DATA-COMMON-SYNTAX
+
+ imports INT
+ imports BOOL
+ imports STRING
+ imports LIST
+ imports MAP
+ imports FLOAT
+ imports BYTES
+ imports K-EQUAL
+```
+
+### Identifiers
+
+In `KWASM` rules, we use `#freshId ( Int )` to generate a fresh identifier based on the element index in the current module.
+```k
+ syntax Identifier ::= #freshId ( Int )
+ // --------------------------------------
+```
+
+In KWasm we store identifiers in maps from `Identifier` to `Int`, the `Int` being an index.
+This rule handles adding an `OptionalId` as a map key, but only when it is a proper identifier.
+
+```k
+ syntax Map ::= #saveId (Map, OptionalId, Int) [function]
+ // -------------------------------------------------------
+ rule #saveId (MAP, ID:OptionalId, _) => MAP requires notBool isIdentifier(ID)
+ rule #saveId (MAP, ID:Identifier, IDX) => MAP [ID <- IDX]
+```
+
+`Int` is the basic form of index, and indices always need to resolve to integers.
+In the text format, `Index` is extended with the `Identifier` subsort, and there needs to be a way to resolve it to an `Int`.
+In Wasm, the current "context" contains a mapping from identifiers to indices.
+The `#ContextLookup` function provides an extensible way to get an `Int` from an index.
+Any extension of the `Index` type requires that the function `#ContextLookup` is suitably extended.
+For `Int`, however, a the context is irrelevant and the index always just resolves to the integer.
+
+```k
+ syntax Int ::= #ContextLookup ( Map , Index ) [function]
+ // --------------------------------------------------------
+ rule #ContextLookup(_IDS:Map, I:Int) => I
+```
+
+### ElemSegment
+
+```k
+ syntax Ints ::= List{Int, ""} [klabel(listInt), symbol]
+ // -------------------------------------------------------
+
+ syntax Int ::= #lenElemSegment (ElemSegment) [function]
+ syntax Index ::= #getElemSegment (ElemSegment, Int) [function]
+ syntax Int ::= #lenInts (Ints) [function]
+ syntax Int ::= #getInts (Ints, Int) [function]
+ // --------------------------------------------------------------
+ rule #lenElemSegment(.ElemSegment) => 0
+ rule #lenElemSegment(_TFIDX ES) => 1 +Int #lenElemSegment(ES)
+
+ rule #getElemSegment(E _ES, 0) => E
+ rule #getElemSegment(_E ES, I) => #getElemSegment(ES, I -Int 1) requires I >Int 0
+
+ rule #lenInts(.Ints) => 0
+ rule #lenInts(_TFIDX ES) => 1 +Int #lenInts(ES)
+
+ rule #getInts(E _ES, 0) => E
+ rule #getInts(_E ES, I) => #getInts(ES, I -Int 1) requires I >Int 0
+
+ syntax Ints ::= elemSegment2Ints ( ElemSegment ) [function]
+ // -----------------------------------------------------------
+ rule elemSegment2Ints(.ElemSegment) => .Ints
+ rule elemSegment2Ints(E:Int ES) => E elemSegment2Ints(ES)
+```
+
+### OptionalInt
+
+In some cases, an integer is optional, such as when either giving or omitting the max bound when defining a table or memory.
+The sort `OptionalInt` provides this potentially "undefined" `Int`.
+
+```k
+ syntax OptionalInt ::= Int | ".Int"
+ // -----------------------------------
+```
+
+### Limits
+
+Tables and memories have limits, defined as either a single `Int` or two `Int`s, representing min and max bounds.
+
+```k
+ syntax Limits ::= #limitsMin(Int) [klabel(limitsMin), symbol]
+ | #limits(Int, Int) [klabel(limitsMinMax), symbol]
+ // ------------------------------------------------------------------
+```
+
+### Type Constructors
+
+There are two basic type-constructors: sequencing (`[_]`) and function spaces (`_->_`).
+
+```k
+ syntax VecType ::= "[" ValTypes "]" [klabel(aVecType), symbol]
+ // ---------------------------------------------------------------
+
+ syntax FuncType ::= VecType "->" VecType [klabel(aFuncType), symbol]
+ // --------------------------------------------------------------------
+
+ syntax Int ::= lengthValTypes ( ValTypes ) [function, total]
+ // -----------------------------------------------------------------
+ rule lengthValTypes(.ValTypes) => 0
+ rule lengthValTypes(_V VS) => 1 +Int lengthValTypes(VS)
+```
+
+All told, a `Type` can be a value type, vector of types, or function type.
+
+```k
+ syntax Type ::= ".Type" | ValType | VecType | FuncType
+ // ------------------------------------------------------
+```
+
+We can append two `ValTypes`s with the `_+_` operator.
+
+```k
+ syntax ValTypes ::= ValTypes "+" ValTypes [function, total]
+ // ----------------------------------------------------------------
+ rule .ValTypes + VTYPES' => VTYPES'
+ rule (VT VTYPES) + VTYPES' => VT (VTYPES + VTYPES')
+```
+
+Also we can reverse a `ValTypes` with `#revt`
+
+```k
+ syntax ValTypes ::= #revt ( ValTypes ) [function, total]
+ | #revt ( ValTypes , ValTypes ) [function, total, klabel(#revtAux)]
+ // ------------------------------------------------------------------------------------------
+ rule #revt(VT) => #revt(VT, .ValTypes)
+
+ rule #revt(.ValTypes, VT') => VT'
+ rule #revt(V VT , VT') => #revt(VT, V VT')
+```
+
+### Type Information
+
+The `#width` function returns the bit-width of a given `IValType`.
+
+```k
+ syntax Int ::= #width ( IValType ) [function, total]
+ syntax Int ::= #numBytes ( IValType ) [function, total, smtlib(numBytes)]
+ // ------------------------------------------------------------------------------
+ rule #width(i32) => 32
+ rule #width(i64) => 64
+
+ rule #numBytes(ITYPE) => #width(ITYPE) /Int 8 [concrete]
+```
+
+`2 ^Int 32` and `2 ^Int 64` are used often enough to warrant providing helpers for them.
+
+```k
+ syntax Int ::= #pow ( IValType ) [function, total, smtlib(pow )] /* 2 ^Int #width(T) */
+ | #pow1 ( IValType ) [function, total, smtlib(pow1)] /* 2 ^Int (#width(T) -Int 1) */
+ // ------------------------------------------------------------------------------------------------------
+ rule #pow1(i32) => 2147483648
+ rule #pow (i32) => 4294967296
+ rule #pow1(i64) => 9223372036854775808
+ rule #pow (i64) => 18446744073709551616
+```
+
+### Type Mutability
+
+```k
+ syntax Mut ::= ".Mut"
+ // ----------------------
+```
+
+### Values
+
+Proper values are numbers annotated with their types.
+
+```k
+ syntax IVal ::= "<" IValType ">" Int [klabel(<_>_)]
+ syntax FVal ::= "<" FValType ">" Float [klabel(<_>_)]
+ syntax Val ::= "<" ValType ">" Number [klabel(<_>_)]
+ | IVal | FVal
+ // ---------------------------
+```
+
+We also add `undefined` as a value, which makes many partial functions in the semantics total.
+
+```k
+ syntax Val ::= "undefined"
+ // --------------------------
+```
+
+#### Value Operations
+
+The `#chop` function will ensure that an integer value is wrapped to the correct bit-width.
+The `#wrap` function wraps an integer to a given byte width.
+The `#get` function extracts the underlying K integer from a WASM `IVal`.
+
+```k
+ syntax IVal ::= #chop ( IVal ) [function, total]
+ // -----------------------------------------------------
+ rule #chop(< ITYPE > N) => < ITYPE > (N modInt #pow(ITYPE))
+
+ syntax Int ::= #wrap ( Int , Int ) [function, total]
+ // ---------------------------------------------------------
+ rule [wrap-Positive] : #wrap(WIDTH, N) => N &Int ((1 < 0 requires notBool 0 N) => N
+```
+
+In `K` all `Float` numbers are of 64-bits width by default, so we need to downcast a `f32` float to 32-bit manually.
+The `#round` function casts a `f64` float to a `f32` float.
+`f64` floats has 1 bit for the sign, 53 bits for the value and 11 bits for exponent.
+`f32` floats has 1 bit for the sign, 23 bits for the value and 8 bits for exponent.
+
+```k
+ syntax FVal ::= #round ( FValType , Number ) [function]
+ // -------------------------------------------------------
+ rule #round(f64 , N:Float) => < f64 > roundFloat(N, 53, 11) [concrete]
+ rule #round(f32 , N:Float) => < f32 > roundFloat(N, 24, 8) [concrete]
+ rule #round(f64 , N:Int ) => < f64 > Int2Float(N, 53, 11) [concrete]
+ rule #round(f32 , N:Int ) => < f32 > Int2Float(N, 24, 8) [concrete]
+```
+
+#### Signed Interpretation
+
+Functions `#signed` and `#unsigned` allow for easier operation on twos-complement numbers.
+These functions assume that the argument integer is in the valid range of signed and unsigned values of the respective type, so they will not correctly map arbitrary integers into the corret range.
+Some operations extend integers from 1, 2, or 4 bytes, so a special function with a bit width argument helps with the conversion.
+
+```k
+ syntax Int ::= #signed ( IValType , Int ) [function]
+ | #unsigned ( IValType , Int ) [function]
+ | #signedWidth ( Int , Int ) [function]
+ // ---------------------------------------------------------
+ rule #signed(ITYPE, N) => N requires 0 <=Int N andBool N N -Int #pow(ITYPE) requires #pow1(ITYPE) <=Int N andBool N N +Int #pow(ITYPE) requires N N requires 0 <=Int N
+
+ rule #signedWidth(1, N) => N requires 0 <=Int N andBool N N -Int 256 requires 128 <=Int N andBool N N requires 0 <=Int N andBool N N -Int 65536 requires 32768 <=Int N andBool N #signed(i32, N)
+```
+
+#### Boolean Interpretation
+
+Function `#bool` converts a `Bool` into an `Int`.
+
+```k
+ syntax Int ::= #bool ( Bool ) [function, total]
+ // ----------------------------------------------------
+ rule #bool( B:Bool ) => 1 requires B
+ rule #bool( B:Bool ) => 0 requires notBool B
+```
+
+### Data Structures
+
+WebAssembly is a stack-machine, so here we provide the stack to operate over.
+Operator `_++_` implements an append operator for sort `ValStack`.
+
+```k
+ syntax ValStack ::= ".ValStack"
+ | Val ":" ValStack
+ | ValStack "++" ValStack [function, total]
+ // -----------------------------------------------------------------
+ rule .ValStack ++ VALSTACK' => VALSTACK'
+ rule (SI : VALSTACK) ++ VALSTACK' => SI : (VALSTACK ++ VALSTACK')
+```
+
+`#zero` will create a specified stack of zero values in a given type.
+`#take` will take the prefix of a given stack.
+`#drop` will drop the prefix of a given stack.
+`#revs` will reverse a given stack.
+
+**NOTE**: `#take` and `#drop` are _total_, so in case they could not take/drop enough values before running out, they just return the empty `.ValStack`.
+Each call site _must_ ensure that this is desired behavior before using these functions.
+
+```k
+ syntax ValStack ::= #zero ( ValTypes ) [function, total]
+ | #take ( Int , ValStack ) [function, total]
+ | #drop ( Int , ValStack ) [function, total]
+ | #revs ( ValStack ) [function, total]
+ | #revs ( ValStack , ValStack ) [function, total, klabel(#revsAux)]
+ // ------------------------------------------------------------------------------------------
+ rule #zero(.ValTypes) => .ValStack
+ rule #zero(ITYPE:IValType VTYPES) => < ITYPE > 0 : #zero(VTYPES)
+ rule #zero(FTYPE:FValType VTYPES) => < FTYPE > 0.0 : #zero(VTYPES)
+
+ rule #take(N, _) => .ValStack requires notBool N >Int 0
+ rule #take(N, .ValStack) => .ValStack requires N >Int 0
+ rule #take(N, V : VS) => V : #take(N -Int 1, VS) requires N >Int 0
+
+ rule #drop(N, VS) => VS requires notBool N >Int 0
+ rule #drop(N, .ValStack) => .ValStack requires N >Int 0
+ rule #drop(N, _ : VS) => #drop(N -Int 1, VS) requires N >Int 0
+
+ rule #revs(VS) => #revs(VS, .ValStack)
+
+ rule #revs(.ValStack, VS') => VS'
+ rule #revs(V : VS , VS') => #revs(VS, V : VS')
+```
+
+### Strings
+
+Wasm uses a different character escape rule with K, so we need to define the `unescape` function ourselves.
+
+```k
+ syntax String ::= unescape(String) [function]
+ | unescape(String, Int, String) [function, klabel(unescapeAux)]
+ // -------------------------------------------------------------------------------
+ rule unescape(S ) => unescape(S, 1, "")
+ rule unescape(S, IDX, SB) => SB requires IDX ==Int lengthString(S) -Int 1
+```
+
+Unescaped characters just directly gets added to the output.
+The escaped character starts with a "\" and followed by 2 hexdigits will be converted to a unescaped character before stored.
+
+```k
+ rule unescape(S, IDX, SB) => unescape(S, IDX +Int 1, SB +String substrString(S, IDX, IDX +Int 1))
+ requires IDX unescape(S, IDX +Int 3, SB +String chrChar(String2Base(substrString(S, IDX +Int 1, IDX +Int 3), 16)))
+ requires IDX unescape(S, IDX +Int 2, SB +String chrChar(String2Base("09", 16)))
+ requires IDX unescape(S, IDX +Int 2, SB +String chrChar(String2Base("0A", 16)))
+ requires IDX unescape(S, IDX +Int 2, SB +String chrChar(String2Base("0D", 16)))
+ requires IDX unescape(S, IDX +Int 2, SB +String chrChar(String2Base("22", 16)))
+ requires IDX unescape(S, IDX +Int 2, SB +String chrChar(String2Base("27", 16)))
+ requires IDX unescape(S, IDX +Int 2, SB +String chrChar(String2Base("5C", 16)))
+ requires IDX +}`.
+The implementation is not correct for now because the UTF-8 encoding is not implemented.
+
+```k
+ syntax Int ::= #idxCloseBracket ( String, Int ) [function]
+ // ----------------------------------------------------------
+ rule #idxCloseBracket ( S, I ) => I requires substrString(S, I, I +Int 1) ==String "}"
+ rule #idxCloseBracket ( S, I ) => #idxCloseBracket ( S, I +Int 1 ) requires substrString(S, I, I +Int 1) =/=String "}"
+
+ syntax Bytes ::= #encodeUTF8 ( Int ) [function]
+ // -----------------------------------------------
+ rule #encodeUTF8 (I) => Int2Bytes(I, BE, Unsigned) requires I <=Int 127
+ rule #encodeUTF8 (I) => Int2Bytes(((((I &Int 1984) >>Int 6) +Int 192) <=Int 128 andBool I <=Int 2047
+ rule #encodeUTF8 (I) => Int2Bytes(((((I &Int 61440) >>Int 12) +Int 224) <>Int 6) +Int 128) <=Int 2048 andBool I <=Int 65535
+ rule #encodeUTF8 (I) => Int2Bytes(((((I &Int 1835008) >>Int 18) +Int 240) <>Int 12) +Int 128) <>Int6) +Int 128) <=Int 65536 andBool I <=Int 1114111
+
+ rule unescape(S, IDX, SB) => unescape(S, #idxCloseBracket(S, IDX) +Int 1, SB +String Bytes2String(#encodeUTF8(String2Base(substrString(S, IDX +Int 3, #idxCloseBracket(S, IDX +Int 3)), 16))))
+ requires substrString(S, IDX, IDX +Int 1) ==K "\\"
+ andBool substrString(S, IDX +Int 1, IDX +Int 2) ==K "u"
+```
+
+`DataString`, as is defined in the wasm semantics, is a list of `WasmString`s.
+`#concatDS` concatenates them together into a single string.
+The strings to connect needs to be unescaped before concatenated, because the `unescape` function removes the quote sign `"` before and after each substring.
+
+```k
+ syntax String ::= #concatDS ( DataString ) [function]
+ | #concatDS ( DataString, String ) [function, klabel(#concatDSAux)]
+ // -----------------------------------------------------------------------------------
+ rule #concatDS ( DS ) => #concatDS ( DS, "" )
+ rule #concatDS ( .DataString , S ) => S
+ rule #concatDS ( WS:WasmStringToken DS , S ) => #concatDS ( DS , S +String unescape(#parseWasmString(WS)) )
+```
+
+`#DS2Bytes` converts a `DataString` to a K builtin `Bytes`.
+
+```k
+ syntax Bytes ::= #DS2Bytes (DataString) [function]
+ // --------------------------------------------------
+ rule #DS2Bytes(DS) => String2Bytes(#concatDS(DS))
+```
+
+### Linear Memory
+
+Wasm memories are byte arrays, sized in pages of 65536 bytes, initialized to be all zero bytes.
+
+- `#setBytesRange(BM, START, BS)` assigns a contiguous chunk of `BS` to `BM` starting at position `N`.
+- `#setRange(BM, START, VAL, WIDTH)` writes the integer `I` to memory as bytes (little-endian), starting at index `N`.
+
+```k
+ syntax Bytes ::= #setBytesRange ( Bytes , Int , Bytes ) [function, total]
+ // ------------------------------------------------------------------------------
+ rule #setBytesRange(BM, START, BS) => replaceAtBytes(padRightBytes(BM, START +Int lengthBytes(BS), 0), START, BS)
+ requires 0 <=Int START
+
+ rule #setBytesRange(_, START, _ ) => .Bytes
+ requires notBool (0 <=Int START)
+
+ syntax Bytes ::= #setRange ( Bytes , Int , Int , Int ) [function, total, smtlib(setRange)]
+ // -----------------------------------------------------------------------------------------------
+ rule #setRange(BM, ADDR, VAL, WIDTH) => BM
+ requires notBool (0 #setBytesRange(BM, ADDR, Int2Bytes(WIDTH, VAL, LE))
+ requires 0 .Bytes
+ requires notBool (0 <=Int START andBool 0 <=Int WIDTH)
+
+ rule #getBytesRange(BM, START, WIDTH) => substrBytes(padRightBytes(BM, START +Int WIDTH, 0), START, START +Int WIDTH)
+ requires (0 <=Int START andBool 0 <=Int WIDTH)
+ andBool START padRightBytes(.Bytes, WIDTH, 0)
+ requires (0 <=Int START andBool 0 <=Int WIDTH)
+ andBool notBool (START 0
+ requires notBool (0 Bytes2Int(#getBytesRange(BM, ADDR, WIDTH), LE, Unsigned)
+ requires 0 &2 ; }
+fatal() { echo "[FATAL] $@" ; exit 1 ; }
+
+kwasm_dir="${KWASM_DIR:-$(dirname $0)}"
+build_dir="$kwasm_dir/.build"
+defn_dir="${KWASM_DEFN_DIR:-$build_dir/defn}"
+lib_dir="$build_dir/local/lib"
+k_release_dir="${K_RELEASE:-$kwasm_dir/deps/k/k-distribution/target/release/k}"
+if [[ ! -f "${k_release_dir}/bin/kompile" ]]; then
+ if which kompile &> /dev/null; then
+ k_release_dir="$(dirname $(which kompile))/.."
+ else
+ fatal "Cannot find K Installation!"
+ fi
+fi
+
+export PATH="$k_release_dir/lib/native/linux:$k_release_dir/lib/native/linux64:$k_release_dir/bin/:$PATH"
+export LD_LIBRARY_PATH="$k_release_dir/lib/native/linux64:$lib_dir:${LD_LIBRARY_PATH:-}"
+
+test_logs="$build_dir/logs"
+mkdir -p "$test_logs"
+test_log="$test_logs/tests.log"
+
+export K_OPTS="${K_OPTS:--Xmx16G -Xss512m}"
+
+# Utilities
+# ---------
+
+preprocess() {
+ local this_script_dir tmp_dir tmp_input
+ this_script_dir="$(dirname $0)"
+ tmp_dir="$(mktemp -d)"
+ tmp_input="$tmp_dir/$(basename $run_file))"
+ touch "$tmp_input"
+ python3 "$this_script_dir/preprocessor.py" "$run_file" > "$tmp_input"
+ run_file="$tmp_input"
+}
+
+# Runners
+# -------
+
+run_krun() {
+ local additional_run_args
+
+ additional_run_args=()
+ ! $bug_report || additional_run_args+=(--haskell-backend-command "kore-exec --bug-report $bug_report_name")
+
+ preprocess
+ krun --directory "$backend_dir" "$run_file" "${additional_run_args[@]}" "$@"
+}
+
+run_krun_legacy() {
+ local additional_run_args
+
+ additional_run_args=()
+ ! $bug_report || additional_run_args+=(--haskell-backend-command "kore-exec --bug-report $bug_report_name")
+
+ preprocess
+ krun-legacy --directory "$backend_dir" "$run_file" "${additional_run_args[@]}" "$@"
+}
+
+run_kast() {
+ local output_mode
+
+ preprocess
+ output_mode="${1:-kast}" ; shift
+ kast --directory "$backend_dir" "$run_file" --output "$output_mode" "$@"
+}
+
+run_prove() {
+ local additional_proof_args
+
+ def_module="$1" ; shift
+
+ additional_proof_args=()
+ ! $repl || additional_proof_args+=(--debugger)
+ ! $bug_report || additional_proof_args+=(--haskell-backend-command "kore-exec --bug-report $bug_report_name")
+
+ kprove-legacy --directory "$backend_dir" -I "$kwasm_dir" "$run_file" --def-module "$def_module" "${additional_proof_args[@]}" "$@"
+}
+
+# Main
+# ----
+
+usage() {
+ echo "
+ usage: $0 run [--backend (llvm|haskell)] [--bug-report] *
+ $0 run-legacy [--backend (llvm|haskell)] [--bug-report] *
+ $0 kast [--backend (llvm|haskell)]
+ claim run ( #getRange(BM, ADDR, 3) modInt 256 ) => done ( #getRange(BM, ADDR , 1) ) ...
+ claim run ( #getRange(BM, ADDR, 3) modInt (2 ^Int (8 *Int 3)) ) => done ( #getRange(BM, ADDR , 3) ) ...
+ claim run ( #getRange(BM, ADDR, 7) modInt (2 ^Int (8 *Int 3)) ) => done ( #getRange(BM, ADDR , 3) ) ...
+ claim run ( #getRange(BM, ADDR, 2) >>Int 8 ) => done ( #getRange(BM, ADDR +Int 1, 1) ) ... requires 0 <=Int ADDR
+
+ claim run ( ( ( #getRange ( BM , ADDR +Int 1 , 1 ) modInt 256 ) +Int ( #getRange ( BM , ADDR , 1 ) modInt 256 < done ( ( #getRange ( BM , ADDR +Int 1 , 1 ) +Int ( #getRange ( BM , ADDR , 1 ) <
+
+ claim run ( ( ( #getRange ( BM , ADDR +Int 1 , 7 ) modInt 256 ) +Int ( #getRange ( BM , ADDR , 8 ) modInt 256 < done ( ( ( #getRange ( BM , ADDR +Int 1 , 1 ) ) +Int ( #getRange ( BM , ADDR , 1 ) <
+
+ claim run ( #setRange(BM, ADDR, #getRange(BM, ADDR +Int 1, 1) +Int (#getRange(BM, ADDR, 1) < done ( #setRange(#setRange(BM, ADDR, #getRange(BM, ADDR +Int 1, 1), 1), ADDR +Int 1, #getRange(BM, ADDR, 1), 1) )
+ ...
+
+ requires ADDR >=Int 0
+
+ claim run ( #setRange ( BM , ADDR modInt 4294967296 , #getRange ( BM , ADDR modInt 4294967296 , #numBytes ( ITYPE ) ) , #numBytes ( ITYPE ) ) )
+ => done ( BM )
+ ...
+
+
+ claim run ( (#getRange(BM, ADDR +Int 1, 1) +Int (#getRange (BM, ADDR, 1) < done ( #getRange(BM, ADDR +Int 1, 1) +Int (#getRange (BM, ADDR, 1) <
+
+ claim run ( #getRange ( #setRange ( BM , ADDR +Int 7 , _VAL , 1 ) , ADDR +Int 3 , 1 ) ) => done ( #getRange ( BM , ADDR +Int 3 , 1 ) ) ...
+
+ claim run ( #getRange ( #setRange ( _BM , ADDR +Int 7 , VAL , 1 ) , ADDR +Int 7 , 1 ) ) => done ( VAL ) ... requires 0 <=Int ADDR andBool 0 <=Int VAL andBool VAL run ( #getRange ( #setRange ( #setRange ( #setRange ( #setRange ( #setRange ( #setRange ( #setRange ( #setRange ( BM , ADDR , #getRange ( BM , ADDR +Int 7 , 1 ) , 1 ) , ADDR +Int 1 , #getRange ( BM , ADDR +Int 6 , 1 ) , 1 ) , ADDR +Int 2 , #getRange ( BM , ADDR +Int 5 , 1 ) , 1 ) , ADDR +Int 3 , #getRange ( BM , ADDR +Int 4 , 1 ) , 1 ) , ADDR +Int 4 , #getRange ( BM , ADDR +Int 3 , 1 ) , 1 ) , ADDR +Int 5 , #getRange ( BM , ADDR +Int 2 , 1 ) , 1 ) , ADDR +Int 6 , #getRange ( BM , ADDR +Int 1 , 1 ) , 1 ) , ADDR +Int 7 , #getRange ( BM , ADDR , 1 ) , 1 ) , ADDR +Int 3 , 1 ) )
+ => done ( #getRange ( BM , ADDR +Int 4 , 1 ) )
+ ...
+
+ requires 0 <=Int ADDR
+
+endmodule
diff --git a/docs/runtimeverification-wasm-semantics/tests/proofs/locals-spec.k b/docs/runtimeverification-wasm-semantics/tests/proofs/locals-spec.k
new file mode 100644
index 000000000..b4afe22eb
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/proofs/locals-spec.k
@@ -0,0 +1,10 @@
+requires "kwasm-lemmas.md"
+
+module LOCALS-SPEC
+ imports KWASM-LEMMAS
+
+ claim #local.get(X) ~> #local.set(X) => . ...
+
+ X |-> < _ITYPE > (VAL => VAL)
+
+endmodule
diff --git a/docs/runtimeverification-wasm-semantics/tests/proofs/loops-spec.k b/docs/runtimeverification-wasm-semantics/tests/proofs/loops-spec.k
new file mode 100644
index 000000000..6f62a7a05
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/proofs/loops-spec.k
@@ -0,0 +1,70 @@
+requires "kwasm-lemmas.md"
+
+module LOOPS-SPEC
+ imports KWASM-LEMMAS
+
+ // Lemma
+ claim #br(0)
+ ~> label // Loop label.
+ [ .ValTypes ]
+ { #loop([ .ValTypes ],
+ #local.get(0)
+ #local.get(1)
+ ITYPE.add
+ #local.set(1)
+ #local.get(0)
+ ITYPE.const 1
+ ITYPE.sub
+ #local.tee(0)
+ ITYPE.eqz
+ #br_if(1)
+ #br(0),
+ _
+ )
+ }
+ .ValStack
+ ~> label [ .ValTypes ] {.Instrs } STACK // Block label.
+ => .
+ ...
+
+ _ => STACK
+
+ 0 |-> < ITYPE > (I => 0)
+ 1 |-> < ITYPE > (X => X +Int ((I *Int (I +Int 1)) /Int 2))
+
+ requires #inUnsignedRange(ITYPE, I)
+ andBool I >Int 0
+ andBool #inUnsignedRange(ITYPE, X +Int I)
+ andBool #inUnsignedRange(ITYPE, X +Int ((I *Int (I +Int 1)) /Int 2))
+
+ // Main claim.
+ claim
+ #block([ .ValTypes ],
+ #loop([ .ValTypes],
+ #local.get(0)
+ #local.get(1)
+ ITYPE.add
+ #local.set(1)
+ #local.get(0)
+ ITYPE.const 1
+ ITYPE.sub
+ #local.tee(0)
+ ITYPE.eqz
+ #br_if(1)
+ #br(0),
+ _
+ ),
+ _
+ )
+ => .
+ ...
+
+
+ 0 |-> < ITYPE > (N => 0)
+ 1 |-> < ITYPE > (0 => (N *Int (N +Int 1)) /Int 2)
+
+ requires #inUnsignedRange(ITYPE, N)
+ andBool N >Int 0
+ andBool #inUnsignedRange(ITYPE, ((N *Int (N +Int 1)) /Int 2))
+
+endmodule
diff --git a/docs/runtimeverification-wasm-semantics/tests/proofs/memory-spec.k b/docs/runtimeverification-wasm-semantics/tests/proofs/memory-spec.k
new file mode 100644
index 000000000..1c8d93beb
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/proofs/memory-spec.k
@@ -0,0 +1,38 @@
+requires "kwasm-lemmas.md"
+
+module MEMORY-SPEC
+ imports KWASM-LEMMAS
+
+ claim i32.const ADDR ~> i32.const ADDR ~> #load(i64, load32_u, 0) ~> #store(i64, store16, 0) => . ...
+ CUR
+
+ CUR
+ 0 |-> MEMADDR
+ ...
+
+
+ MEMADDR
+ SIZE
+ _BM
+ ...
+
+ requires
+ ADDR +Int #numBytes(i64) <=Int SIZE *Int #pageSize()
+ andBool #inUnsignedRange(i32, ADDR)
+
+ claim i32.const ADDR ~> i32.const ADDR ~> #load(ITYPE:IValType, load, 0) ~> #store(ITYPE, store, 0) => . ...
+ CUR
+
+ CUR
+ 0 |-> MEMADDR
+ ...
+
+
+ MEMADDR
+ SIZE
+ _BM
+ ...
+
+ requires
+ #get(#chop( ADDR)) +Int #numBytes(ITYPE) <=Int SIZE *Int #pageSize()
+endmodule
diff --git a/docs/runtimeverification-wasm-semantics/tests/proofs/simple-arithmetic-spec.k b/docs/runtimeverification-wasm-semantics/tests/proofs/simple-arithmetic-spec.k
new file mode 100644
index 000000000..0c2ad2fef
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/proofs/simple-arithmetic-spec.k
@@ -0,0 +1,18 @@
+requires "kwasm-lemmas.md"
+
+module SIMPLE-ARITHMETIC-SPEC
+ imports KWASM-LEMMAS
+
+ claim ITYPE:IValType . const X:Int => . ...
+ S:ValStack => < ITYPE > X : S
+ requires #inUnsignedRange(ITYPE, X)
+
+ claim ITYPE:IValType . const X:Int => . ...
+ S:ValStack => < ITYPE > (X +Int #pow(ITYPE)) : S
+ requires (#minSigned(ITYPE) <=Int X) andBool (X ITYPE:IValType . const X:Int ~> ITYPE . const Y:Int ~> ITYPE . add => . ...
+ S:ValStack => < ITYPE > (X +Int Y) : S
+ requires 0 <=Int X andBool 0 <=Int Y
+ andBool (X +Int Y) sequenceDefns(#t2aDefns<#freshCtx()>(#wrc20ReverseBytes)) // TODO: Have this pre-loaded in the store.
+ ~> i32.const ADDR
+ ~> i32.const ADDR
+ ~> #load(i64, load, 0)
+ ~> (invoke NEXTADDR) // TODO: Use `call`.
+ ~> #store(i64, store, 0)
+ => .
+ ...
+
+ CUR
+
+ CUR
+ #wrc20ReverseBytesTypeIdx |-> #wrc20ReverseBytesType
+ 0 |-> MEMADDR
+ _ => ?_
+ NEXTFUNCIDX => NEXTFUNCIDX +Int 1
+ ...
+
+ .Bag => ?_
+ NEXTADDR => NEXTADDR +Int 1
+
+ MEMADDR
+ SIZE
+ BM => ?BM'
+ ...
+
+ // TODO: Make function out of this tricky side condition.
+ requires ADDR +Int #numBytes(i64) <=Int SIZE *Int #pageSize()
+ andBool #inUnsignedRange(i32, ADDR)
+ ensures #getRange(BM, ADDR +Int 0, 1) ==Int #getRange(?BM', ADDR +Int 7, 1)
+ andBool #getRange(BM, ADDR +Int 1, 1) ==Int #getRange(?BM', ADDR +Int 6, 1)
+ andBool #getRange(BM, ADDR +Int 2, 1) ==Int #getRange(?BM', ADDR +Int 5, 1)
+ andBool #getRange(BM, ADDR +Int 3, 1) ==Int #getRange(?BM', ADDR +Int 4, 1)
+ andBool #getRange(BM, ADDR +Int 4, 1) ==Int #getRange(?BM', ADDR +Int 3, 1)
+ andBool #getRange(BM, ADDR +Int 5, 1) ==Int #getRange(?BM', ADDR +Int 2, 1)
+ andBool #getRange(BM, ADDR +Int 6, 1) ==Int #getRange(?BM', ADDR +Int 1, 1)
+ andBool #getRange(BM, ADDR +Int 7, 1) ==Int #getRange(?BM', ADDR +Int 0, 1)
+
+endmodule
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/address-c.wast b/docs/runtimeverification-wasm-semantics/tests/simple/address-c.wast
new file mode 100644
index 000000000..ca37275cf
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/address-c.wast
@@ -0,0 +1,591 @@
+;; Load i32 data with different offset/align arguments
+
+(module
+ (memory 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "8u_good1") (param $i i32) (result i32)
+ (i32.load8_u offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good2") (param $i i32) (result i32)
+ (i32.load8_u align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good3") (param $i i32) (result i32)
+ (i32.load8_u offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8u_good4") (param $i i32) (result i32)
+ (i32.load8_u offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8u_good5") (param $i i32) (result i32)
+ (i32.load8_u offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "8s_good1") (param $i i32) (result i32)
+ (i32.load8_s offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good2") (param $i i32) (result i32)
+ (i32.load8_s align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good3") (param $i i32) (result i32)
+ (i32.load8_s offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8s_good4") (param $i i32) (result i32)
+ (i32.load8_s offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8s_good5") (param $i i32) (result i32)
+ (i32.load8_s offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "16u_good1") (param $i i32) (result i32)
+ (i32.load16_u offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good2") (param $i i32) (result i32)
+ (i32.load16_u align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good3") (param $i i32) (result i32)
+ (i32.load16_u offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16u_good4") (param $i i32) (result i32)
+ (i32.load16_u offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16u_good5") (param $i i32) (result i32)
+ (i32.load16_u offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "16s_good1") (param $i i32) (result i32)
+ (i32.load16_s offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good2") (param $i i32) (result i32)
+ (i32.load16_s align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good3") (param $i i32) (result i32)
+ (i32.load16_s offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16s_good4") (param $i i32) (result i32)
+ (i32.load16_s offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16s_good5") (param $i i32) (result i32)
+ (i32.load16_s offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "32_good1") (param $i i32) (result i32)
+ (i32.load offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32_good2") (param $i i32) (result i32)
+ (i32.load align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32_good3") (param $i i32) (result i32)
+ (i32.load offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32_good4") (param $i i32) (result i32)
+ (i32.load offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32_good5") (param $i i32) (result i32)
+ (i32.load offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "8u_bad") (param $i i32)
+ (drop (i32.load8_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "8s_bad") (param $i i32)
+ (drop (i32.load8_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "16u_bad") (param $i i32)
+ (drop (i32.load16_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "16s_bad") (param $i i32)
+ (drop (i32.load16_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "32_bad") (param $i i32)
+ (drop (i32.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "8u_good1" (i32.const 0)) (i32.const 97))
+(assert_return (invoke "8u_good2" (i32.const 0)) (i32.const 97))
+(assert_return (invoke "8u_good3" (i32.const 0)) (i32.const 98))
+(assert_return (invoke "8u_good4" (i32.const 0)) (i32.const 99))
+(assert_return (invoke "8u_good5" (i32.const 0)) (i32.const 122))
+
+(assert_return (invoke "8s_good1" (i32.const 0)) (i32.const 97))
+(assert_return (invoke "8s_good2" (i32.const 0)) (i32.const 97))
+(assert_return (invoke "8s_good3" (i32.const 0)) (i32.const 98))
+(assert_return (invoke "8s_good4" (i32.const 0)) (i32.const 99))
+(assert_return (invoke "8s_good5" (i32.const 0)) (i32.const 122))
+
+(assert_return (invoke "16u_good1" (i32.const 0)) (i32.const 25185))
+(assert_return (invoke "16u_good2" (i32.const 0)) (i32.const 25185))
+(assert_return (invoke "16u_good3" (i32.const 0)) (i32.const 25442))
+(assert_return (invoke "16u_good4" (i32.const 0)) (i32.const 25699))
+(assert_return (invoke "16u_good5" (i32.const 0)) (i32.const 122))
+
+(assert_return (invoke "16s_good1" (i32.const 0)) (i32.const 25185))
+(assert_return (invoke "16s_good2" (i32.const 0)) (i32.const 25185))
+(assert_return (invoke "16s_good3" (i32.const 0)) (i32.const 25442))
+(assert_return (invoke "16s_good4" (i32.const 0)) (i32.const 25699))
+(assert_return (invoke "16s_good5" (i32.const 0)) (i32.const 122))
+
+(assert_return (invoke "32_good1" (i32.const 0)) (i32.const 1684234849))
+(assert_return (invoke "32_good2" (i32.const 0)) (i32.const 1684234849))
+(assert_return (invoke "32_good3" (i32.const 0)) (i32.const 1701077858))
+(assert_return (invoke "32_good4" (i32.const 0)) (i32.const 1717920867))
+(assert_return (invoke "32_good5" (i32.const 0)) (i32.const 122))
+
+(assert_return (invoke "8u_good1" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good2" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good3" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good4" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8u_good5" (i32.const 65507)) (i32.const 0))
+
+(assert_return (invoke "8s_good1" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good2" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good3" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good4" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "8s_good5" (i32.const 65507)) (i32.const 0))
+
+(assert_return (invoke "16u_good1" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good2" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good3" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good4" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16u_good5" (i32.const 65507)) (i32.const 0))
+
+(assert_return (invoke "16s_good1" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good2" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good3" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good4" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "16s_good5" (i32.const 65507)) (i32.const 0))
+
+(assert_return (invoke "32_good1" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good2" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good3" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good4" (i32.const 65507)) (i32.const 0))
+(assert_return (invoke "32_good5" (i32.const 65507)) (i32.const 0))
+
+(assert_return (invoke "8u_good1" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good2" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good3" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good4" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8u_good5" (i32.const 65508)) (i32.const 0))
+
+(assert_return (invoke "8s_good1" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good2" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good3" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good4" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "8s_good5" (i32.const 65508)) (i32.const 0))
+
+(assert_return (invoke "16u_good1" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good2" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good3" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good4" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16u_good5" (i32.const 65508)) (i32.const 0))
+
+(assert_return (invoke "16s_good1" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good2" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good3" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good4" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "16s_good5" (i32.const 65508)) (i32.const 0))
+
+(assert_return (invoke "32_good1" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good2" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good3" (i32.const 65508)) (i32.const 0))
+(assert_return (invoke "32_good4" (i32.const 65508)) (i32.const 0))
+(assert_trap (invoke "32_good5" (i32.const 65508)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i32.const 0)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "32_bad" (i32.const 1)) "out of bounds memory access")
+
+(assert_malformed
+ (module quote
+ "(memory 1)"
+ "(func (drop (i32.load offset=4294967296 (i32.const 0))))"
+ )
+ "i32 constant"
+)
+
+;; Load i64 data with different offset/align arguments
+
+(module
+ (memory 1)
+ (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz")
+
+ (func (export "8u_good1") (param $i i32) (result i64)
+ (i64.load8_u offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good2") (param $i i32) (result i64)
+ (i64.load8_u align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8u_good3") (param $i i32) (result i64)
+ (i64.load8_u offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8u_good4") (param $i i32) (result i64)
+ (i64.load8_u offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8u_good5") (param $i i32) (result i64)
+ (i64.load8_u offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "8s_good1") (param $i i32) (result i64)
+ (i64.load8_s offset=0 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good2") (param $i i32) (result i64)
+ (i64.load8_s align=1 (local.get $i)) ;; 97 'a'
+ )
+ (func (export "8s_good3") (param $i i32) (result i64)
+ (i64.load8_s offset=1 align=1 (local.get $i)) ;; 98 'b'
+ )
+ (func (export "8s_good4") (param $i i32) (result i64)
+ (i64.load8_s offset=2 align=1 (local.get $i)) ;; 99 'c'
+ )
+ (func (export "8s_good5") (param $i i32) (result i64)
+ (i64.load8_s offset=25 align=1 (local.get $i)) ;; 122 'z'
+ )
+
+ (func (export "16u_good1") (param $i i32) (result i64)
+ (i64.load16_u offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good2") (param $i i32) (result i64)
+ (i64.load16_u align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16u_good3") (param $i i32) (result i64)
+ (i64.load16_u offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16u_good4") (param $i i32) (result i64)
+ (i64.load16_u offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16u_good5") (param $i i32) (result i64)
+ (i64.load16_u offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "16s_good1") (param $i i32) (result i64)
+ (i64.load16_s offset=0 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good2") (param $i i32) (result i64)
+ (i64.load16_s align=1 (local.get $i)) ;; 25185 'ab'
+ )
+ (func (export "16s_good3") (param $i i32) (result i64)
+ (i64.load16_s offset=1 align=1 (local.get $i)) ;; 25442 'bc'
+ )
+ (func (export "16s_good4") (param $i i32) (result i64)
+ (i64.load16_s offset=2 align=2 (local.get $i)) ;; 25699 'cd'
+ )
+ (func (export "16s_good5") (param $i i32) (result i64)
+ (i64.load16_s offset=25 align=2 (local.get $i)) ;; 122 'z\0'
+ )
+
+ (func (export "32u_good1") (param $i i32) (result i64)
+ (i64.load32_u offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32u_good2") (param $i i32) (result i64)
+ (i64.load32_u align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32u_good3") (param $i i32) (result i64)
+ (i64.load32_u offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32u_good4") (param $i i32) (result i64)
+ (i64.load32_u offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32u_good5") (param $i i32) (result i64)
+ (i64.load32_u offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "32s_good1") (param $i i32) (result i64)
+ (i64.load32_s offset=0 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32s_good2") (param $i i32) (result i64)
+ (i64.load32_s align=1 (local.get $i)) ;; 1684234849 'abcd'
+ )
+ (func (export "32s_good3") (param $i i32) (result i64)
+ (i64.load32_s offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde'
+ )
+ (func (export "32s_good4") (param $i i32) (result i64)
+ (i64.load32_s offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef'
+ )
+ (func (export "32s_good5") (param $i i32) (result i64)
+ (i64.load32_s offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0'
+ )
+
+ (func (export "64_good1") (param $i i32) (result i64)
+ (i64.load offset=0 (local.get $i)) ;; 0x6867666564636261 'abcdefgh'
+ )
+ (func (export "64_good2") (param $i i32) (result i64)
+ (i64.load align=1 (local.get $i)) ;; 0x6867666564636261 'abcdefgh'
+ )
+ (func (export "64_good3") (param $i i32) (result i64)
+ (i64.load offset=1 align=1 (local.get $i)) ;; 0x6968676665646362 'bcdefghi'
+ )
+ (func (export "64_good4") (param $i i32) (result i64)
+ (i64.load offset=2 align=2 (local.get $i)) ;; 0x6a69686766656463 'cdefghij'
+ )
+ (func (export "64_good5") (param $i i32) (result i64)
+ (i64.load offset=25 align=8 (local.get $i)) ;; 122 'z\0\0\0\0\0\0\0'
+ )
+
+ (func (export "8u_bad") (param $i i32)
+ (drop (i64.load8_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "8s_bad") (param $i i32)
+ (drop (i64.load8_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "16u_bad") (param $i i32)
+ (drop (i64.load16_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "16s_bad") (param $i i32)
+ (drop (i64.load16_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "32u_bad") (param $i i32)
+ (drop (i64.load32_u offset=4294967295 (local.get $i)))
+ )
+ (func (export "32s_bad") (param $i i32)
+ (drop (i64.load32_s offset=4294967295 (local.get $i)))
+ )
+ (func (export "64_bad") (param $i i32)
+ (drop (i64.load offset=4294967295 (local.get $i)))
+ )
+)
+
+(assert_return (invoke "8u_good1" (i32.const 0)) (i64.const 97))
+(assert_return (invoke "8u_good2" (i32.const 0)) (i64.const 97))
+(assert_return (invoke "8u_good3" (i32.const 0)) (i64.const 98))
+(assert_return (invoke "8u_good4" (i32.const 0)) (i64.const 99))
+(assert_return (invoke "8u_good5" (i32.const 0)) (i64.const 122))
+
+(assert_return (invoke "8s_good1" (i32.const 0)) (i64.const 97))
+(assert_return (invoke "8s_good2" (i32.const 0)) (i64.const 97))
+(assert_return (invoke "8s_good3" (i32.const 0)) (i64.const 98))
+(assert_return (invoke "8s_good4" (i32.const 0)) (i64.const 99))
+(assert_return (invoke "8s_good5" (i32.const 0)) (i64.const 122))
+
+(assert_return (invoke "16u_good1" (i32.const 0)) (i64.const 25185))
+(assert_return (invoke "16u_good2" (i32.const 0)) (i64.const 25185))
+(assert_return (invoke "16u_good3" (i32.const 0)) (i64.const 25442))
+(assert_return (invoke "16u_good4" (i32.const 0)) (i64.const 25699))
+(assert_return (invoke "16u_good5" (i32.const 0)) (i64.const 122))
+
+(assert_return (invoke "16s_good1" (i32.const 0)) (i64.const 25185))
+(assert_return (invoke "16s_good2" (i32.const 0)) (i64.const 25185))
+(assert_return (invoke "16s_good3" (i32.const 0)) (i64.const 25442))
+(assert_return (invoke "16s_good4" (i32.const 0)) (i64.const 25699))
+(assert_return (invoke "16s_good5" (i32.const 0)) (i64.const 122))
+
+(assert_return (invoke "32u_good1" (i32.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32u_good2" (i32.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32u_good3" (i32.const 0)) (i64.const 1701077858))
+(assert_return (invoke "32u_good4" (i32.const 0)) (i64.const 1717920867))
+(assert_return (invoke "32u_good5" (i32.const 0)) (i64.const 122))
+
+(assert_return (invoke "32s_good1" (i32.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32s_good2" (i32.const 0)) (i64.const 1684234849))
+(assert_return (invoke "32s_good3" (i32.const 0)) (i64.const 1701077858))
+(assert_return (invoke "32s_good4" (i32.const 0)) (i64.const 1717920867))
+(assert_return (invoke "32s_good5" (i32.const 0)) (i64.const 122))
+
+(assert_return (invoke "64_good1" (i32.const 0)) (i64.const 0x6867666564636261))
+(assert_return (invoke "64_good2" (i32.const 0)) (i64.const 0x6867666564636261))
+(assert_return (invoke "64_good3" (i32.const 0)) (i64.const 0x6968676665646362))
+(assert_return (invoke "64_good4" (i32.const 0)) (i64.const 0x6a69686766656463))
+(assert_return (invoke "64_good5" (i32.const 0)) (i64.const 122))
+
+(assert_return (invoke "8u_good1" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good2" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good3" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good4" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8u_good5" (i32.const 65503)) (i64.const 0))
+
+(assert_return (invoke "8s_good1" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good2" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good3" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good4" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "8s_good5" (i32.const 65503)) (i64.const 0))
+
+(assert_return (invoke "16u_good1" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good2" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good3" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good4" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16u_good5" (i32.const 65503)) (i64.const 0))
+
+(assert_return (invoke "16s_good1" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good2" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good3" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good4" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "16s_good5" (i32.const 65503)) (i64.const 0))
+
+(assert_return (invoke "32u_good1" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good2" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good3" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good4" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32u_good5" (i32.const 65503)) (i64.const 0))
+
+(assert_return (invoke "32s_good1" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good2" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good3" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good4" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "32s_good5" (i32.const 65503)) (i64.const 0))
+
+(assert_return (invoke "64_good1" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good2" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good3" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good4" (i32.const 65503)) (i64.const 0))
+(assert_return (invoke "64_good5" (i32.const 65503)) (i64.const 0))
+
+(assert_return (invoke "8u_good1" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good2" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good3" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good4" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8u_good5" (i32.const 65504)) (i64.const 0))
+
+(assert_return (invoke "8s_good1" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good2" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good3" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good4" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "8s_good5" (i32.const 65504)) (i64.const 0))
+
+(assert_return (invoke "16u_good1" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good2" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good3" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good4" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16u_good5" (i32.const 65504)) (i64.const 0))
+
+(assert_return (invoke "16s_good1" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good2" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good3" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good4" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "16s_good5" (i32.const 65504)) (i64.const 0))
+
+(assert_return (invoke "32u_good1" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good2" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good3" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good4" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32u_good5" (i32.const 65504)) (i64.const 0))
+
+(assert_return (invoke "32s_good1" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good2" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good3" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good4" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "32s_good5" (i32.const 65504)) (i64.const 0))
+
+(assert_return (invoke "64_good1" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good2" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good3" (i32.const 65504)) (i64.const 0))
+(assert_return (invoke "64_good4" (i32.const 65504)) (i64.const 0))
+(assert_trap (invoke "64_good5" (i32.const 65504)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32u_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32s_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i32.const 0)) "out of bounds memory access")
+
+(assert_trap (invoke "8u_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "8s_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16u_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "16s_bad" (i32.const 1)) "out of bounds memory access")
+(assert_trap (invoke "32u_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "32s_bad" (i32.const 0)) "out of bounds memory access")
+(assert_trap (invoke "64_bad" (i32.const 1)) "out of bounds memory access")
+
+;; Load f32 data with different offset/align arguments
+
+;; (module
+;; (memory 1)
+;; (data (i32.const 0) "\00\00\00\00\00\00\a0\7f\01\00\d0\7f")
+
+;; (func (export "32_good1") (param $i i32) (result f32)
+;; (f32.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00'
+;; )
+;; (func (export "32_good2") (param $i i32) (result f32)
+;; (f32.load align=1 (local.get $i)) ;; 0.0 '\00\00\00\00'
+;; )
+;; (func (export "32_good3") (param $i i32) (result f32)
+;; (f32.load offset=1 align=1 (local.get $i)) ;; 0.0 '\00\00\00\00'
+;; )
+;; (func (export "32_good4") (param $i i32) (result f32)
+;; (f32.load offset=2 align=2 (local.get $i)) ;; 0.0 '\00\00\00\00'
+;; )
+;; (func (export "32_good5") (param $i i32) (result f32)
+;; (f32.load offset=8 align=4 (local.get $i)) ;; nan:0x500001 '\01\00\d0\7f'
+;; )
+;; (func (export "32_bad") (param $i i32)
+;; (drop (f32.load offset=4294967295 (local.get $i)))
+;; )
+;; )
+
+;; (assert_return (invoke "32_good1" (i32.const 0)) (f32.const 0.0))
+;; (assert_return (invoke "32_good2" (i32.const 0)) (f32.const 0.0))
+;; (assert_return (invoke "32_good3" (i32.const 0)) (f32.const 0.0))
+;; (assert_return (invoke "32_good4" (i32.const 0)) (f32.const 0.0))
+;; (assert_return (invoke "32_good5" (i32.const 0)) (f32.const nan:0x500001))
+
+;; (assert_return (invoke "32_good1" (i32.const 65524)) (f32.const 0.0))
+;; (assert_return (invoke "32_good2" (i32.const 65524)) (f32.const 0.0))
+;; (assert_return (invoke "32_good3" (i32.const 65524)) (f32.const 0.0))
+;; (assert_return (invoke "32_good4" (i32.const 65524)) (f32.const 0.0))
+;; (assert_return (invoke "32_good5" (i32.const 65524)) (f32.const 0.0))
+
+;; (assert_return (invoke "32_good1" (i32.const 65525)) (f32.const 0.0))
+;; (assert_return (invoke "32_good2" (i32.const 65525)) (f32.const 0.0))
+;; (assert_return (invoke "32_good3" (i32.const 65525)) (f32.const 0.0))
+;; (assert_return (invoke "32_good4" (i32.const 65525)) (f32.const 0.0))
+;; (assert_trap (invoke "32_good5" (i32.const 65525)) "out of bounds memory access")
+
+;; (assert_trap (invoke "32_bad" (i32.const 0)) "out of bounds memory access")
+;; (assert_trap (invoke "32_bad" (i32.const 1)) "out of bounds memory access")
+
+;; ;; Load f64 data with different offset/align arguments
+
+;; (module
+;; (memory 1)
+;; (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\f4\7f\01\00\00\00\00\00\fc\7f")
+
+;; (func (export "64_good1") (param $i i32) (result f64)
+;; (f64.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+;; )
+;; (func (export "64_good2") (param $i i32) (result f64)
+;; (f64.load align=1 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+;; )
+;; (func (export "64_good3") (param $i i32) (result f64)
+;; (f64.load offset=1 align=1 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+;; )
+;; (func (export "64_good4") (param $i i32) (result f64)
+;; (f64.load offset=2 align=2 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00'
+;; )
+;; (func (export "64_good5") (param $i i32) (result f64)
+;; (f64.load offset=18 align=8 (local.get $i)) ;; nan:0xc000000000001 '\01\00\00\00\00\00\fc\7f'
+;; )
+;; (func (export "64_bad") (param $i i32)
+;; (drop (f64.load offset=4294967295 (local.get $i)))
+;; )
+;; )
+
+;; (assert_return (invoke "64_good1" (i32.const 0)) (f64.const 0.0))
+;; (assert_return (invoke "64_good2" (i32.const 0)) (f64.const 0.0))
+;; (assert_return (invoke "64_good3" (i32.const 0)) (f64.const 0.0))
+;; (assert_return (invoke "64_good4" (i32.const 0)) (f64.const 0.0))
+;; (assert_return (invoke "64_good5" (i32.const 0)) (f64.const nan:0xc000000000001))
+
+;; (assert_return (invoke "64_good1" (i32.const 65510)) (f64.const 0.0))
+;; (assert_return (invoke "64_good2" (i32.const 65510)) (f64.const 0.0))
+;; (assert_return (invoke "64_good3" (i32.const 65510)) (f64.const 0.0))
+;; (assert_return (invoke "64_good4" (i32.const 65510)) (f64.const 0.0))
+;; (assert_return (invoke "64_good5" (i32.const 65510)) (f64.const 0.0))
+
+;; (assert_return (invoke "64_good1" (i32.const 65511)) (f64.const 0.0))
+;; (assert_return (invoke "64_good2" (i32.const 65511)) (f64.const 0.0))
+;; (assert_return (invoke "64_good3" (i32.const 65511)) (f64.const 0.0))
+;; (assert_return (invoke "64_good4" (i32.const 65511)) (f64.const 0.0))
+;; (assert_trap (invoke "64_good5" (i32.const 65511)) "out of bounds memory access")
+
+;; (assert_trap (invoke "64_bad" (i32.const 0)) "out of bounds memory access")
+;; (assert_trap (invoke "64_bad" (i32.const 1)) "out of bounds memory access")
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/arithmetic.wast b/docs/runtimeverification-wasm-semantics/tests/simple/arithmetic.wast
new file mode 100644
index 000000000..e51fd81f3
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/arithmetic.wast
@@ -0,0 +1,182 @@
+(i32.const 5)
+(i32.const 7)
+(i32.add)
+#assertTopStack < i32 > 12 "add"
+
+(i32.const 5)
+(i32.const 7)
+(i32.sub)
+#assertTopStack < i32 > -2 "sub"
+
+(i32.const 15)
+(i32.const 3)
+(i32.mul)
+#assertTopStack < i32 > 45 "mul"
+
+(i32.const 15)
+(i32.const 3)
+(i32.div_u)
+#assertTopStack < i32 > 5 "div_u1"
+
+(i32.const 15)
+(i32.const 2)
+(i32.div_u)
+#assertTopStack < i32 > 7 "div_u2"
+
+(i32.const 15)
+(i32.const 0)
+(i32.div_u)
+#assertTrap "div_u3"
+
+(i32.const 15)
+(i32.const 3)
+(i32.rem_u)
+#assertTopStack < i32 > 0 "rem_u1"
+
+(i32.const 15)
+(i32.const 2)
+(i32.rem_u)
+#assertTopStack < i32 > 1 "rem_u2"
+
+(i32.const 15)
+(i32.const 0)
+(i32.rem_u)
+#assertTrap "rem_u3"
+
+(i32.const 10)
+(i32.const 3)
+(i32.div_s)
+#assertTopStack < i32 > 3 "i32.div_s 1"
+
+(i32.const 10)
+(i32.const 4)
+(i32.div_s)
+#assertTopStack < i32 > 2 "i32.div_s 2"
+
+(i32.const 10)
+(i32.const 0)
+(i32.div_s)
+#assertTrap "i32.div_s 3"
+
+(i32.const #pow1(i32))
+(i32.const #pow(i32) -Int 1)
+(i32.div_s)
+#assertTrap "i32.div_s 4"
+
+(i32.const 10)
+(i32.const 5)
+(i32.div_s)
+#assertTopStack < i32 > 2 "div_s"
+
+(i32.const 91)
+(i32.const 13)
+(i32.rem_s)
+#assertTopStack 0 "rem_s"
+
+(i32.const -91)
+(i32.const -13)
+(i32.rem_s)
+#assertTopStack 0 "rem_s"
+
+(i32.const -1)
+(i32.const -3)
+(i32.rem_s)
+#assertTopStack -1 "rem_s"
+
+(i32.const 10)
+(i32.const 0)
+(i32.rem_s)
+#assertTrap "rem_s"
+
+(i32.const #pow1(i32))
+(i32.const #pow(i32) -Int 1)
+(i32.rem_s)
+#assertTopStack 0 "rem_s edge case"
+
+;; The following tests were generated using the reference OCaml WASM interpreter.
+
+(i32.const 10)
+(i32.const 3)
+(i32.rem_s)
+#assertTopStack < i32 > 1 "i32.rem_s 1"
+
+(i32.const 10)
+(i32.const 4)
+(i32.rem_s)
+#assertTopStack < i32 > 2 "i32.rem_s 2"
+
+(i32.const 10)
+(i32.const 5)
+(i32.rem_s)
+#assertTopStack < i32 > 0 "i32.rem_s 3"
+
+(i32.const -10)
+(i32.const 3)
+(i32.div_s)
+#assertTopStack < i32 > -3 "i32.div_s 3"
+
+(i32.const -10)
+(i32.const 4)
+(i32.div_s)
+#assertTopStack < i32 > -2 "i32.div_s 4"
+
+(i32.const -10)
+(i32.const 5)
+(i32.div_s)
+#assertTopStack < i32 > -2 "i32.div_s 5"
+
+(i32.const -10)
+(i32.const 3)
+(i32.rem_s)
+#assertTopStack < i32 > -1 "i32.rem_s 4"
+
+(i32.const -10)
+(i32.const 4)
+(i32.rem_s)
+#assertTopStack < i32 > -2 "i32.rem_s 5"
+
+(i32.const -10)
+(i32.const 5)
+(i32.rem_s)
+#assertTopStack < i32 > 0 "i32.rem_s 6"
+
+(i32.const -10)
+(i32.const -3)
+(i32.div_s)
+#assertTopStack < i32 > 3 "i32.div_s 6"
+
+(i32.const -10)
+(i32.const -4)
+(i32.div_s)
+#assertTopStack < i32 > 2 "i32.div_s 7"
+
+(i32.const -10)
+(i32.const -5)
+(i32.div_s)
+#assertTopStack < i32 > 2 "i32.div_s 8"
+
+(i32.const -10)
+(i32.const -3)
+(i32.rem_s)
+#assertTopStack < i32 > -1 "i32.rem_s 7"
+
+(i32.const -10)
+(i32.const -4)
+(i32.rem_s)
+#assertTopStack < i32 > -2 "i32.rem_s 8"
+
+(i32.const -10)
+(i32.const -5)
+(i32.rem_s)
+#assertTopStack < i32 > 0 "i32.rem_s 9"
+
+(i32.add (i32.const 3) (i32.const 4))
+#assertTopStack < i32 > 7 "simple add folded"
+
+(i32.sub (i32.const 3) (i32.const 4))
+#assertTopStack < i32 > -1 "simple sub, order dependent folded"
+
+(i32.sub (i32.mul (i32.const 5) (i32.const 7)) (i32.const 4))
+#assertTopStack < i32 > 31 "mul nested in sub folded"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/bitwise.wast b/docs/runtimeverification-wasm-semantics/tests/simple/bitwise.wast
new file mode 100644
index 000000000..0791e6676
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/bitwise.wast
@@ -0,0 +1,152 @@
+(i32.const 20)
+(i32.const 18)
+(i32.and)
+#assertTopStack < i32 > 16 "and"
+
+(i32.const 20)
+(i32.const 18)
+(i32.or)
+#assertTopStack < i32 > 22 "or"
+
+(i32.const 20)
+(i32.const 18)
+(i32.xor)
+#assertTopStack < i32 > 6 "xor"
+
+(i32.const 2)
+(i32.const 1)
+(i32.shl)
+#assertTopStack < i32 > 4 "shl 1"
+
+(i32.const 2)
+(i32.const #pow1(i32) +Int 1)
+(i32.shl)
+#assertTopStack < i32 > 4 "shl 2"
+
+(i32.const #pow1(i32))
+(i32.const 2)
+(i32.shr_u)
+#assertTopStack < i32 > 2 ^Int 29 "shr_u 1"
+
+(i32.const 2)
+(i32.const 2)
+(i32.shr_u)
+#assertTopStack < i32 > 0 "shr_u 2"
+
+(i32.const #pow(i32) -Int 2)
+(i32.const 1)
+(i32.shr_s)
+#assertTopStack < i32 > #pow(i32) -Int 1 "shr_s 1"
+
+(i32.const 2)
+(i32.const 2)
+(i32.shr_s)
+#assertTopStack < i32 > 0 "shr_s 2"
+
+(i32.const #pow1(i32) +Int 2)
+(i32.const 3)
+(i32.rotl)
+#assertTopStack < i32 > 20 "rotl"
+
+(i32.const #pow1(i32) +Int 16)
+(i32.const 3)
+(i32.rotr)
+#assertTopStack < i32 > 2 ^Int 28 +Int 2 "rotr"
+
+;; clz
+
+(i32.const #pow1(i32))
+(i32.clz)
+#assertTopStack < i32 > 0 "clz #pow1(i32)"
+(i64.const #pow1(i64))
+(i64.clz)
+#assertTopStack < i64 > 0 "clz #pow1(i62)"
+
+(i32.const 0)
+(i32.clz)
+#assertTopStack < i32 > 32 "clz 0"
+(i64.const 0)
+(i64.clz)
+#assertTopStack < i64 > 64 "clz 0"
+
+(i32.const 1)
+(i32.clz)
+#assertTopStack < i32 > 31 "clz 1"
+(i64.const 1)
+(i64.clz)
+#assertTopStack < i64 > 63 "clz 1"
+
+(i32.const 2 ^Int 32 -Int 1)
+(i32.clz)
+#assertTopStack < i32 > 0 "clz 2^32 - 1"
+(i64.const 2 ^Int 64 -Int 1)
+(i64.clz)
+#assertTopStack < i64 > 0 "clz 2^64 - 1"
+
+(i32.const 2 ^Int 31 -Int 1)
+(i32.clz)
+#assertTopStack < i32 > 1 "clz 2^31 - 1"
+(i64.const 2 ^Int 63 -Int 1)
+(i64.clz)
+#assertTopStack < i64 > 1 "clz 2^63 - 1"
+
+;; ctz
+(i32.const #pow1(i32))
+(i32.ctz)
+#assertTopStack < i32 > 31 "ctz #pow1(i32)"
+(i64.const #pow1(i64))
+(i64.ctz)
+#assertTopStack < i64 > 63 "ctz #pow1(i32)"
+
+(i32.const 0)
+(i32.ctz)
+#assertTopStack < i32 > 32 "ctz 0"
+(i64.const 0)
+(i64.ctz)
+#assertTopStack < i64 > 64 "ctz 0"
+
+(i32.const 1)
+(i32.ctz)
+#assertTopStack < i32 > 0 "ctz 1"
+(i64.const 1)
+(i64.ctz)
+#assertTopStack < i64 > 0 "ctz 1"
+
+(i32.const 2 ^Int 32 -Int 1)
+(i32.ctz)
+#assertTopStack < i32 > 0 "ctz 2^32 - 1"
+(i64.const 2 ^Int 64 -Int 1)
+(i64.ctz)
+#assertTopStack < i64 > 0 "ctz 2^64 - 1"
+
+;; popcnt
+
+(i32.const #pow1(i32))
+(i32.popcnt)
+#assertTopStack < i32 > 1 "popcnt #pow1(i32)"
+(i64.const #pow1(i64))
+(i64.popcnt)
+#assertTopStack < i64 > 1 "popcnt #pow1(i32)"
+
+(i32.const 0)
+(i32.popcnt)
+#assertTopStack < i32 > 0 "popcnt 0"
+(i64.const 0)
+(i64.popcnt)
+#assertTopStack < i64 > 0 "popcnt 0"
+
+(i32.const 1)
+(i32.popcnt)
+#assertTopStack < i32 > 1 "popcnt 1"
+(i64.const 1)
+(i64.popcnt)
+#assertTopStack < i64 > 1 "popcnt 1"
+
+(i32.const 2 ^Int 32 -Int 1)
+(i32.popcnt)
+#assertTopStack < i32 > 32 "popcnt 2^32 - 1"
+(i64.const 2 ^Int 64 -Int 1)
+(i64.popcnt)
+#assertTopStack < i64 > 64 "popcnt 2^64 - 1"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/branching.wast b/docs/runtimeverification-wasm-semantics/tests/simple/branching.wast
new file mode 100644
index 000000000..ee7121b0c
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/branching.wast
@@ -0,0 +1,20 @@
+(module
+ (func (export "as-if-cond") (param i32) (result i32)
+ (block (result i32)
+ (if (result i32)
+ (br_if 0 (i32.const 1) (local.get 0))
+ (then (i32.const 2))
+ (else (i32.const 3))
+ )
+ )
+ )
+
+ (func (export "to-top-level0") (br 0))
+ (func (export "to-top-level1") (block (br 0)))
+)
+
+(assert_return (invoke "as-if-cond" (i32.const 1)) (i32.const 1))
+(assert_return (invoke "to-top-level0"))
+(assert_return (invoke "to-top-level1"))
+
+#clearConfig
\ No newline at end of file
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/comments.wast b/docs/runtimeverification-wasm-semantics/tests/simple/comments.wast
new file mode 100644
index 000000000..2071e8b9e
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/comments.wast
@@ -0,0 +1,23 @@
+(i32.const 7)
+;; this should be ignored
+(i32.const 8) ;; this should be ignored as well
+(i32.add)
+
+(;
+all this text
+should be ignored
+;)
+
+#assertTopStack < i32 > 15 "dummy test 1"
+
+(i32.const -3)
+(i32.const 6) (; comment at end of line ;)
+(i32.add)
+#assertTopStack < i32 > 3 "dummy test 2"
+
+(i32.const -3)
+(i32.(;comment in the middle;)const 6)
+(i32.add)
+#assertTopStack < i32 > 3 "dummy test 2"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/comparison.wast b/docs/runtimeverification-wasm-semantics/tests/simple/comparison.wast
new file mode 100644
index 000000000..ae7f0f441
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/comparison.wast
@@ -0,0 +1,115 @@
+(i32.const 0)
+(i32.eqz)
+#assertTopStack < i32 > 1 "eqz1"
+
+(i32.const 3)
+(i32.eqz)
+#assertTopStack < i32 > 0 "eqz2"
+
+(i32.eqz (i32.const 3))
+#assertTopStack < i32 > 0 "eqz folded"
+
+(i32.const 3)
+(i32.const 3)
+(i32.eq)
+#assertTopStack < i32 > 1 "eq1"
+
+(i32.const 3)
+(i32.const 4)
+(i32.eq)
+#assertTopStack < i32 > 0 "eq2"
+
+(i32.const 3)
+(i32.const 3)
+(i32.ne)
+#assertTopStack < i32 > 0 "ne1"
+
+(i32.const 3)
+(i32.const 4)
+(i32.ne)
+#assertTopStack < i32 > 1 "ne2"
+
+(i32.const 2)
+(i32.const 32)
+(i32.lt_u)
+#assertTopStack < i32 > 1 "lt_u"
+
+(i32.lt_u (i32.const 32) (i32.const 2))
+#assertTopStack < i32 > 0 "lt_u"
+
+(i32.const 2)
+(i32.const 32)
+(i32.gt_u)
+#assertTopStack < i32 > 0 "gt_u"
+
+(i32.const #pow1(i32) +Int 7)
+(i32.const #pow1(i32) +Int 15)
+(i32.lt_s)
+#assertTopStack < i32 > 1 "lt_s 1"
+
+(i32.const -32)
+(i32.const 32)
+(i32.lt_s)
+#assertTopStack < i32 > 1 "lt_s 2"
+
+(i32.const #pow1(i32) +Int 7)
+(i32.const #pow1(i32) +Int 15)
+(i32.gt_s)
+#assertTopStack < i32 > 0 "gt_s 1"
+
+(i32.const -32)
+(i32.const 32)
+(i32.gt_s)
+#assertTopStack < i32 > 0 "gt_s 2"
+
+(i32.const 2)
+(i32.const 32)
+(i32.le_u)
+#assertTopStack < i32 > 1 "le_u 1"
+
+(i32.const 32)
+(i32.const 32)
+(i32.le_u)
+#assertTopStack < i32 > 1 "le_u 2"
+
+(i32.const 2)
+(i32.const 32)
+(i32.ge_u)
+#assertTopStack < i32 > 0 "ge_u 1"
+
+(i32.const 32)
+(i32.const 32)
+(i32.ge_u)
+#assertTopStack < i32 > 1 "ge_u 2"
+
+(i32.const #pow1(i32) +Int 7)
+(i32.const #pow1(i32) +Int 15)
+(i32.le_s)
+#assertTopStack < i32 > 1 "le_s 1"
+
+(i32.const 32)
+(i32.const 32)
+(i32.le_s)
+#assertTopStack < i32 > 1 "le_s 2"
+
+(i32.const -32)
+(i32.const 32)
+(i32.le_s)
+#assertTopStack < i32 > 1 "le_s 3"
+
+(i32.const #pow1(i32) +Int 7)
+(i32.const #pow1(i32) +Int 15)
+(i32.ge_s)
+#assertTopStack < i32 > 0 "ge_s 1"
+
+(i32.const 32)
+(i32.const 32)
+(i32.ge_s)
+#assertTopStack < i32 > 1 "ge_s 2"
+
+(i32.const -32)
+(i32.const 32)
+(i32.ge_s)
+#assertTopStack < i32 > 0 "ge_s 3"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/constants.wast b/docs/runtimeverification-wasm-semantics/tests/simple/constants.wast
new file mode 100644
index 000000000..f221feda1
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/constants.wast
@@ -0,0 +1,78 @@
+;; Integers
+;; --------
+
+(i32.const 3)
+#assertTopStack < i32 > 3 "i32 1"
+
+(i32.const 5)
+#assertTopStack < i32 > 5 "i32 parens"
+
+(i64.const 71)
+#assertTopStack < i64 > 71 "i64"
+
+(i32.const #unsigned(i32, -5))
+#assertTopStack < i32 > #pow(i32) -Int 5 "i32 manual unsigned"
+
+(i32.const #pow(i32) -Int 5)
+#assertTopStack < i32 > -5 "i32 manual unsigned"
+
+(i32.const -5)
+#assertTopStack < i32 > #unsigned(i32, -5) "i32 signed constant"
+
+(i32.const #unsigned(i32, -5))
+#assertTopStack < i32 > -5 "i32 signed assert"
+
+(i32.const #pow(i32) +Int 1)
+#assertTopStack < i32 > 1 "i32 overflow"
+
+(i32.const -1)
+#assertTopStackExactly < i32 > #pow(i32) -Int 1 "i32 overflow"
+
+(i64.const -1)
+#assertTopStackExactly < i64 > #pow(i64) -Int 1 "i62 overflow"
+
+;; Floating point
+;; --------------
+
+(f32.const 3.245)
+#assertTopStack < f32 > 3.245 "f32"
+
+(f64.const 3.234523)
+#assertTopStack < f64 > 3.234523 "f32 parens"
+
+(f64.const 1.21460644e+52)
+#assertTopStack < f64 > 1.21460644e+52 "f64 scientific 1"
+
+(f64.const 1.6085927714e-321)
+#assertTopStack < f64 > 1.6085927714e-321 "f64 scientific 2"
+
+(f64.const 1.63176601e-302)
+#assertTopStack < f64 > 1.63176601e-302 "f64 scientific 3"
+
+;; Below examples do not work with current float parser
+;; (f64.const 0x1.da21c460a6f44p+52)
+;; (f64.const 0x1.60859d2e7714ap-321)
+;; (f64.const 0x1.e63f1b7b660e1p-302)
+
+;; Helper conversions
+;; ------------------
+
+(i32.const #unsigned(i32, #signed(i32, 0)))
+#assertTopStack < i32 > 0 "#unsigned . #signed 1"
+
+(i32.const #unsigned(i32, #signed(i32, #pow1(i32))))
+#assertTopStack < i32 > #pow1(i32) "#unsigned . #signed 2"
+
+(i32.const #unsigned(i32, #signed(i32, #pow(i32) -Int 1)))
+#assertTopStack < i32 > #pow(i32) -Int 1 "#unsigned . #signed 3"
+
+(i64.const #unsigned(i64, #signed(i64, 0)))
+#assertTopStack < i64 > 0 "#unsigned . #signed 4"
+
+(i64.const #unsigned(i64, #signed(i64, #pow1(i64))))
+#assertTopStack < i64 > #pow1(i64) "#unsigned . #signed 5"
+
+(i64.const #unsigned(i64, #signed(i64, #pow(i64) -Int 1)))
+#assertTopStack < i64 > #pow(i64) -Int 1 "#unsigned . #signed 6"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/control-flow.wast b/docs/runtimeverification-wasm-semantics/tests/simple/control-flow.wast
new file mode 100644
index 000000000..9b7eadab2
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/control-flow.wast
@@ -0,0 +1,209 @@
+;; Unreachable
+( unreachable )
+#assertTrap "unreachable"
+
+;; Blocks
+
+block (result i32 i32 i32)
+ (i32.const 1)
+ (i32.const 2)
+ (i32.const 3)
+end
+#assertStack < i32 > 3 : < i32 > 2 : < i32 > 1 : .ValStack "block 1"
+
+block (result i32 i32)
+ (i32.const 1)
+ (i32.const 2)
+ (i32.const 3)
+ (drop)
+end
+#assertStack < i32 > 2 : < i32 > 1 : .ValStack "block 2"
+
+block (result i32 i32)
+ (i32.const 1)
+ (i32.const 2)
+ (i32.const 3)
+end
+#assertStack < i32 > 3 : < i32 > 2 : .ValStack "block 3 (invalid)"
+
+;; (block (result i32)
+;; (i32.const 1)
+;; )
+;; #assertTopStack < i32 > 1 "block with named result 1"
+
+;; (block result i64 i32
+;; (i32.const 2)
+;; (i32.const 1)
+;; (i64.const 5)
+;; )
+;; #assertStack < i64 > 5 : < i32 > 1 : .ValStack "block with named result 2"
+
+;; Breaks
+
+(i32.const 1)
+(i32.const 2)
+block
+ (i32.const 3)
+ (br 0)
+ (i32.const 4)
+ (br 0)
+end
+#assertStack < i32 > 2 : < i32 > 1 : .ValStack "br 1"
+
+(i32.const 1)
+(i32.const 2)
+block
+ (i32.const 3)
+ block (result i32 i32)
+ (i32.const 4)
+ (i32.const 5)
+ (br 1)
+ end
+ (i32.const 6)
+ (br 0)
+end
+#assertStack < i32 > 2 : < i32 > 1 : .ValStack "br 2"
+
+(i32.const 1)
+(i32.const 2)
+block (result i32 i32)
+ (i32.const 3)
+ block (result i32 i32)
+ (i32.const 4)
+ (i32.const 5)
+ (br 1)
+ end
+ (i32.const 6)
+ (br 0)
+end
+#assertStack < i32 > 5 : < i32 > 4 : < i32 > 2 : < i32 > 1 : .ValStack "br 3"
+
+(i32.const 1)
+(i32.const 2)
+block (result i32 i32)
+ (i32.const 3)
+ block
+ (i32.const 4)
+ (i32.const 5)
+ (br 1)
+ end
+ (i32.const 6)
+ (br 0)
+end
+#assertStack < i32 > 5 : < i32 > 4 : < i32 > 2 : < i32 > 1 : .ValStack "br 4"
+
+(i32.const 1)
+(i32.const 2)
+block (result i32)
+ (i32.const 3)
+ (i32.const 0)
+ (br_if 0)
+ (i32.const 4)
+ (br 0)
+end
+#assertStack < i32 > 4 : < i32 > 2 : < i32 > 1 : .ValStack "br_if 1 false"
+
+(i32.const 1)
+(i32.const 2)
+block (result i32)
+ (i32.const 3)
+ (i32.const 1)
+ (br_if 0)
+ (i32.const 4)
+ (br 0)
+end
+#assertStack < i32 > 3 : < i32 > 2 : < i32 > 1 : .ValStack "br_if 1 true"
+
+(i32.const 1)
+(i32.const 2)
+block
+ (i32.const 3)
+ (i32.const 1)
+ (br_if 0)
+ (i32.const 4)
+ (br 0)
+end
+#assertStack < i32 > 2 : < i32 > 1 : .ValStack "br_if 2 true"
+
+;; Conditional
+
+(i32.const 1)
+if (result i32) i32.const 1 else i32.const -1 end
+#assertTopStack < i32 > 1 "if true"
+
+(i32.const 0)
+if (result i32) i32.const 1 else i32.const -1 end
+#assertTopStack < i32 > -1 "if false"
+
+;; (i32.const -1)
+;; (if (i32.const 0) (then))
+;; #assertTopStack < i32 > -1 "if folded false empty"
+
+;; (i32.const -1)
+;; (if (result i32) (i32.const 1) (then (i32.const 1)) (else (i32.const 2)))
+;; #assertStack < i32 > 1 : < i32 > -1 : .ValStack "if folded true"
+
+;; (i32.const -1)
+;; (if (result i32) (i32.const 0) (then (i32.const 1)) (else (i32.const 2)))
+;; #assertStack < i32 > 2 : < i32 > -1 : .ValStack "if folded false"
+
+;; (if (result i32) (i32.const 1) (then (unreachable)) (else (i32.const 1)))
+;; #assertTrap "if lazy first branch true"
+
+;; (if (result i32) (i32.const 0) (then (unreachable)) (else (i32.const 1)))
+;; #assertTopStack < i32 > 1 "if lazy first branch false"
+
+;; (if (result i32) (i32.const 1) (then (i32.const -1)) (else (unreachable)))
+;; #assertTopStack < i32 > -1 "if lazy second branch true"
+
+;; (if (result i32) (i32.const 0) (then (i32.const -1)) (else (unreachable)))
+;; #assertTrap "if lazy second branch false"
+
+;; (if (result i32) (unreachable) (then (i32.const -1)) (else (unreachable)))
+;; #assertTrap "if strict condition"
+
+;; Looping
+
+init_locals < i32 > 10 : < i32 > 0 : .ValStack
+loop
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (local.set 1)
+ (local.get 0)
+ (i32.const 1)
+ (i32.sub)
+ (local.tee 0)
+ (br_if 0)
+end
+#assertLocal 0 < i32 > 0 "sum 1 -> 10 loop"
+#assertLocal 1 < i32 > 55 "sum 1 -> 10 loop"
+
+init_locals < i32 > 10 : < i32 > 0 : .ValStack
+block
+ loop
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (local.set 1)
+ (local.get 0)
+ (i32.const 1)
+ (i32.sub)
+ (local.tee 0)
+ (i32.eqz)
+ (br_if 1)
+ (br 0)
+ end
+end
+#assertLocal 0 < i32 > 0 "sum 1 -> 10 loop concrete syntax"
+#assertLocal 1 < i32 > 55 "sum 1 -> 10 loop concrete syntax"
+
+;; Stack Underflow
+;; TODO: We need to give semantics to stack underflow (though it could not happen with a validated program).
+;; We need `trap` semantics first.
+;; (i32.const 0)
+;; block [ i32 i32 ]
+;; (i32.const 7)
+;; end
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/conversion.wast b/docs/runtimeverification-wasm-semantics/tests/simple/conversion.wast
new file mode 100644
index 000000000..c697026fe
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/conversion.wast
@@ -0,0 +1,47 @@
+;; Wrap.
+
+(i64.const 4294967296) ;; 2^32
+(i32.wrap_i64)
+#assertTopStack < i32 > 0 "wrap 2^32"
+
+(i64.const 4294967295) ;; 2^32 - 1
+(i32.wrap_i64)
+#assertTopStack < i32 > 4294967295 "wrap 2^32 - 1"
+
+(i32.wrap_i64 (i64.const 4294967298))
+#assertTopStack < i32 > 2 "folded wrap 2^32 + 2"
+
+;; Extend.
+
+(i32.const 4294967295) ;; 2^32 - 1
+(i64.extend_i32_u)
+#assertTopStack < i64 > 4294967295 "extend unsig"
+
+(i32.const -1) ;; 2^32 - 1
+(i64.extend_i32_s)
+#assertTopStack < i64 > -1 "extend sig"
+
+(i64.extend_i32_s (i32.const 15))
+#assertTopStack < i64 > 15 "folded extend sig"
+
+(module
+ (func (export "i64.extend_i32_s") (param $x i32) (result i64) (i64.extend_i32_s (local.get $x)))
+ (func (export "i64.extend_i32_u") (param $x i32) (result i64) (i64.extend_i32_u (local.get $x)))
+ (func (export "i32.wrap_i64") (param $x i64) (result i32) (i32.wrap_i64 (local.get $x)))
+)
+
+(assert_return (invoke "i64.extend_i32_s" (i32.const 0)) (i64.const 0))
+(assert_return (invoke "i64.extend_i32_s" (i32.const 10000)) (i64.const 10000))
+(assert_return (invoke "i64.extend_i32_s" (i32.const -10000)) (i64.const -10000))
+(assert_return (invoke "i64.extend_i32_s" (i32.const -1)) (i64.const -1))
+(assert_return (invoke "i64.extend_i32_s" (i32.const 0x7fffffff)) (i64.const 0x000000007fffffff))
+(assert_return (invoke "i64.extend_i32_s" (i32.const 0x80000000)) (i64.const 0xffffffff80000000))
+
+(assert_return (invoke "i64.extend_i32_u" (i32.const 0)) (i64.const 0))
+(assert_return (invoke "i64.extend_i32_u" (i32.const 10000)) (i64.const 10000))
+(assert_return (invoke "i64.extend_i32_u" (i32.const -10000)) (i64.const 0x00000000ffffd8f0))
+(assert_return (invoke "i64.extend_i32_u" (i32.const -1)) (i64.const 0xffffffff))
+(assert_return (invoke "i64.extend_i32_u" (i32.const 0x7fffffff)) (i64.const 0x000000007fffffff))
+(assert_return (invoke "i64.extend_i32_u" (i32.const 0x80000000)) (i64.const 0x0000000080000000))
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/data.wast b/docs/runtimeverification-wasm-semantics/tests/simple/data.wast
new file mode 100644
index 000000000..b036ad7ff
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/data.wast
@@ -0,0 +1,91 @@
+;; Instantiating with data
+
+(module
+(memory $an-ident (data "WASM" "2\2E0"))
+)
+
+(memory.size)
+
+#assertTopStack < i32 > 1 "size of stack"
+#assertMemoryData (0, 87) "text to ascii W"
+#assertMemoryData (1, 65) "text to ascii A"
+#assertMemoryData (2, 83) "text to ascii S"
+#assertMemoryData (3, 77) "text to ascii M"
+#assertMemoryData (4, 50) "text to ascii 2"
+#assertMemoryData (5, 46) "text to ascii ."
+#assertMemoryData (6, 48) "text to ascii 0"
+#assertMemory $an-ident 1 1 "memorys string length"
+
+#clearConfig
+
+(module
+(memory 1 1)
+(data (offset (i32.const 100)) "W" "AS" "M")
+)
+#assertMemoryData (100, 87) "text to ascii W"
+#assertMemoryData (101, 65) "text to ascii A"
+#assertMemoryData (102, 83) "text to ascii S"
+#assertMemoryData (103, 77) "text to ascii M"
+#assertMemory 0 1 1 "memorys string length"
+
+#clearConfig
+
+(module
+(memory (data))
+)
+#clearConfig
+
+(module
+(memory (data "W"))
+)
+#assertMemoryData (0, 87) "text to ascii W"
+#assertMemory 0 1 1 "memorys string length"
+
+#clearConfig
+
+(module
+(memory (data "\"\t\n\n\t\'\"\r\u{090A}"))
+)
+#assertMemoryData (0, 34) "text to ascii special"
+#assertMemoryData (1, 9) "text to ascii special"
+#assertMemoryData (2, 10) "text to ascii special"
+#assertMemoryData (3, 10) "text to ascii special"
+#assertMemoryData (4, 9) "text to ascii special"
+#assertMemoryData (5, 39) "text to ascii special"
+#assertMemoryData (6, 34) "text to ascii special"
+
+(module
+ (memory $m 1 1)
+ (data (offset (i32.const 0)) "\00")
+ (data (offset (nop) (i32.const 1)) "\01")
+ (data (offset (i32.const 2) (nop)) "\02")
+ (data $m (offset (i32.const 3)) "\03")
+ (data $m (offset (nop) (i32.const 4)) "\04")
+ (data $m (offset (i32.const 5) (nop)) "\05")
+
+ (data (offset (i32.const 6 (nop))) "\06")
+ (data $m (offset (i32.const 7 (nop))) "\07")
+
+ (global $g i32 (i32.const 8))
+ (global $h i32 (i32.const 9))
+
+ (data (offset (global.get $g)) "\08")
+ (data $m (offset (global.get $h)) "\09")
+
+ (func $main (local i32)
+ (local.set 0 (i32.const 9))
+ loop
+ (i32.load8_u (local.get 0))
+ (local.get 0)
+ (if (i32.ne) (then (unreachable)))
+ (i32.sub (local.get 0) (i32.const 1))
+ (local.tee 0)
+ (i32.eqz)
+ (br_if 1)
+ (br 0)
+ end
+ )
+
+ (start $main)
+)
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/desugaring.wast b/docs/runtimeverification-wasm-semantics/tests/simple/desugaring.wast
new file mode 100644
index 000000000..d3a730506
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/desugaring.wast
@@ -0,0 +1,61 @@
+(module
+ (func (export "foo") (result i32) (i32.const 0))
+ (func (export "bar") (result i32) (i32.const 1))
+)
+
+(register "a")
+
+;; Test that imports get ordered correctly.
+;; Function "bar" should get index 0, since it is imported first.
+(module
+ (func (import "a" "bar") (result i32))
+ (import "a" "foo" (func (result i32)))
+ (export "bar" (func 0) )
+)
+
+(assert_return (invoke "bar") (i32.const 1))
+
+;; Test that data initializations get ordered correctly.
+;; The results of the inlined `data` should overwrite the results of the non-inlined data.
+(module
+ (data (offset (i32.const 0)) "b")
+ (memory (data "a"))
+ (func (export "baz") (result i32)
+ (i32.load (i32.const 0))
+ )
+)
+
+(assert_return (invoke "baz") (i32.const 97))
+
+;; Same as above but for `elem`
+(module
+ (elem (offset (i32.const 0)) 0)
+ (table funcref (elem 1))
+ (func (result i32) (i32.const 0))
+ (func (result i32) (i32.const 1))
+ (func (export "biz") (result i32)
+ (call_indirect (result i32) (i32.const 0))
+ )
+)
+
+(assert_return (invoke "biz") (i32.const 1))
+
+;; Regression test: A module with hex integers inside a function after a `table` with inline `elem`.
+(module
+ (table funcref (elem))
+ (func (export "break-inner") (result i32)
+ (local i32)
+ (local.set 0 (i32.const 0))
+ (local.set 0 (i32.add (local.get 0) (block (result i32) (block (result i32) (br 1 (i32.const 0x1))))))
+ (local.set 0 (i32.add (local.get 0) (block (result i32) (block (br 0)) (i32.const 0x2))))
+ (local.set 0
+ (i32.add (local.get 0) (block (result i32) (i32.ctz (br 0 (i32.const 0x4)))))
+ )
+ (local.set 0
+ (i32.add (local.get 0) (block (result i32) (i32.ctz (block (result i32) (br 1 (i32.const 0x8))))))
+ )
+ (local.get 0)
+ )
+)
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/f64-cs.wast b/docs/runtimeverification-wasm-semantics/tests/simple/f64-cs.wast
new file mode 100644
index 000000000..690686e27
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/f64-cs.wast
@@ -0,0 +1,153 @@
+;; Test all the f64 operators on major boundary values and all special
+;; values (except comparison and bitwise operators, which are tested in
+;; f64_bitwise.wast and f64_cmp.wast).
+
+(module
+ (func (export "add") (param $x f64) (param $y f64) (result f64) (f64.add (local.get $x) (local.get $y)))
+ (func (export "sub") (param $x f64) (param $y f64) (result f64) (f64.sub (local.get $x) (local.get $y)))
+ (func (export "mul") (param $x f64) (param $y f64) (result f64) (f64.mul (local.get $x) (local.get $y)))
+ (func (export "div") (param $x f64) (param $y f64) (result f64) (f64.div (local.get $x) (local.get $y)))
+ (func (export "sqrt") (param $x f64) (result f64) (f64.sqrt (local.get $x)))
+ (func (export "min") (param $x f64) (param $y f64) (result f64) (f64.min (local.get $x) (local.get $y)))
+ (func (export "max") (param $x f64) (param $y f64) (result f64) (f64.max (local.get $x) (local.get $y)))
+ (func (export "ceil") (param $x f64) (result f64) (f64.ceil (local.get $x)))
+ (func (export "floor") (param $x f64) (result f64) (f64.floor (local.get $x)))
+ (func (export "trunc") (param $x f64) (result f64) (f64.trunc (local.get $x)))
+ (func (export "nearest") (param $x f64) (result f64) (f64.nearest (local.get $x)))
+)
+
+(assert_return (invoke "add" (f64.const -0.000000e+00) (f64.const -0.000000e+00)) (f64.const -0.000000e+00))
+(assert_return (invoke "add" (f64.const -0.000000e+00) (f64.const -2.225074e-308)) (f64.const -2.225074e-308))
+(assert_return (invoke "add" (f64.const 5.000000e-01) (f64.const -Infinity)) (f64.const -Infinity))
+(assert_return (invoke "add" (f64.const 5.000000e-01) (f64.const Infinity)) (f64.const Infinity))
+
+(assert_return (invoke "sub" (f64.const -0.000000e+00) (f64.const -0.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "sub" (f64.const 0.000000e+00) (f64.const 1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "sub" (f64.const -0.000000e+00) (f64.const -Infinity)) (f64.const Infinity))
+(assert_return (invoke "sub" (f64.const -0.000000e+00) (f64.const Infinity)) (f64.const -Infinity))
+(assert_return (invoke "sub" (f64.const 5.000000e-01) (f64.const -1.797693e+308)) (f64.const 1.797693e+308))
+(assert_return (invoke "sub" (f64.const 5.000000e-01) (f64.const 1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "sub" (f64.const -5.000000e-01) (f64.const -Infinity)) (f64.const Infinity))
+(assert_return (invoke "sub" (f64.const 1.000000e+00) (f64.const 1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "sub" (f64.const Infinity) (f64.const 1.000000e+00)) (f64.const Infinity))
+(assert_return (invoke "sub" (f64.const -Infinity) (f64.const -6.283185e+00)) (f64.const -Infinity))
+(assert_return (invoke "mul" (f64.const -4.940656e-324) (f64.const -0.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "mul" (f64.const 2.225074e-308) (f64.const -2.225074e-308)) (f64.const -0.000000e+00))
+(assert_return (invoke "mul" (f64.const 2.225074e-308) (f64.const 2.225074e-308)) (f64.const 0.000000e+00))
+(assert_return (invoke "mul" (f64.const -2.225074e-308) (f64.const -5.000000e-01)) (f64.const 1.112537e-308))
+(assert_return (invoke "mul" (f64.const -2.225074e-308) (f64.const 5.000000e-01)) (f64.const -1.112537e-308))
+(assert_return (invoke "mul" (f64.const 2.225074e-308) (f64.const -5.000000e-01)) (f64.const -1.112537e-308))
+(assert_return (invoke "mul" (f64.const 5.000000e-01) (f64.const -5.000000e-01)) (f64.const -2.500000e-01))
+(assert_return (invoke "div" (f64.const -0.000000e+00) (f64.const -4.940656e-324)) (f64.const 0.000000e+00))
+(assert_return (invoke "div" (f64.const 0.000000e+00) (f64.const 5.000000e-01)) (f64.const 0.000000e+00))
+(assert_return (invoke "div" (f64.const -0.000000e+00) (f64.const -1.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "div" (f64.const -0.000000e+00) (f64.const 1.000000e+00)) (f64.const -0.000000e+00))
+(assert_return (invoke "div" (f64.const 0.000000e+00) (f64.const Infinity)) (f64.const 0.000000e+00))
+;; (assert_return_canonical_nan (invoke "div" (f64.const -0x0p+0) (f64.const -nan)))
+;; (assert_return_arithmetic_nan (invoke "div" (f64.const -0x0p+0) (f64.const -nan:0x4000000000000)))
+;; (assert_return_canonical_nan (invoke "div" (f64.const -0x0p+0) (f64.const nan)))
+;; (assert_return_arithmetic_nan (invoke "div" (f64.const -0x0p+0) (f64.const nan:0x4000000000000)))
+;; (assert_return_canonical_nan (invoke "div" (f64.const 0x0p+0) (f64.const -nan)))
+;; (assert_return_arithmetic_nan (invoke "div" (f64.const 0x0p+0) (f64.const -nan:0x4000000000000)))
+;; (assert_return_canonical_nan (invoke "div" (f64.const 0x0p+0) (f64.const nan)))
+;; (assert_return_arithmetic_nan (invoke "div" (f64.const 0x0p+0) (f64.const nan:0x4000000000000)))
+(assert_return (invoke "div" (f64.const -4.940656e-308) (f64.const -0.000000e+00)) (f64.const Infinity))
+(assert_return (invoke "div" (f64.const 4.940656e-308) (f64.const -0.000000e+00)) (f64.const -Infinity))
+(assert_return (invoke "div" (f64.const 2.225074e-308) (f64.const 0.000000e+00)) (f64.const Infinity))
+(assert_return (invoke "div" (f64.const -2.225074e-308) (f64.const -4.940656e-324)) (f64.const 4.503600e+15))
+(assert_return (invoke "div" (f64.const 2.225074e-308) (f64.const Infinity)) (f64.const 0.000000e+00))
+(assert_return (invoke "min" (f64.const 0.000000e+00) (f64.const -1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "min" (f64.const 0.000000e+00) (f64.const 1.797693e+308)) (f64.const 0.000000e+00))
+(assert_return (invoke "min" (f64.const -0.000000e+00) (f64.const -Infinity)) (f64.const -Infinity))
+(assert_return (invoke "min" (f64.const -4.940656e-324) (f64.const -1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "max" (f64.const 0.000000e+00) (f64.const 2.225074e-308)) (f64.const 2.225074e-308))
+(assert_return (invoke "max" (f64.const -0.000000e+00) (f64.const -5.000000e-01)) (f64.const -0.000000e+00))
+(assert_return (invoke "max" (f64.const -0.000000e+00) (f64.const 5.000000e-01)) (f64.const 5.000000e-01))
+(assert_return (invoke "max" (f64.const 0.000000e+00) (f64.const -5.000000e-01)) (f64.const 0.000000e+00))
+(assert_return (invoke "max" (f64.const 0.000000e+00) (f64.const 5.000000e-01)) (f64.const 5.000000e-01))
+(assert_return (invoke "max" (f64.const -0.000000e+00) (f64.const -1.000000e+00)) (f64.const -0.000000e+00))
+(assert_return (invoke "max" (f64.const -0.000000e+00) (f64.const 1.000000e+00)) (f64.const 1.000000e+00))
+(assert_return (invoke "max" (f64.const 0.000000e+00) (f64.const -1.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "max" (f64.const 0.000000e+00) (f64.const 1.000000e+00)) (f64.const 1.000000e+00))
+(assert_return (invoke "max" (f64.const 1.000000e+00) (f64.const 1.797693e+308)) (f64.const 1.797693e+308))
+(assert_return (invoke "max" (f64.const -1.000000e+00) (f64.const -Infinity)) (f64.const -1.000000e+00))
+(assert_return (invoke "max" (f64.const -1.000000e+00) (f64.const Infinity)) (f64.const Infinity))
+;; (assert_return_canonical_nan (invoke "sqrt" (f64.const -0x1p-1)))
+(assert_return (invoke "sqrt" (f64.const 5.000000e-01)) (f64.const 7.071068e-01))
+;; (assert_return_canonical_nan (invoke "sqrt" (f64.const -0x1p+0)))
+(assert_return (invoke "sqrt" (f64.const 1.000000e+00)) (f64.const 1.000000e+00))
+;; (assert_return_canonical_nan (invoke "sqrt" (f64.const -0x1.921fb54442d18p+2)))
+(assert_return (invoke "floor" (f64.const -0.000000e+00)) (f64.const -0.000000e+00))
+(assert_return (invoke "floor" (f64.const 0.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "floor" (f64.const -4.940656e-324)) (f64.const -1.000000e+00))
+(assert_return (invoke "floor" (f64.const 4.940656e-324)) (f64.const 0.000000e+00))
+(assert_return (invoke "floor" (f64.const -2.225074e-308)) (f64.const -1.000000e+00))
+(assert_return (invoke "floor" (f64.const 2.225074e-308)) (f64.const 0.000000e+00))
+(assert_return (invoke "floor" (f64.const -5.000000e-01)) (f64.const -1.000000e+00))
+(assert_return (invoke "floor" (f64.const 5.000000e-01)) (f64.const 0.000000e+00))
+(assert_return (invoke "floor" (f64.const -1.000000e+00)) (f64.const -1.000000e+00))
+(assert_return (invoke "floor" (f64.const 1.000000e+00)) (f64.const 1.000000e+00))
+(assert_return (invoke "floor" (f64.const -6.283185e+00)) (f64.const -7.000000e+00))
+(assert_return (invoke "floor" (f64.const 6.283185e+00)) (f64.const 6.000000e+00))
+(assert_return (invoke "floor" (f64.const -1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "floor" (f64.const 1.797693e+308)) (f64.const 1.797693e+308))
+(assert_return (invoke "floor" (f64.const -Infinity)) (f64.const -Infinity))
+(assert_return (invoke "floor" (f64.const Infinity)) (f64.const Infinity))
+(assert_return (invoke "ceil" (f64.const -0.000000e+00)) (f64.const -0.000000e+00))
+(assert_return (invoke "ceil" (f64.const 0.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "ceil" (f64.const -4.940656e-324)) (f64.const -0.000000e+00))
+(assert_return (invoke "ceil" (f64.const 4.940656e-324)) (f64.const 1.000000e+00))
+(assert_return (invoke "ceil" (f64.const -2.225074e-308)) (f64.const -0.000000e+00))
+(assert_return (invoke "ceil" (f64.const 2.225074e-308)) (f64.const 1.000000e+00))
+(assert_return (invoke "ceil" (f64.const -5.000000e-01)) (f64.const -0.000000e+00))
+(assert_return (invoke "ceil" (f64.const 5.000000e-01)) (f64.const 1.000000e+00))
+(assert_return (invoke "ceil" (f64.const -1.000000e+00)) (f64.const -1.000000e+00))
+(assert_return (invoke "ceil" (f64.const 1.000000e+00)) (f64.const 1.000000e+00))
+(assert_return (invoke "ceil" (f64.const -6.283185e+00)) (f64.const -6.000000e+00))
+(assert_return (invoke "ceil" (f64.const 6.283185e+00)) (f64.const 7.000000e+00))
+(assert_return (invoke "ceil" (f64.const -1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "ceil" (f64.const 1.797693e+308)) (f64.const 1.797693e+308))
+(assert_return (invoke "ceil" (f64.const -Infinity)) (f64.const -Infinity))
+(assert_return (invoke "ceil" (f64.const Infinity)) (f64.const Infinity))
+;; (assert_return_canonical_nan (invoke "ceil" (f64.const -nan)))
+;; (assert_return_arithmetic_nan (invoke "ceil" (f64.const -nan:0x4000000000000)))
+;; (assert_return_canonical_nan (invoke "ceil" (f64.const nan)))
+;; (assert_return_arithmetic_nan (invoke "ceil" (f64.const nan:0x4000000000000)))
+(assert_return (invoke "trunc" (f64.const -0.000000e+00)) (f64.const -0.000000e+00))
+(assert_return (invoke "trunc" (f64.const 0.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "trunc" (f64.const -4.940656e-324)) (f64.const -0.000000e+00))
+(assert_return (invoke "trunc" (f64.const 4.940656e-324)) (f64.const 0.000000e+00))
+(assert_return (invoke "trunc" (f64.const -2.225074e-308)) (f64.const -0.000000e+00))
+(assert_return (invoke "trunc" (f64.const 2.225074e-308)) (f64.const 0.000000e+00))
+(assert_return (invoke "trunc" (f64.const -5.000000e-01)) (f64.const -0.000000e+00))
+(assert_return (invoke "trunc" (f64.const 5.000000e-01)) (f64.const 0.000000e+00))
+(assert_return (invoke "trunc" (f64.const -1.000000e+00)) (f64.const -1.000000e+00))
+(assert_return (invoke "trunc" (f64.const 1.000000e+00)) (f64.const 1.000000e+00))
+(assert_return (invoke "trunc" (f64.const -6.283185e+00)) (f64.const -6.000000e+00))
+(assert_return (invoke "trunc" (f64.const 6.283185e+00)) (f64.const 6.000000e+00))
+(assert_return (invoke "trunc" (f64.const -1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "trunc" (f64.const 1.797693e+308)) (f64.const 1.797693e+308))
+(assert_return (invoke "trunc" (f64.const -Infinity)) (f64.const -Infinity))
+(assert_return (invoke "trunc" (f64.const Infinity)) (f64.const Infinity))
+;; (assert_return_canonical_nan (invoke "trunc" (f64.const -nan)))
+;; (assert_return_arithmetic_nan (invoke "trunc" (f64.const -nan:0x4000000000000)))
+;; (assert_return_canonical_nan (invoke "trunc" (f64.const nan)))
+;; (assert_return_arithmetic_nan (invoke "trunc" (f64.const nan:0x4000000000000)))
+(assert_return (invoke "nearest" (f64.const -0.000000e+00)) (f64.const -0.000000e+00))
+(assert_return (invoke "nearest" (f64.const 0.000000e+00)) (f64.const 0.000000e+00))
+(assert_return (invoke "nearest" (f64.const -4.940656e-324)) (f64.const -0.000000e+00))
+(assert_return (invoke "nearest" (f64.const 4.940656e-324)) (f64.const 0.000000e+00))
+(assert_return (invoke "nearest" (f64.const -2.225074e-308)) (f64.const -0.000000e+00))
+(assert_return (invoke "nearest" (f64.const 2.225074e-308)) (f64.const 0.000000e+00))
+(assert_return (invoke "nearest" (f64.const -5.000000e-01)) (f64.const -0.000000e+00))
+(assert_return (invoke "nearest" (f64.const 5.000000e-01)) (f64.const 0.000000e+00))
+(assert_return (invoke "nearest" (f64.const -1.000000e+00)) (f64.const -1.000000e+00))
+(assert_return (invoke "nearest" (f64.const 1.000000e+00)) (f64.const 1.000000e+00))
+(assert_return (invoke "nearest" (f64.const -6.283185e+00)) (f64.const -6.000000e+00))
+(assert_return (invoke "nearest" (f64.const 6.283185e+00)) (f64.const 6.000000e+00))
+(assert_return (invoke "nearest" (f64.const -1.797693e+308)) (f64.const -1.797693e+308))
+(assert_return (invoke "nearest" (f64.const 1.797693e+308)) (f64.const 1.797693e+308))
+(assert_return (invoke "nearest" (f64.const -Infinity)) (f64.const -Infinity))
+(assert_return (invoke "nearest" (f64.const Infinity)) (f64.const Infinity))
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/f64_bitwise-cs.wast b/docs/runtimeverification-wasm-semantics/tests/simple/f64_bitwise-cs.wast
new file mode 100644
index 000000000..78c3859da
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/f64_bitwise-cs.wast
@@ -0,0 +1,147 @@
+;; Test all the f64 bitwise operators on major boundary values and all special
+;; values.
+
+(module
+ (func (export "abs") (param $x f64) (result f64) (f64.abs (local.get $x)))
+ (func (export "neg") (param $x f64) (result f64) (f64.neg (local.get $x)))
+ (func (export "copysign") (param $x f64) (param $y f64) (result f64) (f64.copysign (local.get $x) (local.get $y)))
+)
+
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const -0.0)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const 0.0)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const -0.0)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const 0.0)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const -4.94065645841e-324)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const 4.94065645841e-324)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const -4.94065645841e-324)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const 4.94065645841e-324)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const -2.22507385851e-308)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const 2.22507385851e-308)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const -2.22507385851e-308)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const 2.22507385851e-308)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const -0.5)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const 0.5)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const -0.5)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const 0.5)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const -1.0)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const -0.0) (f64.const 1.0)) (f64.const 0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const -1.0)) (f64.const -0.0))
+(assert_return (invoke "copysign" (f64.const 0.0) (f64.const 1.0)) (f64.const 0.0))
+;; (assert_return (invoke "copysign" (f64.const -0x1.921fb54442d18p+2) (f64.const -nan)) (f64.const -0x1.921fb54442d18p+2))
+(assert_return (invoke "copysign" (f64.const -6.28318530718) (f64.const NaN)) (f64.const 6.28318530718))
+;; (assert_return (invoke "copysign" (f64.const 0x1.921fb54442d18p+2) (f64.const -nan)) (f64.const -0x1.921fb54442d18p+2))
+(assert_return (invoke "copysign" (f64.const 6.28318530718) (f64.const NaN)) (f64.const 6.28318530718))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -0.0)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const 0.0)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -0.0)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const 0.0)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -4.94065645841e-324)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const 4.94065645841e-324)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -4.94065645841e-324)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const 4.94065645841e-324)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -2.22507385851e-308)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const 2.22507385851e-308)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -2.22507385851e-308)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const 2.22507385851e-308)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -0.5)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const 0.5)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -0.5)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const 0.5)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -1.0)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const 1.0)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -1.0)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const 1.0)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -6.28318530718)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const 6.28318530718)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -6.28318530718)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const 6.28318530718)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -1.79769313486e+308)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const 1.79769313486e+308)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -1.79769313486e+308)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const 1.79769313486e+308)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const -Infinity)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const -1.79769313486e+308) (f64.const Infinity)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const -Infinity)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "copysign" (f64.const 1.79769313486e+308) (f64.const Infinity)) (f64.const 1.79769313486e+308))
+;; (assert_return (invoke "copysign" (f64.const -0x1.fffffffffffffp+1023) (f64.const -nan)) (f64.const -0x1.fffffffffffffp+1023))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -0x0p+0)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const 0x0p+0)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -0x0p+0)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const 0.0)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -0x0.0000000000001p-1022)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const 0x0.0000000000001p-1022)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -0x0.0000000000001p-1022)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const 4.94065645841e-324)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -0x1p-1022)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const 0x1p-1022)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -0x1p-1022)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const 2.22507385851e-308)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -0x1p-1)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const 0x1p-1)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -0x1p-1)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const 0.5)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -0x1p+0)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const 0x1p+0)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -0x1p+0)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const 1.0)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -0x1.921fb54442d18p+2)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const 0x1.921fb54442d18p+2)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -0x1.921fb54442d18p+2)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const 6.28318530718)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -0x1.fffffffffffffp+1023)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const 0x1.fffffffffffffp+1023)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -0x1.fffffffffffffp+1023)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const 1.79769313486e+308)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -inf)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const inf)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -inf)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const Infinity)) (f64.const NaN))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const -nan)) (f64.const -nan))
+;; (assert_return (invoke "copysign" (f64.const -nan) (f64.const nan)) (f64.const nan))
+;; (assert_return (invoke "copysign" (f64.const nan) (f64.const -nan)) (f64.const -nan))
+(assert_return (invoke "copysign" (f64.const NaN) (f64.const NaN)) (f64.const NaN))
+(assert_return (invoke "abs" (f64.const -0.0)) (f64.const 0.0))
+(assert_return (invoke "abs" (f64.const 0.0)) (f64.const 0.0))
+(assert_return (invoke "abs" (f64.const -4.94065645841e-324)) (f64.const 4.94065645841e-324))
+(assert_return (invoke "abs" (f64.const 4.94065645841e-324)) (f64.const 4.94065645841e-324))
+(assert_return (invoke "abs" (f64.const -2.22507385851e-308)) (f64.const 2.22507385851e-308))
+(assert_return (invoke "abs" (f64.const 2.22507385851e-308)) (f64.const 2.22507385851e-308))
+(assert_return (invoke "abs" (f64.const -0.5)) (f64.const 0.5))
+(assert_return (invoke "abs" (f64.const 0.5)) (f64.const 0.5))
+(assert_return (invoke "abs" (f64.const -1.0)) (f64.const 1.0))
+(assert_return (invoke "abs" (f64.const 1.0)) (f64.const 1.0))
+(assert_return (invoke "abs" (f64.const -6.28318530718)) (f64.const 6.28318530718))
+(assert_return (invoke "abs" (f64.const 6.28318530718)) (f64.const 6.28318530718))
+(assert_return (invoke "abs" (f64.const -1.79769313486e+308)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "abs" (f64.const 1.79769313486e+308)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "abs" (f64.const -Infinity)) (f64.const Infinity))
+(assert_return (invoke "abs" (f64.const Infinity)) (f64.const Infinity))
+;; (assert_return (invoke "abs" (f64.const -nan)) (f64.const nan))
+(assert_return (invoke "abs" (f64.const NaN)) (f64.const NaN))
+(assert_return (invoke "neg" (f64.const -0.0)) (f64.const 0.0))
+(assert_return (invoke "neg" (f64.const 0.0)) (f64.const -0.0))
+(assert_return (invoke "neg" (f64.const -4.94065645841e-324)) (f64.const 4.94065645841e-324))
+(assert_return (invoke "neg" (f64.const 4.94065645841e-324)) (f64.const -4.94065645841e-324))
+(assert_return (invoke "neg" (f64.const -2.22507385851e-308)) (f64.const 2.22507385851e-308))
+(assert_return (invoke "neg" (f64.const 2.22507385851e-308)) (f64.const -2.22507385851e-308))
+(assert_return (invoke "neg" (f64.const -0.5)) (f64.const 0.5))
+(assert_return (invoke "neg" (f64.const 0.5)) (f64.const -0.5))
+(assert_return (invoke "neg" (f64.const -1.0)) (f64.const 1.0))
+(assert_return (invoke "neg" (f64.const 1.0)) (f64.const -1.0))
+(assert_return (invoke "neg" (f64.const -6.28318530718)) (f64.const 6.28318530718))
+(assert_return (invoke "neg" (f64.const 6.28318530718)) (f64.const -6.28318530718))
+(assert_return (invoke "neg" (f64.const -1.79769313486e+308)) (f64.const 1.79769313486e+308))
+(assert_return (invoke "neg" (f64.const 1.79769313486e+308)) (f64.const -1.79769313486e+308))
+(assert_return (invoke "neg" (f64.const -Infinity)) (f64.const Infinity))
+(assert_return (invoke "neg" (f64.const Infinity)) (f64.const -Infinity))
+;; (assert_return (invoke "neg" (f64.const -nan)) (f64.const nan))
+;; (assert_return (invoke "neg" (f64.const nan)) (f64.const -nan))
+
+
+;; Type check
+
+;; (assert_invalid (module (func (result f64) (f64.copysign (i64.const 0) (f32.const 0)))) "type mismatch")
+;; (assert_invalid (module (func (result f64) (f64.abs (i64.const 0)))) "type mismatch")
+;; (assert_invalid (module (func (result f64) (f64.neg (i64.const 0)))) "type mismatch")
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/f64_cmp-cs.wast b/docs/runtimeverification-wasm-semantics/tests/simple/f64_cmp-cs.wast
new file mode 100644
index 000000000..b843e667d
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/f64_cmp-cs.wast
@@ -0,0 +1,76 @@
+;; Test all the f64 comparison operators on major boundary values and all
+;; special values.
+
+(module
+ (func (export "eq") (param $x f64) (param $y f64) (result i32) (f64.eq (local.get $x) (local.get $y)))
+ (func (export "ne") (param $x f64) (param $y f64) (result i32) (f64.ne (local.get $x) (local.get $y)))
+ (func (export "lt") (param $x f64) (param $y f64) (result i32) (f64.lt (local.get $x) (local.get $y)))
+ (func (export "le") (param $x f64) (param $y f64) (result i32) (f64.le (local.get $x) (local.get $y)))
+ (func (export "gt") (param $x f64) (param $y f64) (result i32) (f64.gt (local.get $x) (local.get $y)))
+ (func (export "ge") (param $x f64) (param $y f64) (result i32) (f64.ge (local.get $x) (local.get $y)))
+)
+
+(assert_return (invoke "eq" (f64.const -0.0) (f64.const -0.0)) (i32.const 1))
+(assert_return (invoke "eq" (f64.const -0.0) (f64.const 0.0)) (i32.const 1))
+(assert_return (invoke "eq" (f64.const 0.0) (f64.const -0.0)) (i32.const 1))
+(assert_return (invoke "eq" (f64.const 0.0) (f64.const 0.0)) (i32.const 1))
+(assert_return (invoke "eq" (f64.const -0.0) (f64.const -4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "eq" (f64.const -0.0) (f64.const 4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "eq" (f64.const 0.0) (f64.const -4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "eq" (f64.const 0.0) (f64.const 4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "eq" (f64.const -4.94065645841e-324) (f64.const -4.94065645841e-324)) (i32.const 1))
+(assert_return (invoke "eq" (f64.const -4.94065645841e-324) (f64.const 4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "eq" (f64.const 4.94065645841e-324) (f64.const -4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "eq" (f64.const 4.94065645841e-324) (f64.const 4.94065645841e-324)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const -0.0) (f64.const 2.22507385851e-308)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const 0.0) (f64.const -2.22507385851e-308)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const 0.0) (f64.const 2.22507385851e-308)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const -0.0) (f64.const -0.5)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const -0.0) (f64.const 0.5)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const 0.0) (f64.const -0.5)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const 0.0) (f64.const 0.5)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const -0.0) (f64.const -1.0)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const -0.0) (f64.const 1.0)) (i32.const 1))
+(assert_return (invoke "ne" (f64.const NaN) (f64.const -0.0)) (i32.const 1))
+(assert_return (invoke "lt" (f64.const -0.0) (f64.const -0.0)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const -0.0) (f64.const 0.0)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const 0.0) (f64.const -0.0)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const 0.0) (f64.const 0.0)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const -0.0) (f64.const -4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const -0.0) (f64.const 4.94065645841e-324)) (i32.const 1))
+(assert_return (invoke "lt" (f64.const 0.0) (f64.const -4.94065645841e-324)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const 0.0) (f64.const 4.94065645841e-324)) (i32.const 1))
+(assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const 6.28318530718)) (i32.const 1))
+(assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const -6.28318530718)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const 6.28318530718)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const -1.79769313486e+308)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const 1.79769313486e+308)) (i32.const 1))
+(assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const -1.79769313486e+308)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const 1.79769313486e+308)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const -Infinity)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const Infinity)) (i32.const 1))
+(assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const -Infinity)) (i32.const 0))
+(assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const Infinity)) (i32.const 1))
+;; (assert_return (invoke "le" (f64.const -0x0.0000000000001p-1022) (f64.const -nan)) (i32.const 0))
+;; (assert_return (invoke "le" (f64.const -0x0.0000000000001p-1022) (f64.const -nan:0x4000000000000)) (i32.const 0))
+(assert_return (invoke "le" (f64.const -4.94065645841e-324) (f64.const NaN)) (i32.const 0))
+;; (assert_return (invoke "le" (f64.const -0x0.0000000000001p-1022) (f64.const nan:0x4000000000000)) (i32.const 0))
+;; (assert_return (invoke "le" (f64.const 0x0.0000000000001p-1022) (f64.const -nan)) (i32.const 0))
+;; (assert_return (invoke "le" (f64.const 0x0.0000000000001p-1022) (f64.const -nan:0x4000000000000)) (i32.const 0))
+(assert_return (invoke "le" (f64.const 4.94065645841e-324) (f64.const NaN)) (i32.const 0))
+(assert_return (invoke "gt" (f64.const -Infinity) (f64.const 1.0)) (i32.const 0))
+(assert_return (invoke "gt" (f64.const Infinity) (f64.const -1.0)) (i32.const 1))
+(assert_return (invoke "gt" (f64.const Infinity) (f64.const 1.0)) (i32.const 1))
+(assert_return (invoke "gt" (f64.const -Infinity) (f64.const -6.28318530718)) (i32.const 0))
+(assert_return (invoke "gt" (f64.const -Infinity) (f64.const 6.28318530718)) (i32.const 0))
+(assert_return (invoke "gt" (f64.const Infinity) (f64.const -6.28318530718)) (i32.const 1))
+(assert_return (invoke "gt" (f64.const Infinity) (f64.const 6.28318530718)) (i32.const 1))
+(assert_return (invoke "ge" (f64.const -0.0) (f64.const -0.0)) (i32.const 1))
+(assert_return (invoke "ge" (f64.const -0.0) (f64.const 0.0)) (i32.const 1))
+(assert_return (invoke "ge" (f64.const 0.0) (f64.const -0.0)) (i32.const 1))
+(assert_return (invoke "ge" (f64.const 0.0) (f64.const 0.0)) (i32.const 1))
+(assert_return (invoke "ge" (f64.const -Infinity) (f64.const 0.0)) (i32.const 0))
+(assert_return (invoke "ge" (f64.const Infinity) (f64.const -0.0)) (i32.const 1))
+(assert_return (invoke "ge" (f64.const Infinity) (f64.const 0.0)) (i32.const 1))
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/fconversions-c.wast b/docs/runtimeverification-wasm-semantics/tests/simple/fconversions-c.wast
new file mode 100644
index 000000000..887df92d4
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/fconversions-c.wast
@@ -0,0 +1,314 @@
+(module
+ (func (export "i32.trunc_f32_s") (param $x f32) (result i32) (i32.trunc_f32_s (local.get $x)))
+ (func (export "i32.trunc_f32_u") (param $x f32) (result i32) (i32.trunc_f32_u (local.get $x)))
+ (func (export "i32.trunc_f64_s") (param $x f64) (result i32) (i32.trunc_f64_s (local.get $x)))
+ (func (export "i32.trunc_f64_u") (param $x f64) (result i32) (i32.trunc_f64_u (local.get $x)))
+ (func (export "i64.trunc_f32_s") (param $x f32) (result i64) (i64.trunc_f32_s (local.get $x)))
+ (func (export "i64.trunc_f32_u") (param $x f32) (result i64) (i64.trunc_f32_u (local.get $x)))
+ (func (export "i64.trunc_f64_s") (param $x f64) (result i64) (i64.trunc_f64_s (local.get $x)))
+ (func (export "i64.trunc_f64_u") (param $x f64) (result i64) (i64.trunc_f64_u (local.get $x)))
+ (func (export "f32.convert_i32_s") (param $x i32) (result f32) (f32.convert_i32_s (local.get $x)))
+ (func (export "f32.convert_i64_s") (param $x i64) (result f32) (f32.convert_i64_s (local.get $x)))
+ (func (export "f64.convert_i32_s") (param $x i32) (result f64) (f64.convert_i32_s (local.get $x)))
+ (func (export "f64.convert_i64_s") (param $x i64) (result f64) (f64.convert_i64_s (local.get $x)))
+ (func (export "f32.convert_i32_u") (param $x i32) (result f32) (f32.convert_i32_u (local.get $x)))
+ (func (export "f32.convert_i64_u") (param $x i64) (result f32) (f32.convert_i64_u (local.get $x)))
+ (func (export "f64.convert_i32_u") (param $x i32) (result f64) (f64.convert_i32_u (local.get $x)))
+ (func (export "f64.convert_i64_u") (param $x i64) (result f64) (f64.convert_i64_u (local.get $x)))
+ (func (export "f64.promote_f32") (param $x f32) (result f64) (f64.promote_f32 (local.get $x)))
+ (func (export "f32.demote_f64") (param $x f64) (result f32) (f32.demote_f64 (local.get $x)))
+)
+
+(assert_return (invoke "i32.trunc_f32_s" (f32.const 0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const 1.401298e-45)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -1.401298e-45)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const 1.0)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const 1.100000e+00)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const 1.5)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -1.0)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -1.100000e+00)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -1.5)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -1.9)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -2.0)) (i32.const -2))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const 2147483520.0)) (i32.const 2147483520))
+(assert_return (invoke "i32.trunc_f32_s" (f32.const -2147483648.0)) (i32.const -2147483648))
+(assert_trap (invoke "i32.trunc_f32_s" (f32.const 2147483648.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_s" (f32.const -2147483904.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_s" (f32.const Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_s" (f32.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_s" (f32.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f32_s" (f32.const nan:0x200000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f32_s" (f32.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f32_s" (f32.const -nan:0x200000)) "invalid conversion to integer")
+
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const -0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 1.401298e-45)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const -1.401298e-45)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 1.0)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 1.100000e+00)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 1.5)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 1.9)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 2.0)) (i32.const 2))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 2147483648)) (i32.const -2147483648)) ;; 0x1.00000p+31 -> 8000 0000
+(assert_return (invoke "i32.trunc_f32_u" (f32.const 4294967040.0)) (i32.const -256))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const -9.000000e-01)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f32_u" (f32.const -9.999999e-01)) (i32.const 0))
+(assert_trap (invoke "i32.trunc_f32_u" (f32.const 4294967296.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_u" (f32.const -1.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_u" (f32.const Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_u" (f32.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f32_u" (f32.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f32_u" (f32.const nan:0x200000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f32_u" (f32.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f32_u" (f32.const -nan:0x200000)) "invalid conversion to integer")
+
+(assert_return (invoke "i32.trunc_f64_s" (f64.const 0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const 4.940656e-324)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -4.940656e-324)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const 1.0)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const 1.100000e+00)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const 1.5)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -1.0)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -1.100000e+00)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -1.5)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -1.9)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -2.0)) (i32.const -2))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const 2147483647.0)) (i32.const 2147483647))
+(assert_return (invoke "i32.trunc_f64_s" (f64.const -2147483648.0)) (i32.const -2147483648))
+(assert_trap (invoke "i32.trunc_f64_s" (f64.const 2147483648.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_s" (f64.const -2147483649.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_s" (f64.const Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_s" (f64.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_s" (f64.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f64_s" (f64.const nan:0x4000000000000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f64_s" (f64.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f64_s" (f64.const -nan:0x4000000000000)) "invalid conversion to integer")
+
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const -0.0)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 4.940656e-324)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const -4.940656e-324)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 1.0)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 1.100000e+00)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 1.5)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 1.9)) (i32.const 1))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 2.0)) (i32.const 2))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 2147483648)) (i32.const -2147483648)) ;; 0x1.00000p+31 -> 8000 0000
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 4294967295.0)) (i32.const -1))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const -9.000000e-01)) (i32.const 0))
+(assert_return (invoke "i32.trunc_f64_u" (f64.const 1e8)) (i32.const 100000000))
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const 4294967296.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const -1.0)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const 1e16)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const 1e30)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const 9223372036854775808)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i32.trunc_f64_u" (f64.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f64_u" (f64.const nan:0x4000000000000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f64_u" (f64.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i32.trunc_f64_u" (f64.const -nan:0x4000000000000)) "invalid conversion to integer")
+
+(assert_return (invoke "i64.trunc_f32_s" (f32.const 0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const 1.401298e-45)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -1.401298e-45)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const 1.0)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const 1.100000e+00)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const 1.5)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -1.0)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -1.100000e+00)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -1.5)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -1.9)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -2.0)) (i64.const -2))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const 4294967296)) (i64.const 4294967296)) ;; 0x1.00000p+32 -> 1 0000 0000
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -4294967296)) (i64.const -4294967296)) ;; -0x1.00000p+32 -> ffff ffff 0000 0000
+(assert_return (invoke "i64.trunc_f32_s" (f32.const 9223371487098961920.0)) (i64.const 9223371487098961920))
+(assert_return (invoke "i64.trunc_f32_s" (f32.const -9223372036854775808.0)) (i64.const -9223372036854775808))
+(assert_trap (invoke "i64.trunc_f32_s" (f32.const 9223372036854775808.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_s" (f32.const -9223373136366403584.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_s" (f32.const Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_s" (f32.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_s" (f32.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f32_s" (f32.const nan:0x200000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f32_s" (f32.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f32_s" (f32.const -nan:0x200000)) "invalid conversion to integer")
+
+(assert_return (invoke "i64.trunc_f32_u" (f32.const 0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const -0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const 1.401298e-45)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const -1.401298e-45)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const 1.0)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const 1.100000e+00)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const 1.5)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const 4294967296)) (i64.const 4294967296))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const 18446742974197923840.0)) (i64.const -1099511627776))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const -9.000000e-01)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f32_u" (f32.const -9.999999e-01)) (i64.const 0))
+(assert_trap (invoke "i64.trunc_f32_u" (f32.const 18446744073709551616.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_u" (f32.const -1.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_u" (f32.const Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_u" (f32.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f32_u" (f32.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f32_u" (f32.const nan:0x200000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f32_u" (f32.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f32_u" (f32.const -nan:0x200000)) "invalid conversion to integer")
+
+(assert_return (invoke "i64.trunc_f64_s" (f64.const 0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const 4.940656e-324)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -4.940656e-324)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const 1.0)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const 1.100000e+00)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const 1.5)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -1.0)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -1.100000e+00)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -1.5)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -1.9)) (i64.const -1))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -2.0)) (i64.const -2))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const 4294967296)) (i64.const 4294967296)) ;; 0x1.00000p+32 -> 1 0000 0000
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -4294967296)) (i64.const -4294967296)) ;; -0x1.00000p+32 -> ffff ffff 0000 0000
+(assert_return (invoke "i64.trunc_f64_s" (f64.const 9223372036854774784.0)) (i64.const 9223372036854774784))
+(assert_return (invoke "i64.trunc_f64_s" (f64.const -9223372036854775808.0)) (i64.const -9223372036854775808))
+(assert_trap (invoke "i64.trunc_f64_s" (f64.const 9223372036854775808.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_s" (f64.const -9223372036854777856.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_s" (f64.const Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_s" (f64.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_s" (f64.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f64_s" (f64.const nan:0x4000000000000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f64_s" (f64.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f64_s" (f64.const -nan:0x4000000000000)) "invalid conversion to integer")
+
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const -0.0)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 4.940656e-324)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const -4.940656e-324)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 1.0)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 1.100000e+00)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 1.5)) (i64.const 1))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 4294967295)) (i64.const 0xffffffff))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 4294967296)) (i64.const 0x100000000))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 18446744073709549568.0)) (i64.const -2048))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const -9.000000e-01)) (i64.const 0))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 1e8)) (i64.const 100000000))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 1e16)) (i64.const 10000000000000000))
+(assert_return (invoke "i64.trunc_f64_u" (f64.const 9223372036854775808)) (i64.const -9223372036854775808))
+(assert_trap (invoke "i64.trunc_f64_u" (f64.const 18446744073709551616.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_u" (f64.const -1.0)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_u" (f64.const Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_u" (f64.const -Infinity)) "integer overflow")
+(assert_trap (invoke "i64.trunc_f64_u" (f64.const NaN)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f64_u" (f64.const nan:0x4000000000000)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f64_u" (f64.const -nan)) "invalid conversion to integer")
+;; (assert_trap (invoke "i64.trunc_f64_u" (f64.const -nan:0x4000000000000)) "invalid conversion to integer")
+
+(assert_return (invoke "f32.convert_i32_s" (i32.const 1)) (f32.const 1.0))
+(assert_return (invoke "f32.convert_i32_s" (i32.const -1)) (f32.const -1.0))
+(assert_return (invoke "f32.convert_i32_s" (i32.const 0)) (f32.const 0.0))
+(assert_return (invoke "f32.convert_i32_s" (i32.const 2147483647)) (f32.const 2147483648))
+(assert_return (invoke "f32.convert_i32_s" (i32.const -2147483648)) (f32.const -2147483648))
+(assert_return (invoke "f32.convert_i32_s" (i32.const 1234567890)) (f32.const 1.234568e+09))
+;; Test rounding directions.
+(assert_return (invoke "f32.convert_i32_s" (i32.const 16777217)) (f32.const 16777216.0))
+(assert_return (invoke "f32.convert_i32_s" (i32.const -16777217)) (f32.const -16777216.0))
+(assert_return (invoke "f32.convert_i32_s" (i32.const 16777219)) (f32.const 16777220.0))
+(assert_return (invoke "f32.convert_i32_s" (i32.const -16777219)) (f32.const -16777220.0))
+
+(assert_return (invoke "f32.convert_i64_s" (i64.const 1)) (f32.const 1.0))
+(assert_return (invoke "f32.convert_i64_s" (i64.const -1)) (f32.const -1.0))
+(assert_return (invoke "f32.convert_i64_s" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "f32.convert_i64_s" (i64.const 9223372036854775807)) (f32.const 9223372036854775807))
+(assert_return (invoke "f32.convert_i64_s" (i64.const -9223372036854775808)) (f32.const -9223372036854775808))
+(assert_return (invoke "f32.convert_i64_s" (i64.const 314159265358979)) (f32.const 3.141593e+14)) ;; PI
+;; Test rounding directions.
+(assert_return (invoke "f32.convert_i64_s" (i64.const 16777217)) (f32.const 16777216.0))
+(assert_return (invoke "f32.convert_i64_s" (i64.const -16777217)) (f32.const -16777216.0))
+(assert_return (invoke "f32.convert_i64_s" (i64.const 16777219)) (f32.const 16777220.0))
+(assert_return (invoke "f32.convert_i64_s" (i64.const -16777219)) (f32.const -16777220.0))
+
+(assert_return (invoke "f64.convert_i32_s" (i32.const 1)) (f64.const 1.0))
+(assert_return (invoke "f64.convert_i32_s" (i32.const -1)) (f64.const -1.0))
+(assert_return (invoke "f64.convert_i32_s" (i32.const 0)) (f64.const 0.0))
+(assert_return (invoke "f64.convert_i32_s" (i32.const 2147483647)) (f64.const 2147483647))
+(assert_return (invoke "f64.convert_i32_s" (i32.const -2147483648)) (f64.const -2147483648))
+(assert_return (invoke "f64.convert_i32_s" (i32.const 987654321)) (f64.const 987654321))
+
+(assert_return (invoke "f64.convert_i64_s" (i64.const 1)) (f64.const 1.0))
+(assert_return (invoke "f64.convert_i64_s" (i64.const -1)) (f64.const -1.0))
+(assert_return (invoke "f64.convert_i64_s" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "f64.convert_i64_s" (i64.const 9223372036854775807)) (f64.const 9223372036854775807))
+(assert_return (invoke "f64.convert_i64_s" (i64.const -9223372036854775808)) (f64.const -9223372036854775808))
+(assert_return (invoke "f64.convert_i64_s" (i64.const 4669201609102990)) (f64.const 4669201609102990)) ;; Feigenbaum
+;; Test rounding directions.
+(assert_return (invoke "f64.convert_i64_s" (i64.const 9007199254740993)) (f64.const 9007199254740992))
+(assert_return (invoke "f64.convert_i64_s" (i64.const -9007199254740993)) (f64.const -9007199254740992))
+(assert_return (invoke "f64.convert_i64_s" (i64.const 9007199254740995)) (f64.const 9007199254740996))
+(assert_return (invoke "f64.convert_i64_s" (i64.const -9007199254740995)) (f64.const -9007199254740996))
+
+(assert_return (invoke "f32.convert_i32_u" (i32.const 1)) (f32.const 1.0))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0)) (f32.const 0.0))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 2147483647)) (f32.const 2147483648))
+(assert_return (invoke "f32.convert_i32_u" (i32.const -2147483648)) (f32.const 2147483648))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0x12345678)) (f32.const 3.054199e+08))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0xffffffff)) (f32.const 4294967296.0))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0x80000080)) (f32.const 2.147484e+09))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0x80000081)) (f32.const 2.147484e+09))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0x80000082)) (f32.const 2.147484e+09))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0xfffffe80)) (f32.const 4.294967e+09))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0xfffffe81)) (f32.const 4.294967e+09))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 0xfffffe82)) (f32.const 4.294967e+09))
+;; Test rounding directions.
+(assert_return (invoke "f32.convert_i32_u" (i32.const 16777217)) (f32.const 16777216.0))
+(assert_return (invoke "f32.convert_i32_u" (i32.const 16777219)) (f32.const 16777220.0))
+
+(assert_return (invoke "f32.convert_i64_u" (i64.const 1)) (f32.const 1.0))
+(assert_return (invoke "f32.convert_i64_u" (i64.const 0)) (f32.const 0.0))
+(assert_return (invoke "f32.convert_i64_u" (i64.const 9223372036854775807)) (f32.const 9223372036854775807))
+(assert_return (invoke "f32.convert_i64_u" (i64.const -9223372036854775808)) (f32.const 9223372036854775808))
+(assert_return (invoke "f32.convert_i64_u" (i64.const 0xffffffffffffffff)) (f32.const 18446744073709551616.0))
+;; Test rounding directions.
+(assert_return (invoke "f32.convert_i64_u" (i64.const 16777217)) (f32.const 16777216.0))
+(assert_return (invoke "f32.convert_i64_u" (i64.const 16777219)) (f32.const 16777220.0))
+
+(assert_return (invoke "f64.convert_i32_u" (i32.const 1)) (f64.const 1.0))
+(assert_return (invoke "f64.convert_i32_u" (i32.const 0)) (f64.const 0.0))
+(assert_return (invoke "f64.convert_i32_u" (i32.const 2147483647)) (f64.const 2147483647))
+(assert_return (invoke "f64.convert_i32_u" (i32.const -2147483648)) (f64.const 2147483648))
+(assert_return (invoke "f64.convert_i32_u" (i32.const 0xffffffff)) (f64.const 4294967295.0))
+
+(assert_return (invoke "f64.convert_i64_u" (i64.const 1)) (f64.const 1.0))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0)) (f64.const 0.0))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 9223372036854775807)) (f64.const 9223372036854775807))
+(assert_return (invoke "f64.convert_i64_u" (i64.const -9223372036854775808)) (f64.const 9223372036854775808))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0xffffffffffffffff)) (f64.const 18446744073709551616.0))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0x8000000000000400)) (f64.const 9.223372e+18))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0x8000000000000401)) (f64.const 9.223372e+18))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0x8000000000000402)) (f64.const 9.223372e+18))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0xfffffffffffff400)) (f64.const 1.844674e+19))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0xfffffffffffff401)) (f64.const 1.844674e+19))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 0xfffffffffffff402)) (f64.const 1.844674e+19))
+;; Test rounding directions.
+(assert_return (invoke "f64.convert_i64_u" (i64.const 9007199254740993)) (f64.const 9007199254740992))
+(assert_return (invoke "f64.convert_i64_u" (i64.const 9007199254740995)) (f64.const 9007199254740996))
+
+(assert_return (invoke "f64.promote_f32" (f32.const 0.0)) (f64.const 0.0))
+(assert_return (invoke "f64.promote_f32" (f32.const -0.0)) (f64.const -0.0))
+(assert_return (invoke "f64.promote_f32" (f32.const 1.123)) (f64.const 1.123))
+(assert_return (invoke "f64.promote_f32" (f32.const Infinity)) (f64.const Infinity))
+(assert_return (invoke "f64.promote_f32" (f32.const -Infinity)) (f64.const -Infinity))
+;; (assert_return_canonical_nan (invoke "f64.promote_f32" (f32.const nan)))
+;; (assert_return_arithmetic_nan (invoke "f64.promote_f32" (f32.const nan:0x200000)))
+;; (assert_return_canonical_nan (invoke "f64.promote_f32" (f32.const -nan)))
+;; (assert_return_arithmetic_nan (invoke "f64.promote_f32" (f32.const -nan:0x200000)))
+
+(assert_return (invoke "f32.demote_f64" (f64.const 0.0)) (f32.const 0.0))
+(assert_return (invoke "f32.demote_f64" (f64.const -0.0)) (f32.const -0.0))
+(assert_return (invoke "f32.demote_f64" (f64.const 4.940656e-324)) (f32.const 0.0))
+(assert_return (invoke "f32.demote_f64" (f64.const -4.940656e-324)) (f32.const -0.0))
+(assert_return (invoke "f32.demote_f64" (f64.const 1.0)) (f32.const 1.0))
+(assert_return (invoke "f32.demote_f64" (f64.const -1.0)) (f32.const -1.0))
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/functions_call.wast b/docs/runtimeverification-wasm-semantics/tests/simple/functions_call.wast
new file mode 100644
index 000000000..39a804c9f
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/functions_call.wast
@@ -0,0 +1,277 @@
+;; Simple add function
+
+(module
+ (type $a-cool-type (func (param i32) (param $b i32) ( result i32 )))
+)
+
+#assertType 0 [ i32 i32 ] -> [ i32 ]
+#assertNextTypeIdx 1
+
+(module
+ (type $a-cool-type (func (param i32) (param $b i32) ( result i32 )))
+ (func $x (type $a-cool-type)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+ (export "000" (func 0))
+
+;; String-named add function
+
+ (func $add (type $a-cool-type) (param $a i32) (param i32) ( result i32 )
+ (local.get $a)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ ;; Remove return statement, don't use explicit type name
+
+ (func $0 (param $a i32) (param $b i32) result i32
+ (local.get $a)
+ (local.get $b)
+ (i32.add)
+ )
+
+
+ (table 1 funcref)
+ (elem 0 (i32.const 0) 2)
+
+ ;; More complicated function with locals
+
+ (func $1 param i64 i64 i64 result i64 local i64
+ (i64.sub (local.get 2) (i64.add (local.get 0) (local.get 1)))
+ (local.set 3)
+ (local.get 3)
+ (return)
+ )
+
+ ( export "export-1" (func 3) )
+)
+
+(assert_return (invoke "000" (i32.const 7) (i32.const 8)) (i32.const 15))
+#assertFunction 0 [ i32 i32 ] -> [ i32 ] [ ] "call function 0 exists"
+
+#assertFunction 1 [ i32 i32 ] -> [ i32 ] [ ] "function string-named add"
+#assertNextTypeIdx 2
+
+(assert_return (invoke "export-1" (i64.const 100) (i64.const 43) (i64.const 22)) (i64.const -121))
+#assertFunction 3 [ i64 i64 i64 ] -> [ i64 ] [ i64 ] "call function 1 exists"
+
+
+(i32.const 7)
+(i32.const 8)
+(i32.const 0)
+(call_indirect (type $a-cool-type))
+
+#assertTopStack < i32 > 15 "call function 0 no return"
+(drop)
+#assertFunction 2 [ i32 i32 ] -> [ i32 ] [ ] "call function 0 exists no return"
+
+;; Function with complicated declaration of types
+(module
+ (func $2 result i32 param i32 i64 param i64 local i32
+ (local.get 0)
+ (return)
+ )
+ (func (export "out-of-order-type-declaration") (result i32)
+ (i32.const 7)
+ (i64.const 8)
+ (i64.const 5)
+ (call $2)
+ )
+)
+(assert_return (invoke "out-of-order-type-declaration") (i32.const 7))
+#assertFunction 0 [ i32 i64 i64 ] -> [ i32 ] [ i32 ] "out of order type declarations"
+#assertNextTypeIdx 2
+
+;; Function with empty declarations of types
+
+(module
+ (func $0 param i64 i64 result result i64 param local
+ (local.get 0)
+ (return)
+ )
+
+ (func $1 (param i64 i64) (result i64)
+ (local.get 0)
+ (return)
+ )
+ (func (export "cool") (result i64)
+ i64.const 10
+ i64.const 11
+ call $1
+ )
+)
+
+(assert_return (invoke "cool") (i64.const 10))
+#assertFunction 1 [ i64 i64 ] -> [ i64 ] [ ] "empty type declarations"
+#assertNextTypeIdx 2
+
+;; Function with just a name
+
+(module
+ (func $3)
+ (export "return-null" (func $3) )
+)
+(assert_return (invoke "return-null"))
+
+#assertFunction 0 [ ] -> [ ] [ ] "no domain/range or locals"
+
+(module
+ (func $add (export "add")
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ (func $sub (export "sub")
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.sub)
+ (return)
+ )
+
+ (func $mul (export "mul")
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.mul)
+ (return)
+ )
+
+ (func $xor (export "xor") (param i32 i32) (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.xor)
+ )
+)
+
+(assert_return (invoke "add" (i32.const 3) (i32.const 5)) (i32.const 8))
+(assert_return (invoke "mul" (i32.const 3) (i32.const 5)) (i32.const 15))
+(assert_return (invoke "sub" (i32.const 12) (i32.const 5)) (i32.const 7))
+(assert_return (invoke "xor" (i32.const 3) (i32.const 5)) (i32.const 6))
+
+#assertFunction 0 [ i32 i32 ] -> [ i32 ] [ ] "add function typed correctly"
+#assertFunction 1 [ i32 i32 ] -> [ i32 ] [ ] "sub function typed correctly"
+#assertFunction 2 [ i32 i32 ] -> [ i32 ] [ ] "mul function typed correctly"
+#assertFunction 3 [ i32 i32 ] -> [ i32 ] [ ] "xor function typed correctly"
+#assertNextTypeIdx 1
+
+(module
+ (func $f1 (param $a i32) (param i32) (result i32) (local $c i32)
+ (local.get $a)
+ (local.get 1)
+ (i32.add)
+ (local.set $c)
+ (local.get $a)
+ (local.get $c)
+ (i32.mul)
+ (return)
+ )
+
+ (func $f2 (param i32 i32 i32 ) (result i32) (local i32 i32)
+ (local.get 0)
+ (local.get 2)
+ (call $f1)
+ (local.get 1)
+ (call $f1)
+ (local.get 0)
+ (i32.mul)
+ (return)
+ )
+
+ (func (export "nested-method-call") (result i32)
+ (i32.const 3)
+ (i32.const 5)
+ (call $f1)
+ (i32.const 5)
+ (i32.const 8)
+ (call $f2)
+ )
+
+)
+
+(assert_return (invoke "nested-method-call") (i32.const 14247936))
+#assertFunction 0 [ i32 i32 ] -> [ i32 ] [ i32 ] "inner calling method"
+#assertFunction 1 [ i32 i32 i32 ] -> [ i32 ] [ i32 i32 ] "outer calling method"
+
+(module
+ (func $func (param i32 i32) (result i32) (local.get 0))
+ (func (export "aaa") (result i32)
+ (block (result i32)
+ (call $func
+ (block (result i32) (i32.const 1)) (i32.const 2)
+ )
+ )
+ )
+)
+
+(assert_return (invoke "aaa") (i32.const 1))
+
+(module
+ (func $2 (export "cool-align-1") (export "cool-align-2") result i32 param i32 i64 param i64 local i32
+ (local.get 0)
+ (return)
+ )
+)
+
+(assert_return (invoke "cool-align-1" (i32.const 7) (i64.const 8) (i64.const 3)) (i32.const 7))
+(assert_return (invoke "cool-align-2" (i32.const 1) (i64.const 5) (i64.const 7)) (i32.const 1))
+
+#assertFunction 0 [ i32 i64 i64 ] -> [ i32 ] [ i32 ] "out of order type declarations"
+
+(module
+ (func (export "foo") (result i32)
+ (block $a (result i32)
+ (block $b (result i32)
+ (call $bar)
+ (i32.const 0)
+ (br $b)
+ )
+ (drop)
+ (i32.const 1)
+ )
+ )
+
+ (func $bar
+ (block $b (block $a (br $a)))
+ )
+)
+
+(assert_return (invoke "foo") (i32.const 1))
+
+;; Check type is correctly desugared.
+
+(module
+ (func $1 param i64 i64 i64 result i64 local i64
+ (i64.sub (local.get 2) (i64.add (local.get 0) (local.get 1)))
+ (local.set 3)
+ (local.get 3)
+ (return)
+ )
+
+ ( export "export-1" (func $1) )
+
+ (func $2 param i64 i64 i64 result i64 local i64
+ (i64.sub (local.get 2) (i64.add (local.get 0) (local.get 1)))
+ (local.set 3)
+ (local.get 3)
+ (return)
+ )
+)
+
+(assert_return (invoke "export-1" (i64.const 100) (i64.const 43) (i64.const 22)) (i64.const -121))
+#assertFunction 0 [ i64 i64 i64 ] -> [ i64 ] [ i64 ] "call function 1 exists"
+#assertType 0 [ i64 i64 i64 ] -> [ i64 ]
+;; Check type was only added once.
+#assertNextTypeIdx 1
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/identifiers.wast b/docs/runtimeverification-wasm-semantics/tests/simple/identifiers.wast
new file mode 100644
index 000000000..a983365ab
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/identifiers.wast
@@ -0,0 +1,76 @@
+;; tests of function identifier names
+
+(module
+ (func $oeauth
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ (func $023eno!thu324
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ (func $02$3e%no!t&hu324
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ (func $02$3e%no!t&hu3'24*32++2ao-eunth
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ (func $02$3e%no!t&hu3'24*32++2ao-eu//nh?
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ (func $aenuth_ae`st|23~423
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+
+ (func $bioi::..@@?^
+ (param i32 i32)
+ (result i32)
+ (local.get 0)
+ (local.get 1)
+ (i32.add)
+ (return)
+ )
+)
+
+#assertFunction 0 [ i32 i32 ] -> [ i32 ] [ ] "simple function name"
+#assertFunction 1 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 1"
+#assertFunction 2 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 2"
+#assertFunction 3 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3"
+#assertFunction 4 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3"
+#assertFunction 5 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3"
+#assertFunction 6 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/imports.wast b/docs/runtimeverification-wasm-semantics/tests/simple/imports.wast
new file mode 100644
index 000000000..fc64b4ab1
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/imports.wast
@@ -0,0 +1,31 @@
+(module $a
+ (global (export "g") (export "glob") (mut i32) (i32.const 42))
+ (memory (export "m") (export "mem") (data "A"))
+ (type $t (func ))
+ (func (export "f") (export "func"))
+ (func (export "gunc") (param i64) (param i32) (result i32) (local.get 1))
+ )
+
+(register "m")
+
+(module
+ (import "m" "gunc" (func (type $t)))
+ (memory (import "m" "mem") 1)
+ (export "x" (global $x))
+ (type $t (func (param i64) (param i32) (result i32)))
+ (func (import "m" "gunc") (type $t))
+ (func (import "m" "f"))
+ (global $x (import "m" "g") (mut i32))
+ (import "m" "g" (global (mut i32)))
+ (func (export "foo") (result i32) (global.get 0))
+ (func (export "mod") (global.set 0 (i32.const 10)))
+ )
+
+(assert_return (invoke "foo") (i32.const 42))
+(invoke "mod")
+(invoke $a "f")
+(assert_return (invoke "foo") (i32.const 10))
+(assert_return (get $a "g") (i32.const 10))
+(assert_return (get "x") (i32.const 10))
+
+#clearConfig
\ No newline at end of file
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/integers.wast b/docs/runtimeverification-wasm-semantics/tests/simple/integers.wast
new file mode 100644
index 000000000..812bb251f
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/integers.wast
@@ -0,0 +1,16 @@
+(module
+ (func (export "add0") (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 0)))
+)
+
+(assert_return (invoke "add0" (i32.const 123)) (i32.const 123))
+(assert_return (invoke "add0" (i32.const +123)) (i32.const 1_2_3))
+(assert_return (invoke "add0" (i32.const +123)) (i32.const 1_2_3))
+(assert_return (invoke "add0" (i32.const -1_23)) (i32.const -12_3))
+(assert_return (invoke "add0" (i32.const -0x11)) (i32.const -17))
+(assert_return (invoke "add0" (i32.const -0x1_1)) (i32.const -1_7))
+(assert_return (invoke "add0" (i32.const 0xF_FF_F)) (i32.const 65535))
+(assert_return (invoke "add0" (i32.const 0xF_FF_F)) (i32.const 65_535))
+(assert_return (invoke "add0" (i32.const -0xF_F111_1)) (i32.const -16716049))
+(assert_return (invoke "add0" (i32.const -0xAABBCCDD)) (i32.const -0xA_A_B_B_C_C_D_D))
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/memory.wast b/docs/runtimeverification-wasm-semantics/tests/simple/memory.wast
new file mode 100644
index 000000000..5610f5ca3
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/memory.wast
@@ -0,0 +1,198 @@
+( memory 34)
+#assertMemory 0 34 .Int "memory initial 2"
+
+#clearConfig
+
+( memory $a-memory 34)
+#assertMemory $a-memory 34 .Int "memory initial 2"
+
+#clearConfig
+
+( memory 4 10 )
+#assertMemory 0 4 10 "memory initial 3"
+
+#clearConfig
+
+( memory $more-memory 4 10 )
+#assertMemory $more-memory 4 10 "memory initial 3"
+
+#clearConfig
+
+( memory $mem 0 10 )
+(memory.size)
+#assertTopStack 0 "memory.size 1"
+#assertMemory $mem 0 10 "memory ungrown"
+
+#clearConfig
+
+( memory $mem 0 10 )
+(memory.grow (i32.const 10))
+(memory.size)
+#assertStack 10 : < i32 > 0 : .ValStack "memory grow"
+(memory.grow (i32.const 1))
+#assertTopStack -1 "memory grow"
+#assertMemory $mem 10 10 "memory grown"
+
+#clearConfig
+
+( memory #maxMemorySize())
+(memory.grow (i32.const 1))
+#assertTopStack -1 "memory grow max too large"
+#assertMemory 0 #maxMemorySize() .Int "memory grow max too large"
+
+#clearConfig
+
+( memory 0 )
+(memory.grow (i32.const #maxMemorySize()))
+(memory.size)
+#assertStack #maxMemorySize() : < i32 > 0 : .ValStack "memory grow unbounded"
+(memory.grow (i32.const 1))
+(memory.size)
+#assertStack #maxMemorySize() : < i32 > -1 : .ValStack "memory grow unbounded"
+#assertMemory 0 #maxMemorySize() .Int "memory grown unbounded"
+
+;; Store and load
+
+#clearConfig
+
+(memory 1)
+(i32.const 1)
+(i64.const 1)
+(i64.store offset=2)
+#assertMemoryData (3, 1) "store is little endian"
+(i32.const 1)
+(i64.const 257)
+(i64.store8 offset=2)
+#assertMemoryData (3, 1) "store8"
+(i32.const 1)
+(i64.const 65537)
+(i64.store16 offset=2)
+#assertMemoryData (3, 1) "store16"
+(i32.const 1)
+(i64.const #pow(i32) +Int 1)
+(i64.store16 offset=2)
+#assertMemoryData (3, 1) "store32"
+#assertMemory 0 1 .Int ""
+
+#clearConfig
+
+(memory $foo 0)
+(i32.const 0)
+(i32.const 0)
+(i32.store8)
+#assertTrap "store to 0 size memory"
+#assertMemory $foo 0 .Int ""
+
+#clearConfig
+
+(memory 1)
+(i32.const 65535)
+(i32.const 1)
+(i32.store8)
+#assertMemoryData (65535, 1) "store to memory edge"
+(i32.const 65535)
+(i32.const 1)
+(i32.store16)
+#assertTrap "store outside of size memory"
+#assertMemory 0 1 .Int ""
+
+#clearConfig
+
+(memory 1)
+(i32.const 15)
+(i64.const #pow(i32) -Int 1)
+(i64.store)
+(i32.const 15)
+(i32.load8_u)
+#assertTopStack 255 "load8 unsigned"
+(i32.const 15)
+(i32.load8_s )
+#assertTopStack -1 "load8 signed"
+(i32.const 16)
+(i32.load16_u )
+#assertTopStack 65535 "load16 unsigned"
+(i32.const 16)
+(i32.load16_s )
+#assertTopStack -1 "load16 signed"
+(i32.const 15)
+(i64.load32_u )
+#assertTopStack #pow(i32) -Int 1 "load32 unsigned1"
+(i32.const 15)
+(i64.load32_s )
+#assertTopStack -1 "load32 signed1"
+(i32.const 17)
+(i64.load32_u )
+#assertTopStack 65535 "load32 unsigned2"
+(i32.const 17)
+(i64.load32_u )
+#assertTopStack 65535 "load32 signed2"
+#assertMemoryData (15, 255) ""
+#assertMemoryData (16, 255) ""
+#assertMemoryData (17, 255) ""
+#assertMemoryData (18, 255) ""
+#assertMemory 0 1 .Int ""
+
+;; Updating
+
+#clearConfig
+
+(memory 1)
+(i32.const 1)
+(i64.const #pow(i64) -Int 1)
+(i64.store)
+(i32.const 5) (i32.const 0)
+(i32.store )
+(i32.const 3) (i32.const 0)
+(i32.store16 )
+(i32.const 1) (i32.const 0)
+(i32.store8 )
+(i32.const 2) (i32.const 0)
+(i32.store8 )
+#assertMemory 0 1 .Int "Zero updates erases memory"
+
+#clearConfig
+
+(memory 1)
+(i32.const 1) (i64.const #pow(i64) -Int 1)
+(i64.store )
+(i32.const 2) (i32.const 0)
+(i32.store8 )
+(i32.const 4) (i32.const 0)
+(i32.store )
+#assertMemoryData (1, 255) ""
+#assertMemoryData (3, 255) ""
+#assertMemoryData (8, 255) ""
+#assertMemory 0 1 .Int "Zero updates don't over-erase"
+
+#clearConfig
+
+(module
+ (memory 0)
+)
+
+(module
+ (memory (data "A"))
+)
+
+#assertMemoryData (0, 65) ""
+
+(module
+ (memory 1)
+ (func $start (i32.store (i32.const 0) (i32.const 42)))
+ (start $start)
+)
+
+#assertMemoryData 1 (0, 65) "Start didn't modify other memory"
+#assertMemoryData (0, 42) "Start function modified its own memory"
+
+(module
+ (memory 0)
+
+ (func (export "load_at_zero") (result i32) (i32.load (i32.const 0)))
+ (func (export "store_at_zero") (i32.store (i32.const 0) (i32.const 2)))
+)
+
+(assert_trap (invoke "store_at_zero") "out of bounds memory access")
+(assert_trap (invoke "load_at_zero") "out of bounds memory access")
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/modules.wast b/docs/runtimeverification-wasm-semantics/tests/simple/modules.wast
new file mode 100644
index 000000000..4266b9c8a
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/modules.wast
@@ -0,0 +1,58 @@
+(module $myMod)
+
+#assertNamedModule $myMod "named empty module"
+
+(module $anotherName)
+
+(register "a module name")
+
+#assertRegistrationNamed "a module name" $anotherName "registration1"
+#assertNamedModule $anotherName "named registered module"
+
+(module $myMod2)
+
+(module)
+
+(module $myMod3)
+
+(register "a module name 2" $myMod2)
+(register "another module name" $myMod3)
+(register "third module name")
+
+#assertRegistrationNamed "another module name" $myMod3 "registration3"
+#assertRegistrationNamed "a module name 2" $myMod2 "registration4"
+#assertRegistrationUnnamed "third module name" "registration5"
+
+(assert_malformed
+ (module quote "(func block end $l)")
+ "mismatching label"
+)
+
+(assert_malformed
+ (module quote "(func block $a end $l)")
+ "mismatching label"
+)
+
+#clearConfig
+
+;; Test ordering of definitions in modules.
+
+(module
+ (start $main) ;; Should initialize memory position 1.
+ (elem (i32.const 1) $store)
+ (data (i32.const 100) "ba")
+ (data (i32.const 100) "c") ;; Should overwrite previous, leaving "5 1" as memory bytes
+ (func)
+ (func $main (call_indirect (i32.const 1))) ;; Should call $store.
+ (func $store (i32.store (i32.const 1) (i32.const 42)))
+ (func $get (export "get") (result i32)
+ (i32.add (i32.load (i32.const 1)) (i32.load (i32.const 100))) ;; For checking both data initialization.
+ )
+ (memory 10 10)
+ (elem (i32.const 0) 0)
+ (table 2 funcref)
+)
+
+(assert_return (invoke "get") i32.const 24973 )
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/polymorphic.wast b/docs/runtimeverification-wasm-semantics/tests/simple/polymorphic.wast
new file mode 100644
index 000000000..e507b17bf
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/polymorphic.wast
@@ -0,0 +1,68 @@
+;; drop
+
+(i32.const 15)
+(drop)
+#assertStack .ValStack "drop i32"
+
+(i64.const 15)
+(drop)
+#assertStack .ValStack "drop i64"
+
+(f32.const 15.0)
+(drop)
+#assertStack .ValStack "drop f32"
+
+(f64.const 15.0)
+(drop)
+#assertStack .ValStack "drop f64"
+
+(i32.const 5)
+(drop (i32.const 1))
+#assertTopStack < i32 > 5 "folded drop"
+
+;; select
+
+(i32.const -1)
+(i32.const 1)
+(i32.const 1)
+(select)
+#assertTopStack < i32 > -1 "select i32 true"
+
+(i32.const -1)
+(i32.const 1)
+(i32.const 0)
+(select)
+#assertTopStack < i32 > 1 "select i32 false"
+
+(i64.const -1)
+(i64.const 1)
+(i32.const 1)
+(select)
+#assertTopStack < i64 > -1 "select i64 true"
+
+(i64.const -1)
+(i64.const 1)
+(i32.const 0)
+(select)
+#assertTopStack < i64 > 1 "select i64 false"
+
+(select (i32.const 1) (i32.const 0) (i32.const 1))
+#assertTopStack < i32 > 1 "folded select i32"
+
+(select (i64.const 1) (i64.const 0) (i32.const 0))
+#assertTopStack < i64 > 0 "folded select i64"
+
+(select (unreachable) (i64.const -1) (i32.const 0))
+#assertTrap "select strict in first branch"
+
+(select (i64.const 1) (unreachable) (i32.const 0))
+#assertTrap "select strict in second branch"
+#assertTopStack < i64 > 1 "select strict in second branch"
+
+(select (i64.const 1) (i64.const -1) (unreachable))
+#assertTrap "select strict in condition"
+#assertTopStack < i64 > -1 "select strict in condition"
+(drop)
+#assertTopStack < i64 > 1 "select strict in condition"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/start.wast b/docs/runtimeverification-wasm-semantics/tests/simple/start.wast
new file mode 100644
index 000000000..5301f14b8
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/start.wast
@@ -0,0 +1,38 @@
+(module
+ (memory 1)
+ (func $inc
+ (i32.store8
+ (i32.const 0)
+ (i32.add
+ (i32.load8_u (i32.const 0))
+ (i32.const 1)))
+ )
+ (func $main
+ (i32.store (i32.const 0) (i32.const 65))
+ (call $inc)
+ (call $inc)
+ (call $inc)
+ )
+ (start $main)
+)
+
+#assertMemoryData (0, 68) "start inc"
+#assertFunction 0 [ ] -> [ ] [ ] "$inc"
+#assertFunction 1 [ ] -> [ ] [ ] "$main"
+#assertMemory 0 1 .Int ""
+
+#clearConfig
+
+(module
+ (func $foo (unreachable))
+ (start $foo)
+)
+#assertTrap "Trap propagates through start invocation"
+#assertFunction 0 [ ] -> [ ] [ ] ""
+
+(assert_trap
+ (module (func $main (unreachable)) (start $main))
+ "unreachable"
+)
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/table.wast b/docs/runtimeverification-wasm-semantics/tests/simple/table.wast
new file mode 100644
index 000000000..fe7972b0b
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/table.wast
@@ -0,0 +1,112 @@
+(module ( table 0 funcref ) )
+#assertTable 0 0 .Int "table initial 1"
+
+(module ( table $named 4 funcref) )
+#assertTable $named 4 .Int "table initial 2"
+
+(module ( table 14 21 funcref ) )
+#assertTable 0 14 21 "table initial 3"
+
+(module (
+ table $named2 funcref (elem $f $g $k))
+ (func $f) (func $g) (func $k)
+)
+#assertTableElem (0, 0) "table elem 0"
+#assertTableElem (1, 1) "table elem 1"
+#assertTableElem (2, 2) "table elem 2"
+#assertTable $named2 3 3 "table one with elements"
+
+(module
+ ( elem 0 (i32.const 1) $f $g)
+ ( table 4 funcref)
+ (func $f) (func $g)
+)
+
+#assertTableElem (1, 3) "table elem 1"
+#assertTableElem (2, 4) "table elem 2"
+#assertTable 0 4 .Int "table two with elements"
+
+(module
+ ( elem (i32.const 1) func $f $g)
+ ( table 4 funcref)
+ (func $f) (func $g)
+)
+
+#assertTableElem (1, 5) "table elem 1"
+#assertTableElem (2, 6) "table elem 2"
+#assertTable 0 4 .Int "table two with elements"
+
+(module
+ (type $out-i32 (func (result i32)))
+ (table $tab 10 funcref)
+ (elem (i32.const 8) $const-i32-a)
+ (elem (i32.const 9) $const-i32-b)
+ (func $const-i32-a (type $out-i32) (i32.const 65))
+ (func $const-i32-b (type $out-i32) (i32.const 66))
+ (func (export "call-7") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 7))
+ )
+ (func (export "call-8") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 8))
+ )
+ (func (export "call-9") (type $out-i32)
+ (call_indirect (type $out-i32) (i32.const 9))
+ )
+)
+
+(invoke "call-8")
+
+#assertTopStack < i32> 65 "call_indirect_result1"
+
+(invoke "call-9")
+
+#assertTopStack < i32> 66 "call_indirect_result2"
+
+#assertFunction 0 [ ] -> [ i32 ] [ ] "call function 1 exists"
+#assertFunction 1 [ ] -> [ i32 ] [ ] "call function 2 exists"
+#assertFunction 2 [ ] -> [ i32 ] [ ] "call function 3 exists"
+#assertFunction 3 [ ] -> [ i32 ] [ ] "call function 4 exists"
+#assertFunction 4 [ ] -> [ i32 ] [ ] "call function 5 exists"
+#assertTableElem (8, 7) "table elem 8"
+#assertTableElem (9, 8) "table elem 9"
+#assertTable $tab 10 .Int "table three with elements"
+
+;; Test offset unfolding.
+
+(module
+ (table $t 10 funcref)
+ (type $typ (func))
+ (func)
+ (elem (offset (i32.const 0)) 0)
+ (elem (offset (nop) (i32.const 1)) 0)
+ (elem (offset (i32.const 2) (nop)) 0)
+ (elem $t (offset (i32.const 3)) 0)
+ (elem $t (offset (nop) (i32.const 4)) 0)
+ (elem $t (offset (i32.const 5) (nop)) 0)
+
+ (elem (offset (i32.const 6 (nop))) 0)
+ (elem $t (offset (i32.const 7 (nop))) 0)
+
+ (global $g i32 (i32.const 8))
+ (global $h i32 (i32.const 9))
+
+ (elem (offset (global.get $g)) 0)
+ (elem $t (offset (global.get $h)) 0)
+
+ (func $main (local i32)
+ (local.set 0 (i32.const 7))
+ loop
+ (local.get 0)
+ (call_indirect (type $typ))
+ (i32.sub (local.get 0) (i32.const 1))
+ (local.tee 0)
+ (i32.eqz)
+ (br_if 1)
+ (br 0)
+ end
+ )
+
+ (start $main)
+)
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/text2abstract.wast b/docs/runtimeverification-wasm-semantics/tests/simple/text2abstract.wast
new file mode 100644
index 000000000..d7f9e4a2d
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/text2abstract.wast
@@ -0,0 +1,157 @@
+(module)
+
+(module $id
+ (func (export "foo") (param $a i32) (result i32)
+ local.get $a
+ )
+
+ (func (export "bar") (param $a i32) (result i32)
+ block (result i32)
+ local.get $a
+ end
+ )
+
+ (func (export "baz") (param $a i32) (result i32)
+ loop (result i32)
+ local.get $a
+ end
+ )
+
+ (func (export "baf") (param $a i32) (result i32)
+ i32.const 1
+ if (result i32)
+ local.get $a
+ else
+ local.get $a
+ end
+ )
+
+ (func (export "bag") (param $a i32) (result i32)
+ i32.const 0
+ if (result i32)
+ local.get $a
+ else
+ local.get $a
+ end
+ )
+
+ (func $far (param $a i32) (result i32) (local $b i64)
+ local.get $a
+ )
+)
+
+(assert_return (invoke "foo" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "bar" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "baz" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "baf" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "bag" (i32.const 7)) (i32.const 7))
+
+#assertFunction 5 [ i32 ] -> [ i32 ] [ i64 ] "identifiers are erased inside module"
+
+#clearConfig
+
+;; With sugared blocks
+
+(module $id
+
+(type $i32->i32 (func (param i32) (result i32)))
+
+ (func (export "foo") (param $a i32) (result i32)
+ (local.get $a)
+ )
+
+ (func (export "bar") (type 0) (param $a i32) (result i32)
+ (block (result i32)
+ (local.get $a))
+ )
+
+ (func (export "baz") (type $i32->i32) (param $a i32) (result i32)
+ (loop (result i32)
+ (local.get $a))
+ )
+
+ (func (export "baf") (param $a i32) (result i32)
+ i32.const 1
+ (if (result i32)
+ (then (local.get $a))
+ (else (local.get $a))
+ )
+ )
+
+ (func (export "bag") (param $a i32) (result i32)
+ i32.const 0
+ (if (result i32)
+ (then (local.get $a))
+ (else (local.get $a))
+ )
+ )
+)
+
+(assert_return (invoke "foo" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "bar" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "baz" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "baf" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "bag" (i32.const 7)) (i32.const 7))
+
+#clearConfig
+
+(type (func (param i32) (result i32)))
+
+(func $foo (type 0) (param $a i32) (result i32)
+ local.get $a
+)
+(export "foo" (func 0))
+
+(func $bar (type 0) (param $a i32) (result i32)
+ block (result i32)
+ local.get $a
+ end
+)
+ (export "bar" (func 1))
+
+(func $baz (type 0) (param $a i32) (result i32)
+ loop (result i32)
+ local.get $a
+ end
+)
+(export "baz" (func 2))
+
+(func $baf (type 0) (param $a i32) (result i32)
+ i32.const 1
+ if (result i32)
+ local.get $a
+ else
+ local.get $a
+ end
+)
+(export "baf" (func 3))
+
+(func $bag (type 0) (param $a i32) (result i32)
+ i32.const 0
+ if (result i32)
+ local.get $a
+ else
+ local.get $a
+ end
+)
+(export "bag" (func 4))
+
+(func $far (type 0) (param $a i32) (result i32) (local $b i64)
+ local.get $a
+)
+
+(assert_return (invoke "foo" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "bar" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "baz" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "baf" (i32.const 7)) (i32.const 7))
+(assert_return (invoke "bag" (i32.const 7)) (i32.const 7))
+
+#assertFunction 5 [ i32 ] -> [ i32 ] [ i64 ] "identifiers are erased outside module"
+
+(type (func))
+
+(func $fir (type 1) (local i64) (local $a i32))
+
+#assertFunction 6 [ ] -> [ ] [ i64 i32 ] "identifiers are erased inside module"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/unicode.wast b/docs/runtimeverification-wasm-semantics/tests/simple/unicode.wast
new file mode 100644
index 000000000..33cf24122
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/unicode.wast
@@ -0,0 +1,39 @@
+(module
+ (memory 1)
+ (data (i32.const 0) "~!@#$%\u{1}\u{11}\u{334}\u{EDFF}\u{BBBBB}\u{10EFEF}")
+ (func (export "load8_u") (param $i i32) (result i64)
+ (i64.load8_u offset=0 (local.get $i))
+ )
+ (func (export "load16_u") (param $i i32) (result i64)
+ (i64.load16_u offset=0 (local.get $i))
+ )
+ (func (export "load32_u") (param $i i32) (result i64)
+ (i64.load32_u offset=0 (local.get $i))
+ )
+)
+
+(assert_return (invoke "load8_u" (i32.const 0)) (i64.const 126))
+(assert_return (invoke "load8_u" (i32.const 3)) (i64.const 35))
+(assert_return (invoke "load8_u" (i32.const 6)) (i64.const 1))
+(assert_return (invoke "load8_u" (i32.const 9)) (i64.const 180))
+(assert_return (invoke "load8_u" (i32.const 11)) (i64.const 183))
+(assert_return (invoke "load8_u" (i32.const 14)) (i64.const 187))
+(assert_return (invoke "load8_u" (i32.const 15)) (i64.const 174))
+
+(assert_return (invoke "load16_u" (i32.const 0)) (i64.const 8574))
+(assert_return (invoke "load16_u" (i32.const 1)) (i64.const 16417))
+(assert_return (invoke "load16_u" (i32.const 2)) (i64.const 9024))
+(assert_return (invoke "load16_u" (i32.const 4)) (i64.const 9508))
+(assert_return (invoke "load16_u" (i32.const 12)) (i64.const 62143))
+(assert_return (invoke "load16_u" (i32.const 13)) (i64.const 48114))
+(assert_return (invoke "load16_u" (i32.const 16)) (i64.const 62651))
+
+(assert_return (invoke "load32_u" (i32.const 2)) (i64.const 623125312))
+(assert_return (invoke "load32_u" (i32.const 3)) (i64.const 19211299))
+(assert_return (invoke "load32_u" (i32.const 6)) (i64.const 3033272577))
+(assert_return (invoke "load32_u" (i32.const 7)) (i64.const 4004826129))
+(assert_return (invoke "load32_u" (i32.const 11)) (i64.const 3153248183))
+(assert_return (invoke "load32_u" (i32.const 16)) (i64.const 3213817019))
+(assert_return (invoke "load32_u" (i32.const 19)) (i64.const 44991))
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/simple/variables.wast b/docs/runtimeverification-wasm-semantics/tests/simple/variables.wast
new file mode 100644
index 000000000..a04736237
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/simple/variables.wast
@@ -0,0 +1,62 @@
+;; Test locals
+
+init_locals < i32 > 0 : < i32 > 0 : < i32 > 0 : .ValStack
+
+(i32.const 43)
+(local.set 0)
+#assertLocal 0 < i32 > 43 "set_local"
+
+(i32.const 55)
+(local.set 1)
+(local.get 1)
+#assertTopStack < i32 > 55 "set_local stack"
+#assertLocal 1 < i32 > 55 "set_local"
+
+(i32.const 67)
+(local.tee 2)
+#assertTopStack < i32 > 67 "tee_local stack"
+#assertLocal 2 < i32 > 67 "tee_local local"
+
+;; Test globals
+
+(module
+ (global (mut i32) (i32.const 0))
+ (global $someglobal (mut i32) (i32.const 0))
+
+ (func
+ (i32.const 43)
+ (global.set 0)
+ )
+
+ (func (export "set")
+ (i32.const 55)
+ (global.set $someglobal)
+ )
+
+ (start 0)
+)
+#assertGlobal 0 < i32 > 43 "set_global"
+
+(invoke "set")
+#assertGlobal $someglobal < i32 > 55 "set_global"
+
+;; Test global folded forms
+
+#clearConfig
+
+(module
+ (global (mut i32) (i32.const 0))
+ (global (mut i32) (i32.const 0))
+
+ (func
+ (global.set 1 (i32.const 99))
+ (global.set 0 (i32.const 77))
+ )
+
+ (start 0)
+)
+
+#assertGlobal 1 < i32 > 99 "set_global folded"
+#assertGlobal 0 < i32 > 77 "set_global folded 2"
+
+#clearConfig
diff --git a/docs/runtimeverification-wasm-semantics/tests/success-k.out b/docs/runtimeverification-wasm-semantics/tests/success-k.out
new file mode 100644
index 000000000..c25e493df
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/success-k.out
@@ -0,0 +1,3 @@
+
+ .
+
diff --git a/docs/runtimeverification-wasm-semantics/tests/success-llvm.out b/docs/runtimeverification-wasm-semantics/tests/success-llvm.out
new file mode 100644
index 000000000..873d19486
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/tests/success-llvm.out
@@ -0,0 +1,62 @@
+
+
+ .
+
+
+
+ .
+
+
+ .ValStack
+
+
+
+ .Map
+
+
+ .Int
+
+
+
+ .Map
+
+
+ .Map
+
+
+ .ModuleInstCellMap
+
+
+ 0
+
+
+
+ .FuncDefCellMap
+
+
+ 0
+
+
+ .TabInstCellMap
+
+
+ 0
+
+
+ .MemInstCellMap
+
+
+ 0
+
+
+ .GlobalInstCellMap
+
+
+ 0
+
+
+
+ true
+
+
+
diff --git a/docs/runtimeverification-wasm-semantics/wasm-text.md b/docs/runtimeverification-wasm-semantics/wasm-text.md
new file mode 100644
index 000000000..a5e8c34d9
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/wasm-text.md
@@ -0,0 +1,1082 @@
+WebAssembly Text Format
+=======================
+
+```k
+require "wasm.md"
+require "data.md"
+
+module WASM-TEXT-SYNTAX
+ imports WASM-TEXT
+ imports WASM-SYNTAX
+ imports WASM-TOKEN-SYNTAX
+endmodule
+```
+
+Wasm Tokens
+-----------
+
+`WASM-TOKEN-SYNTAX` module defines the tokens used in parsing programs.
+
+```k
+module WASM-TOKEN-SYNTAX
+```
+
+### Strings
+
+In WebAssembly, strings are defined differently to K's built-in strings, so we have to write the definition of WebAssembly `WasmString` in a separate module, and use the module just for parsing the program.
+Note that you cannot use a normal K `String` in any production definitions, because the definitions of `String` and `WasmString` overlap, and the K tokenizer does not support ambiguity.
+
+```k
+ syntax WasmStringToken ::= r"\\\"(([^\\\"\\\\])|(\\\\[0-9a-fA-F]{2})|(\\\\t)|(\\\\n)|(\\\\r)|(\\\\\\\")|(\\\\')|(\\\\\\\\)|(\\\\u\\{[0-9a-fA-F]{1,6}\\}))*\\\"" [token]
+ // -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
+```
+
+### Identifiers
+
+In WebAssembly, identifiers are defined by the regular expression below.
+
+```k
+ syntax IdentifierToken ::= r"\\$[0-9a-zA-Z!$%&'*+/<>?_`|~=:\\@^.-]+" [token]
+ // ----------------------------------------------------------------------------
+```
+
+### Integers
+
+In WebAssembly, integers could be represented in either the decimal form or hexadecimal form.
+In both cases, digits can optionally be separated by underscores.
+
+```k
+ syntax WasmIntToken ::= r"[\\+-]?[0-9]+(_[0-9]+)*" [token]
+ | r"[\\+-]?0x[0-9a-fA-F]+(_[0-9a-fA-F]+)*" [token]
+ // ------------------------------------------------------------------------
+```
+
+### Layout
+
+WebAssembly allows for block comments using `(;` and `;)`, and line comments using `;;`.
+Additionally, white-space is skipped/ignored.
+Declaring regular expressions of sort `#Layout` infroms the K lexer to drop these tokens.
+
+```k
+ syntax #Layout ::= r"\\(;([^;]|(;+([^;\\)])))*;\\)" [token]
+ | r";;[^\\n\\r]*" [token]
+ | r"[\\ \\n\\r\\t]" [token]
+ // -----------------------------------------------------------
+```
+
+```k
+endmodule
+```
+
+Wasm Textual Format Syntax
+--------------------------
+
+### Values
+
+```k
+module WASM-TEXT-COMMON-SYNTAX
+ imports WASM-COMMON-SYNTAX
+
+ syntax WasmInt ::= Int
+ syntax WasmInt ::= WasmIntToken [klabel(WasmInt), avoid, symbol, function]
+
+ syntax Index ::= Identifier
+ // ---------------------------
+```
+
+### Instructions
+
+#### Plain Instructions
+
+```k
+ syntax PlainInstr ::= "br" Index
+ | "br_if" Index
+ | "br_table" ElemSegment
+ | "call" Index
+ | "global.get" Index
+ | "global.set" Index
+ | "local.get" Index
+ | "local.set" Index
+ | "local.tee" Index
+ // ---------------------------------------
+
+ syntax PlainInstr ::= IValType "." StoreOpM
+ | FValType "." StoreOpM
+ | IValType "." LoadOpM
+ | FValType "." LoadOpM
+ syntax StoreOpM ::= StoreOp | StoreOp MemArg
+ syntax LoadOpM ::= LoadOp | LoadOp MemArg
+ syntax MemArg ::= OffsetArg | AlignArg | OffsetArg AlignArg
+ syntax OffsetArg ::= "offset=" WasmInt
+ syntax AlignArg ::= "align=" WasmInt
+ // ---------------------------------------
+```
+
+#### Block Instructions
+
+```k
+ syntax Instr ::= BlockInstr
+ // ---------------------------
+
+ syntax BlockInstr ::= "block" OptionalId TypeDecls Instrs "end" OptionalId
+ | "loop" OptionalId TypeDecls Instrs "end" OptionalId
+ | "if" OptionalId TypeDecls Instrs "else" OptionalId Instrs "end" OptionalId
+ | "if" OptionalId TypeDecls Instrs "end" OptionalId
+ // ------------------------------------------------------------------------------------------------
+```
+
+##### Folded Instructions
+
+Folded instructions are a syntactic sugar where expressions can be grouped using parentheses for higher readability.
+
+```k
+ syntax Instr ::= FoldedInstr
+ // ----------------------------
+```
+
+One type of folded instruction are `PlainInstr`s wrapped in parentheses and optionally includes nested folded instructions to indicate its operands.
+
+```k
+ syntax FoldedInstr ::= "(" PlainInstr Instrs ")"
+ | "(" PlainInstr ")" [prefer]
+ // ---------------------------------------------------------
+
+ syntax FoldedInstr ::= "(" "block" OptionalId TypeDecls Instrs ")"
+ | "(" "loop" OptionalId TypeDecls Instrs ")"
+ | "(" "if" OptionalId TypeDecls Instrs "(" "then" Instrs ")" ")"
+ | "(" "if" OptionalId TypeDecls Instrs "(" "then" Instrs ")" "(" "else" Instrs ")" ")"
+ // -----------------------------------------------------------------------------------------------------------
+```
+
+### Types
+
+```k
+ syntax TypeDefn ::= "(type" OptionalId "(" "func" TypeDecls ")" ")"
+ // -------------------------------------------------------------------
+
+ syntax TextLimits ::= Int | Int Int
+ // -----------------------------------
+```
+
+### Exports
+
+Exports can be declared like regular functions, memories, etc., by giving an inline export declaration.
+In that case, it simply desugars to the definition followed by an export of it.
+If no identifer is present, one must be introduced so that the export can refer to it.
+Note that it is possible to define multiple exports inline, i.e. export a single entity under many names.
+
+```k
+ syntax ExportDefn ::= "(" "export" WasmString "(" Externval ")" ")"
+ // -------------------------------------------------------------------
+
+ syntax InlineExport ::= "(" "export" WasmString ")"
+ // ----------------------------------------------------
+```
+
+### Imports
+
+```k
+ syntax ImportDefn ::= "(" "import" WasmString WasmString ImportDesc ")"
+ // -----------------------------------------------------------------------
+```
+
+Imports can be declared like regular functions, memories, etc., by giving an inline import declaration.
+
+```k
+ syntax InlineImport ::= "(" "import" WasmString WasmString ")"
+ // --------------------------------------------------------------
+```
+
+The following is the text format representation of an import specification.
+
+```k
+ syntax ImportDesc ::= "(" "func" OptionalId TypeUse ")" [klabel(funcImportDesc)]
+ | "(" "global" OptionalId TextFormatGlobalType ")" [klabel(globImportDesc)]
+ | "(" "table" OptionalId TableType ")" [klabel( tabImportDesc)]
+ | "(" "memory" OptionalId MemType ")" [klabel( memImportDesc)]
+ // -----------------------------------------------------------------------------------------------
+```
+
+### Functions
+
+```k
+ syntax FuncDefn ::= "(" "func" OptionalId FuncSpec ")"
+ syntax FuncSpec ::= TypeUse LocalDecls Instrs
+ | InlineImport TypeUse
+ | InlineExport FuncSpec
+ // -----------------------------------------
+```
+
+#### Function Local Declaration
+
+```k
+ syntax LocalDecl ::= "(" LocalDecl ")" [bracket]
+ | "local" ValTypes
+ | "local" Identifier ValType
+ syntax LocalDecls ::= List{LocalDecl , ""} [klabel(listLocalDecl)]
+ // -------------------------------------------------------------------------
+```
+
+### Tables
+
+```k
+ syntax TableDefn ::= "(" "table" OptionalId TableSpec ")"
+ syntax TableSpec ::= TableType
+ | TableElemType "(" "elem" ElemSegment ")"
+ | InlineImport TableType
+ | InlineExport TableSpec
+ // -------------------------------------------
+
+ syntax TableType ::= TextLimits TableElemType
+ syntax TableElemType ::= "funcref"
+ // ----------------------------------
+```
+
+### Memories
+
+```k
+ syntax MemoryDefn ::= "(" "memory" OptionalId MemorySpec ")"
+ // ------------------------------------------------------------
+
+ syntax MemorySpec ::= MemType
+ // --------------------------------
+
+ syntax MemorySpec ::= "(" "data" DataString ")"
+ | InlineImport MemType
+ | InlineExport MemorySpec
+ // ---------------------------------------------
+
+ syntax MemType ::= TextLimits
+ // --------------------------------
+```
+
+### Globals
+
+```k
+ syntax GlobalDefn ::= "(" "global" OptionalId GlobalSpec ")"
+ syntax GlobalSpec ::= TextFormatGlobalType Instr
+ | InlineImport TextFormatGlobalType
+ | InlineExport GlobalSpec
+ // ---------------------------------------------
+
+ syntax TextFormatGlobalType ::= ValType | "(" "mut" ValType ")"
+ // ---------------------------------------------------------------
+```
+
+### Offset
+
+The `elem` and `data` initializers take an offset, which is an instruction.
+This is not optional.
+
+```k
+ syntax Offset ::= "(" "offset" Instrs ")"
+ // -----------------------------------------
+```
+
+The offset can either be specified explicitly with the `offset` key word, or be a single instruction.
+
+```k
+ syntax Offset ::= Instrs
+ // ------------------------
+```
+
+### Element Segments
+
+```k
+
+ syntax ElemDefn ::= "(" "elem" Index Offset ElemSegment ")"
+ | "(" "elem" Offset ElemSegment ")"
+ | "(" "elem" Offset "func" ElemSegment ")"
+ // ------------------------------------------------------------
+```
+
+### Data Segments
+
+```k
+ syntax DataDefn ::= "(" "data" Index Offset DataString ")"
+ | "(" "data" Offset DataString ")"
+ // ----------------------------------------------------
+```
+
+### Start Function
+
+```k
+ syntax StartDefn ::= "(" "start" Index ")"
+ // ------------------------------------------
+```
+
+### Modules
+
+Modules are defined as a sequence of definitions, that may come in any order.
+The only requirements are that all imports must precede all other definitions, and that there may be at most one start function.
+
+```k
+ syntax Stmt ::= ModuleDecl
+ syntax ModuleDecl ::= "(" "module" OptionalId Defns ")"
+ // -------------------------------------------------------
+```
+
+```k
+endmodule
+```
+
+Translation from Text Format to Core Format
+-------------------------------------------
+
+```k
+module WASM-TEXT
+ imports WASM-TEXT-COMMON-SYNTAX
+ imports WASM
+```
+
+The text format is a concrete syntax for Wasm.
+It allows specifying instructions in a folded, S-expression like format, and a few other syntactic sugars.
+Most instructions, those in the sort `PlainInstr`, have identical keywords in the abstract and concrete syntax, and can be used directly.
+
+### Text Integers
+
+All integers given in the text format are automatically turned into regular integers.
+That means converting between hexadecimal and decimal when necessary, and removing underscores.
+
+**TODO**: Symbolic reasoning for sort `WasmIntToken` not tested yet.
+In the future should investigate which direction the subsort should go.
+(`WasmIntToken` under `Int`/`Int` under `WasmIntToken`)
+
+```k
+ rule `WasmInt`(VAL) => WasmIntToken2Int(VAL)
+
+ syntax String ::= WasmIntToken2String ( WasmIntToken ) [function, total, hook(STRING.token2string)]
+ syntax Int ::= WasmIntTokenString2Int ( String ) [function]
+ | WasmIntToken2Int ( WasmIntToken ) [function]
+ // --------------------------------------------------------------------
+ rule WasmIntTokenString2Int(S) => String2Base(replaceFirst(S, "0x", ""), 16) requires findString(S, "0x", 0) =/=Int -1
+ rule WasmIntTokenString2Int(S) => String2Base( S, 10) requires findString(S, "0x", 0) ==Int -1
+
+ rule WasmIntToken2Int(VAL) => WasmIntTokenString2Int(replaceAll(WasmIntToken2String(VAL), "_", ""))
+```
+
+### Identifiers
+
+When we want to specify an identifier, we can do so with the following helper function.
+
+```k
+ syntax IdentifierToken ::= String2Identifier(String) [function, total, hook(STRING.string2token)]
+ // ------------------------------------------------------------------------------------------------------
+```
+
+### Looking up Indices
+
+In the abstract Wasm syntax, indices are always integers.
+In the text format, we extend indices to incorporate identifiers.
+We also enable context lookups with identifiers.
+
+```k
+ rule #ContextLookup(IDS:Map, ID:Identifier) => {IDS [ ID ]}:>Int
+ requires ID in_keys(IDS)
+```
+
+### Desugaring
+
+The text format is one of the concrete formats of Wasm.
+Every concrete format maps to a common structure, described as an abstract syntax.
+The function `text2abstract` is a partial function which maps valid programs in the text format to the abstract format.
+Some classes of invalid programs, such as those where an identifier appears in a context in which it is not declared, are undefined.
+
+The function deals with the desugarings which are context dependent.
+Other desugarings are either left for runtime or expressed as macros (for now).
+
+#### Unfolding Abbreviations
+
+```k
+ syntax Stmts ::= unfoldStmts ( Stmts ) [function]
+ syntax Defns ::= unfoldDefns ( Defns ) [function]
+ | #unfoldDefns ( Defns , Int, TypesInfo ) [function]
+ // -------------------------------------------------------------------
+ rule unfoldStmts(( module OID:OptionalId DS) SS) => ( module OID unfoldDefns(DS) ) unfoldStmts(SS)
+ rule unfoldStmts(.Stmts) => .Stmts
+ rule unfoldStmts(S SS) => S unfoldStmts(SS) [owise]
+
+ rule unfoldDefns(DS) => #unfoldDefns(DS, 0, types2indices(DS))
+ rule #unfoldDefns(.Defns, _, _) => .Defns
+ rule #unfoldDefns(D:Defn DS, I, TI) => D #unfoldDefns(DS, I, TI) [owise]
+
+ syntax Defns ::= Defns "appendDefn" Defn [function]
+ // ---------------------------------------------------
+ rule (D DS) appendDefn D' => D (DS appendDefn D')
+ rule .Defns appendDefn D' => D' .Defns
+```
+
+#### Types
+
+The text format allows declaring a function without referencing a module-level type for that function.
+If there is a module-level type matching the function type, the function is automatically assigned to that type.
+The `TypeDecl` of the type is kept, since it may contain parameter identifiers.
+If there is no matching module-level type, a new such type is inserted *at the end of the module*.
+Since the inserted type is module-level, any subsequent functions declaring the same type will not implicitly generate a new type.
+
+```k
+ rule #unfoldDefns(( func _OID:OptionalId (TDECLS:TypeDecls => (type {M [asFuncType(TDECLS)]}:>Int) TDECLS) _LOCALS:LocalDecls _BODY:Instrs ) _DS
+ , _I
+ , #ti(... t2i: M))
+ requires asFuncType(TDECLS) in_keys(M)
+
+ rule #unfoldDefns(( func _OID:OptionalId (TDECLS:TypeDecls => (type N) TDECLS) _LOCALS:LocalDecls _BODY:Instrs ) (DS => DS appendDefn (type (func TDECLS)))
+ , _I
+ , #ti(... t2i: M => M [ asFuncType(TDECLS) <- N ], count: N => N +Int 1))
+ requires notBool asFuncType(TDECLS) in_keys(M)
+
+ rule #unfoldDefns(( func OID:OptionalId TUSE:TypeUse LOCALS:LocalDecls BODY) DS, I, TI)
+ => (( func OID TUSE LOCALS unfoldInstrs(BODY)))
+ #unfoldDefns(DS, I, TI)
+ requires notBool isTypeDecls(TUSE)
+
+ rule #unfoldDefns(( import MOD NAME (func OID:OptionalId TDECLS:TypeDecls )) DS, I, #ti(... t2i: M) #as TI)
+ => (import MOD NAME (func OID (type {M [asFuncType(TDECLS)]}:>Int) TDECLS ))
+ #unfoldDefns(DS, I, TI)
+ requires asFuncType(TDECLS) in_keys(M)
+
+ rule #unfoldDefns(( import MOD NAME (func OID:OptionalId TDECLS:TypeDecls)) DS, I, #ti(... t2i: M, count: N))
+ => (import MOD NAME (func OID (type N) TDECLS))
+ #unfoldDefns(DS appendDefn (type (func TDECLS)), I, #ti(... t2i: M [asFuncType(TDECLS) <- N], count: N +Int 1))
+ requires notBool asFuncType(TDECLS) in_keys(M)
+
+ syntax TypesInfo ::= #ti( t2i: Map, count: Int )
+ syntax TypesInfo ::= types2indices( Defns ) [function]
+ | #types2indices( Defns, TypesInfo ) [function]
+ // ------------------------------------------------------------------
+ rule types2indices(DS) => #types2indices(DS, #ti(... t2i: .Map, count: 0))
+
+ rule #types2indices(.Defns, TI) => TI
+
+ rule #types2indices((type _OID (func TDECLS)) DS, #ti(... t2i: M, count: N))
+ => #types2indices(DS, #ti(... t2i: M [ asFuncType(TDECLS) <- (M [ asFuncType(TDECLS) ] orDefault N) ], count: N +Int 1))
+
+ rule #types2indices(_D DS, M) => #types2indices(DS, M) [owise]
+```
+
+#### Functions
+
+```k
+ rule #unfoldDefns(( func OID:OptionalId (import MOD NAME) TUSE) DS, I, M)
+ => #unfoldDefns(( import MOD NAME (func OID TUSE) ) DS, I, M)
+
+ rule #unfoldDefns(( func EXPO:InlineExport SPEC:FuncSpec ) DS, I, M)
+ => #unfoldDefns(( func #freshId(I) EXPO SPEC) DS, I +Int 1, M)
+
+ rule #unfoldDefns(( func ID:Identifier ( export ENAME ) SPEC:FuncSpec ) DS, I, M)
+ => ( export ENAME ( func ID ) ) #unfoldDefns(( func ID SPEC ) DS, I, M)
+```
+
+#### Tables
+
+```k
+ rule #unfoldDefns(( table funcref ( elem ELEM ) ) DS, I, M)
+ => #unfoldDefns(( table #freshId(I) funcref ( elem ELEM ) ) DS, I +Int 1, M)
+
+ rule #unfoldDefns(( table ID:Identifier funcref ( elem ELEM ) ) DS, I, M)
+ => ( table ID #lenElemSegment(ELEM) #lenElemSegment(ELEM) funcref ):TableDefn
+ ( elem ID (offset (i32.const 0) .Instrs) ELEM )
+ #unfoldDefns(DS, I, M)
+
+ rule #unfoldDefns(( table OID:OptionalId (import MOD NAME) TT:TableType ) DS, I, M)
+ => #unfoldDefns(( import MOD NAME (table OID TT) ) DS, I, M)
+
+ rule #unfoldDefns(( table EXPO:InlineExport SPEC:TableSpec ) DS, I, M)
+ => #unfoldDefns(( table #freshId(I) EXPO SPEC ) DS, I +Int 1, M)
+
+ rule #unfoldDefns(( table ID:Identifier ( export ENAME ) SPEC:TableSpec ) DS, I, M)
+ => ( export ENAME ( table ID ) ) #unfoldDefns(( table ID SPEC ) DS, I, M)
+```
+
+#### Memories
+
+```k
+ rule #unfoldDefns(( memory ( data DATA ) ) DS, I, M)
+ => #unfoldDefns(( memory #freshId(I) ( data DATA ) ) DS, I +Int 1, M)
+
+ rule #unfoldDefns(( memory ID:Identifier ( data DATA ) ) DS, I, M)
+ => ( memory ID #lengthDataPages(DATA) #lengthDataPages(DATA) ):MemoryDefn
+ ( data ID (offset (i32.const 0) .Instrs) DATA )
+ #unfoldDefns(DS, I, M)
+
+ rule #unfoldDefns(( memory OID:OptionalId (import MOD NAME) MT:MemType ) DS, I, M)
+ => #unfoldDefns(( import MOD NAME (memory OID MT ) ) DS, I, M)
+
+ rule #unfoldDefns(( memory EXPO:InlineExport SPEC:MemorySpec ) DS, I, M)
+ => #unfoldDefns(( memory #freshId(I:Int) EXPO SPEC ) DS, I +Int 1, M)
+
+ rule #unfoldDefns(( memory ID:Identifier ( export ENAME ) SPEC:MemorySpec ) DS, I, M)
+ => ( export ENAME ( memory ID ) ) #unfoldDefns( ( memory ID SPEC ) DS, I, M)
+
+ syntax Int ::= #lengthDataPages ( DataString ) [function]
+ // ---------------------------------------------------------
+ rule #lengthDataPages(DS:DataString) => lengthBytes(#DS2Bytes(DS)) up/Int #pageSize()
+```
+
+#### Globals
+
+```k
+ syntax GlobalType ::= asGMut (TextFormatGlobalType) [function]
+ // --------------------------------------------------------------
+ rule asGMut ( (mut T:ValType ) ) => var T
+ rule asGMut ( T:ValType ) => const T
+
+ rule #unfoldDefns((( global OID TYP:TextFormatGlobalType IS:Instr) => #global(... type: asGMut(TYP), init: unfoldInstrs(IS .Instrs), metadata: OID)) _DS, _I, _M)
+
+ rule #unfoldDefns(( global OID:OptionalId (import MOD NAME) TYP ) DS, I, M)
+ => #unfoldDefns(( import MOD NAME (global OID TYP ) ) DS, I, M)
+
+ rule #unfoldDefns(( global EXPO:InlineExport SPEC:GlobalSpec ) DS, I, M)
+ => #unfoldDefns(( global #freshId(I) EXPO SPEC ) DS, I +Int 1, M)
+
+ rule #unfoldDefns(( global ID:Identifier ( export ENAME ) SPEC:GlobalSpec ) DS, I, M)
+ => ( export ENAME ( global ID ) ) #unfoldDefns(( global ID SPEC ) DS, I, M)
+```
+
+#### Element Segments
+
+```k
+ rule #unfoldDefns(((elem OFFSET func ES) => (elem OFFSET ES)) _DS, _I, _M)
+ rule #unfoldDefns(((elem OFFSET:Offset ES ) => ( elem 0 OFFSET ES )) _DS, _I, _M)
+ rule #unfoldDefns(((elem IDX OFFSET:Instrs ES ) => ( elem IDX ( offset OFFSET ) ES )) _DS, _I, _M)
+
+ rule #unfoldDefns((elem IDX (offset IS) ES) DS, I, M) => (elem IDX (offset unfoldInstrs(IS)) ES) #unfoldDefns(DS, I, M)
+```
+
+#### Data Segments
+
+```k
+ rule #unfoldDefns(((data OFFSET:Offset DATA ) => ( data 0 OFFSET DATA )) _DS, _I, _M)
+ rule #unfoldDefns(((data IDX OFFSET:Instrs DATA ) => ( data IDX ( offset OFFSET ) DATA )) _DS, _I, _M)
+
+ rule #unfoldDefns((data IDX (offset IS) DATA) DS, I, M) => (data IDX (offset unfoldInstrs(IS)) DATA) #unfoldDefns(DS, I, M)
+```
+
+#### Instructions
+
+```k
+ syntax Instrs ::= unfoldInstrs ( Instrs ) [function]
+ | #unfoldInstrs ( Instrs, Int, Map ) [function]
+ // ---------------------------------------------------------------
+ rule unfoldInstrs(IS) => #unfoldInstrs(IS, 0, .Map)
+ rule #unfoldInstrs(.Instrs, _, _) => .Instrs
+ rule #unfoldInstrs(I IS, DEPTH, M) => I #unfoldInstrs(IS, DEPTH, M) [owise]
+
+ syntax Instrs ::= Instrs "appendInstrs" Instrs [function]
+ | #appendInstrs ( Instrs, Instrs ) [function]
+ | #reverseInstrs ( Instrs, Instrs ) [function]
+ // --------------------------------------------------------------
+ rule IS appendInstrs IS' => #appendInstrs(#reverseInstrs(IS, .Instrs), IS')
+
+ rule #appendInstrs(I IS => IS, IS' => I IS')
+ rule #appendInstrs(.Instrs , IS') => IS'
+
+ rule #reverseInstrs(.Instrs, ACC) => ACC
+ rule #reverseInstrs(I IS => IS, ACC => I ACC)
+```
+
+##### Block Instructions
+
+In the text format, block instructions can have identifiers attached to them, and branch instructions can refer to these identifiers.
+Branching with an identifier is the same as branching to the label with that identifier.
+The correct label index is calculated by looking at whih depth the index occured and what depth execution is currently at.
+
+Conceptually, `br ID => br CURRENT_EXECUTION_DEPTH -Int IDENTIFIER_LABEL_DEPTH -Int 1`.
+
+```k
+ rule #unfoldInstrs(br ID:Identifier IS, DEPTH, M) => br DEPTH -Int {M [ ID ]}:>Int -Int 1 #unfoldInstrs(IS, DEPTH, M)
+ rule #unfoldInstrs(br_if ID:Identifier IS, DEPTH, M) => br_if DEPTH -Int {M [ ID ]}:>Int -Int 1 #unfoldInstrs(IS, DEPTH, M)
+ rule #unfoldInstrs(br_table ES:ElemSegment IS, DEPTH, M) => br_table elemSegment2Indices(ES, DEPTH, M) #unfoldInstrs(IS, DEPTH, M)
+
+ syntax ElemSegment ::= elemSegment2Indices( ElemSegment, Int, Map ) [function]
+ // ------------------------------------------------------------------------------
+ rule elemSegment2Indices(.ElemSegment , _DEPTH, _M) => .ElemSegment
+ rule elemSegment2Indices(ID:Identifier ES, DEPTH, M) => DEPTH -Int {M [ ID ]}:>Int -Int 1 elemSegment2Indices(ES, DEPTH, M)
+ rule elemSegment2Indices(E ES, DEPTH, M) => E elemSegment2Indices(ES, DEPTH, M) [owise]
+```
+
+There are several syntactic sugars for block instructions, some of which may have identifiers.
+The same identifier can optionally be repeated at the end of the block instruction (to mark which block is ending) and on the branches in an `if`.
+`if` blocks may omit the `else`-branch, as long as the type declaration is empty.
+
+```k
+ rule #unfoldInstrs( (block ID:Identifier TDS IS end _OID' => block TDS IS end) _IS', DEPTH, M => M [ ID <- DEPTH ])
+ rule #unfoldInstrs(block TDS:TypeDecls IS end IS', DEPTH, M) => block TDS #unfoldInstrs(IS, DEPTH +Int 1, M) end #unfoldInstrs(IS', DEPTH, M)
+
+ rule #unfoldInstrs( (loop ID:Identifier TDS IS end _OID' => loop TDS IS end) _IS', DEPTH, M => M [ ID <- DEPTH ])
+ rule #unfoldInstrs(loop TDS:TypeDecls IS end IS', DEPTH, M) => loop TDS #unfoldInstrs(IS, DEPTH +Int 1, M) end #unfoldInstrs(IS', DEPTH, M)
+
+ // TODO: Only unfold empty else-branch if the type declaration is empty.
+ rule #unfoldInstrs( (if ID:Identifier TDS IS end _OID'' => if ID TDS IS else .Instrs end) _IS'', _DEPTH, _M)
+ rule #unfoldInstrs( (if TDS IS end _OID'' => if TDS IS else .Instrs end) _IS'', _DEPTH, _M)
+ rule #unfoldInstrs( (if ID:Identifier TDS IS else _OID':OptionalId IS' end _OID'' => if TDS IS else IS' end) _IS'', DEPTH, M => M [ ID <- DEPTH ])
+ rule #unfoldInstrs(if TDS IS else IS' end IS'', DEPTH, M) => if TDS #unfoldInstrs(IS, DEPTH +Int 1, M) else #unfoldInstrs(IS', DEPTH +Int 1, M) end #unfoldInstrs(IS'', DEPTH, M)
+```
+
+#### Folded Instructions
+
+```k
+ rule #unfoldInstrs(( PI:PlainInstr IS:Instrs ):FoldedInstr IS', DEPTH, M)
+ => (#unfoldInstrs(IS , DEPTH, M)
+ appendInstrs #unfoldInstrs(PI .Instrs, DEPTH, M))
+ appendInstrs #unfoldInstrs(IS' , DEPTH, M)
+ rule #unfoldInstrs(( PI:PlainInstr ):FoldedInstr IS', DEPTH, M)
+ => #unfoldInstrs(PI .Instrs, DEPTH, M)
+ appendInstrs #unfoldInstrs(IS' , DEPTH, M)
+```
+
+Another type of folded instruction is control flow blocks wrapped in parentheses, in which case the `end` keyword is omitted.
+
+```k
+ rule #unfoldInstrs(((block ID:Identifier TDS IS) => block ID TDS IS end) _IS', _DEPTH, _M)
+ rule #unfoldInstrs(((block TDS IS) => block TDS IS end) _IS', _DEPTH, _M)
+
+ rule #unfoldInstrs(((loop ID:Identifier TDS IS) => loop ID TDS IS end) _IS', _DEPTH, _M)
+ rule #unfoldInstrs(((loop TDS IS) => loop TDS IS end) _IS', _DEPTH, _M)
+
+ rule #unfoldInstrs(((if OID:OptionalId TDS COND (then IS)) => (if OID TDS COND (then IS) (else .Instrs))) _IS'', _DEPTH, _M)
+ rule #unfoldInstrs(((if ID:Identifier TDS COND (then IS) (else IS')) IS'':Instrs) => (COND appendInstrs if ID TDS IS else IS' end IS''), _DEPTH, _M)
+ rule #unfoldInstrs(((if TDS COND (then IS) (else IS')) IS'':Instrs) => (COND appendInstrs if TDS IS else IS' end IS''), _DEPTH, _M)
+```
+
+#### Structuring Modules
+
+The text format allows definitions to appear in any order in a module.
+In the abstract format, the module is a record, one for each type of definition.
+The following functions convert the text format module, given as a list of definitions, into the abstract format.
+In doing so, the respective ordering of all types of definitions are preserved.
+
+```k
+ syntax Stmts ::= structureModules ( Stmts ) [function]
+ // ------------------------------------------------------
+ rule structureModules((module OID:OptionalId DS) SS) => structureModule(DS, OID) structureModules(SS)
+ rule structureModules(.Stmts) => .Stmts
+ rule structureModules(S SS) => S structureModules(SS) [owise]
+
+ syntax ModuleDecl ::= structureModule ( Defns , OptionalId ) [function]
+ | #structureModule ( Defns , ModuleDecl ) [function]
+ // ------------------------------------------------------------------------
+ rule structureModule(DEFNS, OID) => #structureModule(#reverseDefns(DEFNS, .Defns), #emptyModule(OID))
+
+ rule #structureModule(.Defns, SORTED_MODULE) => SORTED_MODULE
+
+ rule #structureModule((T:TypeDefn DS:Defns => DS), #module(... types: TS => T TS))
+ rule #structureModule((I:ImportDefn DS:Defns => DS), #module(... importDefns: IS => I IS))
+ rule #structureModule((X:FuncDefn DS:Defns => DS), #module(... funcs: FS => X FS))
+ rule #structureModule((X:GlobalDefn DS:Defns => DS), #module(... globals: GS => X GS))
+ rule #structureModule((T:TableDefn DS:Defns => DS), #module(... tables: TS => T TS))
+ rule #structureModule((M:MemoryDefn DS:Defns => DS), #module(... mems: MS => M MS))
+ rule #structureModule((E:ExportDefn DS:Defns => DS), #module(... exports: ES => E ES))
+ rule #structureModule((I:DataDefn DS:Defns => DS), #module(... data: IS => I IS))
+ rule #structureModule((I:ElemDefn DS:Defns => DS), #module(... elem: IS => I IS))
+ rule #structureModule((S:StartDefn DS:Defns => DS), #module(... start: .Defns => S .Defns))
+
+ syntax Defns ::= #reverseDefns(Defns, Defns) [function]
+ // -------------------------------------------------------
+ rule #reverseDefns( .Defns , ACC) => ACC
+ rule #reverseDefns(D:Defn DS:Defns, ACC) => #reverseDefns(DS, D ACC)
+```
+
+### Replacing Identifiers and Unfolding Instructions
+
+The desugaring is done on the module level.
+First, if the program is just a list of definitions, that's an abbreviation for a single module.
+If not, we distribute the text to abstract transformation out over all the statements in the file.
+
+**TODO:**
+
+- Get rid of inline type declarations.
+ The text format allows specifying the type directly in the function header using the `param` and `result` keywords.
+ However, these will either be desugared to a new top-level `type` declaration or they must match an existing one.
+ In the abstract format, a function's type is a pointer to a top-level `type` declaration.
+ This could either be done by doing an initial pass to gather all type declarations, or they could be desugared locally, which is similar to what we do currently: `(func (type X) TDS:TDecls ... ) => (func (type X))` and `(func TDS:TDecls ...) => (type TDECLS) (func (type NEXT_TYPE_ID))`.
+- Remove module names.
+- Give the text format and abstract format different sorts, and have `text2abstract` handle the conversion.
+ Then identifiers and other text-only constructs can be completely removed from the abstract format.
+
+
+#### The Context
+
+The `Context` contains information of how to map text-level identifiers to corresponding indices.
+Record updates can currently not be done in a function rule which also does other updates, so we have helper functions to update specific fields.
+
+```k
+ syntax Context ::= ctx(localIds: Map, globalIds: Map, funcIds: Map, typeIds: Map)
+ | #freshCtx ( ) [function, total]
+ | #updateLocalIds ( Context , Map ) [function, total]
+ | #updateLocalIdsAux ( Context , Map , Bool ) [function, total]
+ | #updateFuncIds ( Context , Map ) [function, total]
+ | #updateFuncIdsAux ( Context , Map , Bool ) [function, total]
+ // -------------------------------------------------------------------------------------
+ rule #freshCtx ( ) => ctx(... localIds: .Map, globalIds: .Map, funcIds: .Map, typeIds: .Map)
+
+ rule #updateLocalIds(C, M) => #updateLocalIdsAux(C, M, false)
+ rule #updateLocalIdsAux(ctx(... localIds: (_ => M)), M, false => true)
+ rule #updateLocalIdsAux(C, _, true) => C
+
+ rule #updateFuncIds(C, M) => #updateFuncIdsAux(C, M, false)
+ rule #updateFuncIdsAux(ctx(... funcIds: (_ => M)), M, false => true)
+ rule #updateFuncIdsAux(C, _, true) => C
+```
+
+#### Traversing the Full Program
+
+The program is traversed in full once, context being gathered along the way.
+Since we do not have polymorphic functions available, we define one function per sort of syntactic construct we need to traverse, and for each type of list we encounter.
+
+```k
+ syntax Stmt ::= "#t2aStmt" "<" Context ">" "(" Stmt ")" [function]
+ syntax ModuleDecl ::= "#t2aModuleDecl" "<" Context ">" "(" ModuleDecl ")" [function]
+ syntax ModuleDecl ::= "#t2aModule" "<" Context ">" "(" ModuleDecl ")" [function]
+ syntax Defn ::= "#t2aDefn" "<" Context ">" "(" Defn ")" [function]
+ // ------------------------------------------------------------------------------------
+ rule text2abstract(DS:Defns) => text2abstract(( module DS ) .Stmts)
+ rule text2abstract(SS) => #t2aStmts<#freshCtx()>(structureModules(unfoldStmts(SS))) [owise]
+
+ rule #t2aStmt(M:ModuleDecl) => #t2aModuleDecl(M)
+ rule #t2aStmt(D:Defn) => #t2aDefn(D)
+ rule #t2aStmt(I:Instr) => #t2aInstr(I)
+ rule #t2aStmt<_>(S) => S [owise]
+
+ rule #t2aModuleDecl<_>(#module(... types: TS, funcs: FS, globals: GS, importDefns: IS) #as M) => #t2aModule(M)
+ rule #t2aModule(#module(... types: TS, funcs: FS, tables: TABS, mems: MS, globals: GS, elem: EL, data: DAT, start: S, importDefns: IS, exports: ES, metadata: #meta(... id: OID)))
+ => #module( ... types: #t2aDefns(TS)
+ , funcs: #t2aDefns(FS)
+ , tables: #t2aDefns(TABS)
+ , mems: #t2aDefns(MS)
+ , globals: #t2aDefns(GS)
+ , elem: #t2aDefns(EL)
+ , data: #t2aDefns(DAT)
+ , start: #t2aDefns(S)
+ , importDefns: #t2aDefns(IS)
+ , exports: #t2aDefns(ES)
+ , metadata: #meta(... id: OID, funcIds: FIDS, filename: .String)
+ )
+```
+
+#### Types
+
+```k
+ rule #t2aDefn<_>((type OID (func TDECLS))) => #type(... type: asFuncType(TDECLS), metadata: OID)
+```
+
+#### Imports
+
+```k
+ rule #t2aDefn(( import MOD NAME (func OID:OptionalId (type ID:Identifier) ))) => #import(MOD, NAME, #funcDesc(... id: OID:OptionalId, type: {TIDS[ID]}:>Int))
+ rule #t2aDefn(( import MOD NAME (func OID:OptionalId (type ID:Identifier) _:TypeDecls))) => #import(MOD, NAME, #funcDesc(... id: OID:OptionalId, type: {TIDS[ID]}:>Int))
+ rule #t2aDefn<_ >(( import MOD NAME (func OID:OptionalId (type IDX:Int) ))) => #import(MOD, NAME, #funcDesc(... id: OID:OptionalId, type: IDX))
+ rule #t2aDefn<_ >(( import MOD NAME (func OID:OptionalId (type IDX:Int ) _:TypeDecls))) => #import(MOD, NAME, #funcDesc(... id: OID:OptionalId, type: IDX))
+
+ rule #t2aDefn<_ >(( import MOD NAME (global OID:OptionalId TYP:TextFormatGlobalType))) => #import(MOD, NAME, #globalDesc(... id: OID:OptionalId, type: asGMut(TYP)))
+
+ rule #t2aDefn<_ >(( import MOD NAME (table OID:OptionalId LIM:TextLimits funcref))) => #import(MOD, NAME, #tableDesc(... id: OID:OptionalId, type: t2aLimits(LIM)))
+ rule #t2aDefn<_ >(( import MOD NAME (memory OID:OptionalId LIM:TextLimits ))) => #import(MOD, NAME, #memoryDesc(... id: OID:OptionalId, type: t2aLimits(LIM)))
+```
+
+#### Globals
+
+```k
+ rule #t2aDefn(#global(... type: GTYP, init: IS, metadata: OID)) => #global(... type: GTYP, init: #t2aInstrs(IS), metadata: OID)
+```
+
+#### Functions
+
+After unfolding, each type use in a function starts with an explicit reference to a module-level function.
+
+```k
+ rule #t2aDefn(( func OID:OptionalId T:TypeUse LS:LocalDecls IS:Instrs ))
+ => #func(... type: typeUse2typeIdx(T, TIDS)
+ , locals: locals2vectype(LS)
+ , body: #t2aInstrs <#updateLocalIds(C, #ids2Idxs(T, LS))>(IS)
+ , metadata: #meta(... id: OID, localIds: #ids2Idxs(T, LS))
+ )
+
+ syntax Int ::= typeUse2typeIdx ( TypeUse , Map ) [function]
+ // -----------------------------------------------------------
+ rule typeUse2typeIdx( (type IDX ) _:TypeDecls => (type IDX), _TIDS )
+
+ rule typeUse2typeIdx( (type ID:Identifier ) , TIDS ) => {TIDS [ ID ]}:>Int
+ rule typeUse2typeIdx( (type IDX:Int ) , _TIDS ) => IDX
+
+ syntax VecType ::= locals2vectype ( LocalDecls ) [function]
+ | #locals2vectype ( LocalDecls , ValTypes ) [function]
+ // -----------------------------------------------------------------------
+ rule locals2vectype(LDECLS) => #locals2vectype(LDECLS, .ValTypes)
+
+ rule #locals2vectype(.LocalDecls , VTYPES) => [ VTYPES ]
+ rule #locals2vectype(local VTYPES':ValTypes LDECLS:LocalDecls , VTYPES) => #locals2vectype(LDECLS , VTYPES + VTYPES')
+ rule #locals2vectype(local _ID:Identifier VTYPE:ValType LDECLS:LocalDecls , VTYPES) => #locals2vectype(LDECLS , VTYPES + VTYPE .ValTypes)
+```
+
+#### Tables
+
+```k
+ rule #t2aDefn<_>((table OID:OptionalId LIMITS:TextLimits funcref )) => #table(... limits: t2aLimits(LIMITS), metadata: OID)
+```
+
+#### Memories
+
+```k
+ rule #t2aDefn<_>((memory OID:OptionalId LIMITS:TextLimits )) => #memory(... limits: t2aLimits(LIMITS), metadata: OID)
+```
+
+```k
+ syntax Limits ::= t2aLimits(TextLimits) [function, total]
+ // --------------------------------------------------------------
+ rule t2aLimits(MIN:Int) => #limitsMin(MIN)
+ rule t2aLimits(MIN:Int MAX:Int) => #limits(MIN, MAX)
+```
+
+#### Start Function
+
+```k
+ rule #t2aDefn(( start ID:Identifier )) => #start({FIDS[ID]}:>Int)
+ requires ID in_keys(FIDS)
+ rule #t2aDefn<_>(( start I:Int )) => #start(I)
+```
+
+#### Element Segments
+
+Wasm currently supports only one table, so we do not need to resolve any identifiers.
+
+```k
+ rule #t2aDefn(( elem _:Index (offset IS) ES )) => #elem(0, #t2aInstrs(IS), #t2aElemSegment(ES) )
+
+ syntax Ints ::= "#t2aElemSegment" "<" Context ">" "(" ElemSegment ")" [function]
+ // --------------------------------------------------------------------------------
+ rule #t2aElemSegment(ID:Identifier ES) => {FIDS[ID]}:>Int #t2aElemSegment(ES)
+ requires ID in_keys(FIDS)
+ rule #t2aElemSegment(I:Int ES) => I #t2aElemSegment(ES)
+ rule #t2aElemSegment<_C>(.ElemSegment) => .Ints
+```
+
+#### Data Segments
+
+Wasm currently supports only one memory, so we do not need to resolve any identifiers.
+
+```k
+ rule #t2aDefn(( data _:Index (offset IS) DS )) => #data(0, #t2aInstrs(IS), #DS2Bytes(DS))
+```
+
+#### Exports
+
+```k
+ rule #t2aDefn(( export ENAME ( func ID:Identifier ) )) => #export(ENAME, {IDS[ID]}:>Int) requires ID in_keys(IDS)
+ rule #t2aDefn(( export ENAME ( global ID:Identifier ) )) => #export(ENAME, {IDS[ID]}:>Int) requires ID in_keys(IDS)
+ rule #t2aDefn<_>(( export ENAME ( func I:Int ) )) => #export(ENAME, I)
+ rule #t2aDefn<_>(( export ENAME ( global I:Int ) )) => #export(ENAME, I)
+
+ rule #t2aDefn<_>(( export ENAME ( table _ ) )) => #export(ENAME, 0)
+ rule #t2aDefn<_>(( export ENAME ( memory _ ) )) => #export(ENAME, 0)
+```
+
+#### Other Definitions
+
+```k
+ rule #t2aDefn<_C>(D:Defn) => D [owise]
+```
+
+#### Instructions
+
+```k
+ syntax Instr ::= "#t2aInstr" "<" Context ">" "(" Instr ")" [function]
+ // ---------------------------------------------------------------------
+ rule #t2aInstr(( PI:PlainInstr IS:Instrs ):FoldedInstr) => ({#t2aInstr(PI)}:>PlainInstr #t2aInstrs(IS))
+ rule #t2aInstr(( PI:PlainInstr ):FoldedInstr) => #t2aInstr(PI)
+```
+
+#### Basic Instructions
+
+```k
+ rule #t2aInstr<_>(unreachable) => unreachable
+ rule #t2aInstr<_>(nop) => nop
+ rule #t2aInstr<_>(br L:Int) => #br(L)
+ rule #t2aInstr<_>(br_if L:Int) => #br_if(L)
+ rule #t2aInstr<_>(br_table ES) => #br_table(elemSegment2Ints(ES))
+ rule #t2aInstr<_>(return) => return
+
+ rule #t2aInstr(call ID:Identifier) => #call({FIDS[ID]}:>Int)
+ requires ID in_keys(FIDS)
+ rule #t2aInstr<_> (call I:Int) => #call(I)
+
+ rule #t2aInstr<_>(call_indirect TU) => call_indirect TU
+```
+
+#### Parametric Instructions
+
+```k
+ rule #t2aInstr<_>(drop) => drop
+ rule #t2aInstr<_>(select) => select
+```
+
+#### Variable Instructions
+
+```k
+ rule #t2aInstr(local.get ID:Identifier) => #local.get({LIDS[ID]}:>Int)
+ requires ID in_keys(LIDS)
+ rule #t2aInstr(local.set ID:Identifier) => #local.set({LIDS[ID]}:>Int)
+ requires ID in_keys(LIDS)
+ rule #t2aInstr(local.tee ID:Identifier) => #local.tee({LIDS[ID]}:>Int)
+ requires ID in_keys(LIDS)
+
+ rule #t2aInstr<_>(local.get I:Int) => #local.get(I)
+ rule #t2aInstr<_>(local.set I:Int) => #local.set(I)
+ rule #t2aInstr<_>(local.tee I:Int) => #local.tee(I)
+
+ rule #t2aInstr(global.get ID:Identifier) => #global.get({GIDS[ID]}:>Int)
+ requires ID in_keys(GIDS)
+ rule #t2aInstr(global.set ID:Identifier) => #global.set({GIDS[ID]}:>Int)
+ requires ID in_keys(GIDS)
+
+ rule #t2aInstr<_>(global.get I:Int) => #global.get(I)
+ rule #t2aInstr<_>(global.set I:Int) => #global.set(I)
+```
+
+#### Memory Instructions
+
+`MemArg`s can optionally be passed to `load` and `store` operations.
+The `offset` parameter is added to the the address given on the stack, resulting in the "effective address" to store to or load from.
+The `align` parameter is for optimization only and is not allowed to influence the semantics, so we ignore it.
+
+```k
+ rule #t2aInstr<_>(ITYPE:IValType.OP:StoreOp) => #store(ITYPE, OP, 0)
+ rule #t2aInstr<_>(ITYPE:IValType.OP:StoreOp MemArg) => #store(ITYPE, OP, #getOffset(MemArg))
+ rule #t2aInstr<_>(FTYPE:FValType.OP:StoreOp) => #store(FTYPE, OP, 0)
+ rule #t2aInstr<_>(FTYPE:FValType.OP:StoreOp MemArg) => #store(FTYPE, OP, #getOffset(MemArg))
+ rule #t2aInstr<_>(ITYPE:IValType.OP:LoadOp) => #load(ITYPE, OP, 0)
+ rule #t2aInstr<_>(ITYPE:IValType.OP:LoadOp MemArg) => #load(ITYPE, OP, #getOffset(MemArg))
+ rule #t2aInstr<_>(FTYPE:FValType.OP:LoadOp) => #load(FTYPE, OP, 0)
+ rule #t2aInstr<_>(FTYPE:FValType.OP:LoadOp MemArg) => #load(FTYPE, OP, #getOffset(MemArg))
+ rule #t2aInstr<_>(memory.size) => memory.size
+ rule #t2aInstr<_>(memory.grow) => memory.grow
+
+ syntax Int ::= #getOffset ( MemArg ) [function, total]
+ // -----------------------------------------------------------
+ rule #getOffset( _:AlignArg) => 0
+ rule #getOffset(offset= OS ) => OS
+ rule #getOffset(offset= OS _:AlignArg) => OS
+```
+
+#### Numeric Instructions
+
+```k
+ rule #t2aInstr<_>(ITYPE:IValType.const I) => ITYPE.const I
+ rule #t2aInstr<_>(FTYPE:FValType.const N) => FTYPE.const N
+ rule #t2aInstr<_>(ITYPE.OP:IUnOp) => ITYPE.OP
+ rule #t2aInstr<_>(FTYPE.OP:FUnOp) => FTYPE.OP
+ rule #t2aInstr<_>(ITYPE.OP:IBinOp) => ITYPE.OP
+ rule #t2aInstr<_>(FTYPE.OP:FBinOp) => FTYPE.OP
+ rule #t2aInstr<_>(ITYPE.OP:TestOp) => ITYPE.OP
+ rule #t2aInstr<_>(ITYPE.OP:IRelOp) => ITYPE.OP
+ rule #t2aInstr<_>(FTYPE.OP:FRelOp) => FTYPE.OP
+ rule #t2aInstr<_>(ATYPE.OP:CvtOp) => ATYPE.OP
+```
+
+#### Block Instructions
+
+There are several formats of block instructions, and the text-to-abstract transformation must be distributed over them.
+At this point, all branching identifiers should have been resolved, so we can remove the id.
+
+```k
+ rule #t2aInstr( block _OID:OptionalId TDS:TypeDecls IS end _OID') => #block(gatherTypes(result, TDS), #t2aInstrs(IS), .Int)
+ rule #t2aInstr( loop _OID:OptionalId TDS IS end _OID') => #loop(gatherTypes(result, TDS), #t2aInstrs(IS), .Int)
+ rule #t2aInstr( if _OID:OptionalId TDS IS else _OID':OptionalId IS' end _OID'') => #if(gatherTypes(result, TDS), #t2aInstrs(IS), #t2aInstrs(IS'), .Int)
+```
+
+#### KWasm Administrative Instructions
+
+The following instructions are not part of the official Wasm text format.
+They are currently supported in KWasm text files, but may be deprecated.
+
+```k
+ rule #t2aInstr<_C>(trap) => trap
+
+ rule #t2aInstr(#block(VT:VecType, IS:Instrs, BLOCKINFO)) => #block(VT, #t2aInstrs(IS), BLOCKINFO)
+
+ rule #t2aInstr<_>(init_local I V) => init_local I V
+ rule #t2aInstr<_>(init_locals VS) => init_locals VS
+```
+
+#### List Functions
+
+The following are helper functions.
+They distribute the text-to-abstract functions above over lists.
+
+```k
+ syntax Stmts ::= "#t2aStmts" "<" Context ">" "(" Stmts ")" [function]
+ syntax Defns ::= "#t2aDefns" "<" Context ">" "(" Defns ")" [function]
+ syntax Instrs ::= "#t2aInstrs" "<" Context ">" "(" Instrs ")" [function]
+ // ------------------------------------------------------------------------------------
+ rule #t2aStmts(S:Stmt SS:Stmts) => #t2aStmt(S) #t2aStmts(SS)
+ rule #t2aStmts<_>(.Stmts) => .Stmts
+
+ rule #t2aDefns(D:Defn DS:Defns) => #t2aDefn(D) #t2aDefns(DS)
+ rule #t2aDefns<_>(.Defns) => .Defns
+
+ rule #t2aInstrs(I:Instr IS:Instrs) => #t2aInstr(I) #t2aInstrs(IS)
+ rule #t2aInstrs<_>(.Instrs) => .Instrs
+```
+
+#### Functions for Gathering Context
+
+The following are helper functions for gathering and updating context.
+
+```k
+ syntax Map ::= #idcTypes ( Defns ) [function]
+ | #idcTypesAux ( Defns, Int, Map ) [function]
+ // ----------------------------------------------------------
+ rule #idcTypes(DEFNS) => #idcTypesAux(DEFNS, 0, .Map)
+
+ rule #idcTypesAux((type ID:Identifier (func _)) TS => TS, IDX => IDX +Int 1, ACC => ACC [ ID <- IDX ]) requires notBool ID in_keys(ACC)
+ rule #idcTypesAux((type (func _)) TS => TS, IDX => IDX +Int 1, _ACC)
+ rule #idcTypesAux(.Defns, _, ACC) => ACC
+
+ syntax Map ::= #idcFuncs ( Defns, Defns ) [function]
+ | #idcFuncsAux ( Defns, Defns, Int, Map ) [function]
+ // -----------------------------------------------------------------
+ rule #idcFuncs(IMPORTS, DEFNS) => #idcFuncsAux(IMPORTS, DEFNS, 0, .Map)
+
+ rule #idcFuncsAux((import _ _ (func ID:Identifier _)) IS => IS, _FS, IDX => IDX +Int 1, ACC => ACC [ ID <-IDX ]) requires notBool ID in_keys(ACC)
+ rule #idcFuncsAux((import _ _ (func _)) IS => IS, _FS, IDX => IDX +Int 1, _ACC)
+ rule #idcFuncsAux(_I IS => IS, _FS, _IDX , _ACC) [owise]
+
+ rule #idcFuncsAux(.Defns, (func ID:Identifier _) FS => FS, IDX => IDX +Int 1, ACC => ACC [ ID <- IDX ]) requires notBool ID in_keys(ACC)
+ rule #idcFuncsAux(.Defns, (func _:FuncSpec) FS => FS, IDX => IDX +Int 1, _ACC)
+ rule #idcFuncsAux(.Defns, .Defns, _, ACC) => ACC
+
+ syntax Map ::= #idcGlobals ( Defns, Defns ) [function]
+ | #idcGlobalsAux ( Defns, Defns, Int, Map ) [function]
+ // -------------------------------------------------------------------
+ rule #idcGlobals(IMPORTS, DEFNS) => #idcGlobalsAux(IMPORTS, DEFNS, 0, .Map)
+
+ rule #idcGlobalsAux((import _ _ (global ID:Identifier _)) IS => IS, _GS, IDX => IDX +Int 1, ACC => ACC [ ID <-IDX ]) requires notBool ID in_keys(ACC)
+ rule #idcGlobalsAux((import _ _ (global _)) IS => IS, _GS, IDX => IDX +Int 1, _ACC)
+ rule #idcGlobalsAux(_I IS => IS, _GS, _IDX , _ACC) [owise]
+
+ rule #idcGlobalsAux(.Defns, #global(... metadata: ID:Identifier) GS => GS, IDX => IDX +Int 1, ACC => ACC [ ID <- IDX ]) requires notBool ID in_keys(ACC)
+ rule #idcGlobalsAux(.Defns, #global(...) GS => GS, IDX => IDX +Int 1, _ACC) [owise]
+ rule #idcGlobalsAux(.Defns, .Defns, _, ACC) => ACC
+
+ syntax Map ::= #ids2Idxs(TypeUse, LocalDecls) [function, total]
+ | #ids2Idxs(Int, TypeUse, LocalDecls) [function, total]
+ // -------------------------------------------------------------------------
+ rule #ids2Idxs(TU, LDS) => #ids2Idxs(0, TU, LDS)
+
+ rule #ids2Idxs(_, .TypeDecls, .LocalDecls) => .Map
+ rule #ids2Idxs(N, (type _) , LDS) => #ids2Idxs(N, .TypeDecls, LDS)
+ rule #ids2Idxs(N, (type _) TDS, LDS) => #ids2Idxs(N, TDS , LDS)
+
+ rule #ids2Idxs(N, (param ID:Identifier _) TDS, LDS)
+ => (ID |-> N) #ids2Idxs(N +Int 1, TDS, LDS)
+ rule #ids2Idxs(N, (param _) TDS, LDS) => #ids2Idxs(N +Int 1, TDS, LDS)
+ rule #ids2Idxs(N, _TD:TypeDecl TDS, LDS) => #ids2Idxs(N , TDS, LDS) [owise]
+
+ rule #ids2Idxs(N, .TypeDecls, local ID:Identifier _ LDS:LocalDecls)
+ => (ID |-> N) #ids2Idxs(N +Int 1, .TypeDecls, LDS)
+ rule #ids2Idxs(N, .TypeDecls, _LD:LocalDecl LDS) => #ids2Idxs(N +Int 1, .TypeDecls, LDS) [owise]
+```
+
+```k
+endmodule
+```
diff --git a/docs/runtimeverification-wasm-semantics/wasm.md b/docs/runtimeverification-wasm-semantics/wasm.md
new file mode 100644
index 000000000..914c06d68
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/wasm.md
@@ -0,0 +1,1430 @@
+WebAssembly State and Semantics
+===============================
+
+```k
+require "data.md"
+require "numeric.md"
+
+module WASM-SYNTAX
+ imports WASM-DATA-SYNTAX
+ imports WASM-COMMON-SYNTAX
+ imports WASM-NUMERIC-SYNTAX
+endmodule
+```
+
+Common Syntax
+-------------
+
+```k
+module WASM-COMMON-SYNTAX
+ imports WASM-DATA-COMMON-SYNTAX
+ imports WASM-NUMERIC
+```
+
+### Text Format
+
+WebAssmebly code consists of instruction sequences.
+The basic abstract syntax contains only the `instr` syntax production.
+The text format also specifies the `plaininstr`, which corresponds almost exactly to the the `instr` production.
+
+Most instructions are plain instructions.
+
+```k
+ syntax Instr ::= PlainInstr
+ // ---------------------------
+```
+
+### Sequencing
+
+WebAssembly code consists of sequences of statements (`Stmts`).
+In this file we define 3 types of statements:
+
+- Instruction (`Instr`): Administrative or computational instructions.
+- Definitions (`Defn`) : The declarations of `type`, `func`, `table`, `mem` etc.
+- The Declaration of a module.
+
+The sorts `EmptyStmt` and `EmptyStmts` are administrative so that the empty list of `Stmt`, `Instr`, or `Defn` has a unique least sort.
+
+```k
+ syntax EmptyStmt
+ // ----------------
+
+ syntax Instr ::= EmptyStmt
+ syntax Defn ::= EmptyStmt
+ syntax Stmt ::= Instr | Defn
+ // -----------------------------
+
+ syntax EmptyStmts ::= List{EmptyStmt , ""} [klabel(listStmt), symbol]
+ syntax Instrs ::= List{Instr , ""} [klabel(listStmt)]
+ syntax Defns ::= List{Defn , ""} [klabel(listStmt)]
+ syntax Stmts ::= List{Stmt , ""} [klabel(listStmt)]
+ // -------------------------------------------------------------
+
+ syntax Instrs ::= EmptyStmts
+ syntax Defns ::= EmptyStmts
+ syntax Stmts ::= Instrs | Defns
+ // --------------------------------
+```
+
+### Instructions
+
+**TODO**: Implement `Float` in the format of `-nan`, `nan:0x n:hexnum` and `hexfloat`.
+
+```k
+ syntax PlainInstr ::= IValType "." "const" WasmInt [klabel(aIConst), symbol]
+ | FValType "." "const" Number [klabel(aFConst), symbol]
+ | IValType "." IUnOp [klabel(aIUnOp), symbol]
+ | FValType "." FUnOp [klabel(aFUnOp), symbol]
+ | IValType "." IBinOp [klabel(aIBinOp), symbol]
+ | FValType "." FBinOp [klabel(aFBinOp), symbol]
+ | IValType "." TestOp [klabel(aTestOp), symbol]
+ | IValType "." IRelOp [klabel(aIRelOp), symbol]
+ | FValType "." FRelOp [klabel(aFRelOp), symbol]
+ | ValType "." CvtOp [klabel(aCvtOp), symbol]
+ | "drop" [klabel(aDrop), symbol]
+ | "select" [klabel(aSelect), symbol]
+ | "nop" [klabel(aNop), symbol]
+ | "unreachable" [klabel(aUnreachable), symbol]
+ | "return" [klabel(aReturn), symbol]
+ | "memory.size" [klabel(aSize), symbol]
+ | "memory.grow" [klabel(aGrow), symbol]
+ // -----------------------------------
+
+ syntax PlainInstr ::= "call_indirect" TypeUse
+ syntax TypeUse ::= TypeDecls
+ | "(type" Index ")" [prefer] // TODO: Remove and move to wasm-text.
+ | "(type" Index ")" TypeDecls
+ syntax TypeKeyWord ::= "param" | "result"
+ syntax TypeDecl ::= "(" TypeDecl ")" [bracket]
+ | TypeKeyWord ValTypes
+ | "param" Identifier ValType
+ syntax TypeDecls ::= List{TypeDecl , ""} [klabel(listTypeDecl)]
+ // -----------------------------------------------------------------
+
+ syntax StoreOp ::= "store" [klabel(storeOpStore), symbol]
+ | "store8" [klabel(storeOpStore8), symbol]
+ | "store16" [klabel(storeOpStore16), symbol]
+ | "store32" [klabel(storeOpStore32), symbol]
+ syntax LoadOp ::= "load" [klabel(loadOpLoad), symbol]
+ | "load8_u" [klabel(loadOpLoad8_u), symbol]
+ | "load16_u" [klabel(loadOpLoad16_u), symbol]
+ | "load32_u" [klabel(loadOpLoad32_u), symbol]
+ | "load8_s" [klabel(loadOpLoad8_s), symbol]
+ | "load16_s" [klabel(loadOpLoad16_s), symbol]
+ | "load32_s" [klabel(loadOpLoad32_s), symbol]
+ // --------------------------------------------------------------
+```
+
+### Definitions at the Module Level
+
+```k
+ syntax Defn ::= TypeDefn
+ | GlobalDefn
+ | FuncDefn
+ | TableDefn
+ | MemoryDefn
+ | ElemDefn
+ | DataDefn
+ | StartDefn
+ | ExportDefn
+ | ImportDefn
+ // --------------------------
+```
+
+The following are kept abstract, and can be extended in other formats, such as the text format.
+
+```k
+ syntax TypeDefn
+ syntax GlobalDefn
+ syntax FuncDefn
+ syntax TableDefn
+ syntax MemoryDefn
+ syntax ElemDefn
+ syntax DataDefn
+ syntax StartDefn
+ syntax ImportDefn
+ syntax ExportDefn
+ // -----------------
+```
+
+```k
+endmodule
+```
+
+Semantics
+---------
+
+```k
+module WASM
+ imports WASM-COMMON-SYNTAX
+ imports WASM-DATA
+ imports WASM-NUMERIC
+```
+
+### Configuration
+
+```k
+ configuration
+
+ .K
+ .ValStack
+
+ .Map
+ .Int
+
+ .Map
+ .Map
+
+
+ 0
+ .Map
+ .Map
+ 0
+ .Map
+ 0
+ .Map
+ .Map
+ .Map
+ .Map
+ .Map
+ .Map
+ 0
+
+ .String
+
+ .Map
+ .Map
+
+
+
+ 0
+
+
+
+ 0
+ .Instrs:Instrs
+ .Type
+ .Type
+ 0
+
+
+ .Map
+
+
+
+ 0
+
+
+ 0
+ .Int
+ 0
+ .Map
+
+
+ 0
+
+
+ 0
+ .Int
+ 0
+ .Bytes
+
+
+ 0
+
+
+ 0
+ undefined
+ .Mut
+
+
+ 0
+
+ true
+
+```
+
+### Assumptions and invariants
+
+Integers in K are unbounded.
+As an invariant, however, for any integer `< iNN > I:Int` on the stack, `I` is between 0 and `#pow(NN) - 1`.
+That way, unsigned instructions can make use of `I` directly, whereas signed instructions may need `#signed(iNN, I)`.
+
+The highest address in a memory instance divided by the `#pageSize()` constant (defined below) may not exceed the value in the `` cell, if present.
+
+Since memory data is bytes, all integers in the `Map` in the `` cell are bounded to be between 1 and 255, inclusive.
+All places in the data with no entry are considered zero bytes.
+
+### Translations to Abstract Syntax
+
+Before execution, the program is translated from the text-format concrete syntax tree into an abstract syntax tree using the following function.
+It's full definition is found in the `wasm-text.md` file.
+
+```k
+ syntax Stmts ::= text2abstract ( Stmts ) [function]
+ // ---------------------------------------------------
+```
+
+Instructions
+------------
+
+### Sequencing
+
+```k
+ syntax K ::= sequenceStmts ( Stmts ) [function]
+ | sequenceDefns ( Defns ) [function]
+ | sequenceInstrs ( Instrs ) [function]
+ // -------------------------------------------------
+ rule sequenceStmts(.Stmts) => .
+ rule sequenceStmts(S SS ) => S ~> sequenceStmts(SS)
+
+ rule sequenceDefns(.Defns) => .
+ rule sequenceDefns(D DS ) => D ~> sequenceDefns(DS)
+
+ rule sequenceInstrs(.Instrs) => .
+ rule sequenceInstrs(I IS ) => I ~> sequenceInstrs(IS)
+```
+
+### Traps
+
+`trap` is the error mechanism of Wasm.
+Traps cause all execution to halt, and can not be caught from within Wasm.
+We emulate this by consuming everything in the `` cell that is not a `Stmt`.
+Statements are not part of Wasm semantics, but rather of the embedder, and is where traps can be caught.
+Thus, a `trap` "bubbles up" (more correctly, to "consumes the continuation") until it reaches a statement which is not an `Instr` or `Def`.
+
+```k
+ syntax Instr ::= "trap"
+ // -----------------------
+ rule trap ~> (_L:Label => .) ...
+ rule trap ~> (_F:Frame => .) ...
+ rule trap ~> (_I:Instr => .) ...
+ rule trap ~> (_D:Defn => .) ...
+```
+
+When a single value ends up on the instruction stack (the `` cell), it is moved over to the value stack (the `` cell).
+If the value is the special `undefined`, then `trap` is generated instead.
+
+```k
+ rule undefined => trap ...
+ rule V:Val => . ...
+ VALSTACK => V : VALSTACK
+ requires V =/=K undefined
+```
+
+Common Operator Machinery
+-------------------------
+
+Common machinery for operators is supplied here, based on their categorization.
+This allows us to give purely functional semantics to many of the opcodes.
+
+### Constants
+
+Constants are moved directly to the value stack.
+Function `#unsigned` is called on integers to allow programs to use negative numbers directly.
+
+```k
+ rule ITYPE:IValType . const VAL => #chop (< ITYPE > VAL) ...
+ rule FTYPE:FValType . const VAL => #round( FTYPE , VAL) ...
+```
+
+### Unary Operations
+
+When a unary operator is the next instruction, the single argument is loaded from the `` automatically.
+An `*UnOp` operator always produces a result of the same type as its operand.
+
+```k
+ rule ITYPE . UOP:IUnOp => ITYPE . UOP C1 ...
+ < ITYPE > C1 : VALSTACK => VALSTACK
+ rule FTYPE . UOP:FUnOp => FTYPE . UOP C1 ...
+ < FTYPE > C1 : VALSTACK => VALSTACK
+```
+
+### Binary Operations
+
+When a binary operator is the next instruction, the two arguments are loaded from the `` automatically.
+
+```k
+ rule ITYPE . BOP:IBinOp => ITYPE . BOP C1 C2 ...
+ < ITYPE > C2 : < ITYPE > C1 : VALSTACK => VALSTACK
+ rule FTYPE . BOP:FBinOp => FTYPE . BOP C1 C2 ...
+ < FTYPE > C2 : < FTYPE > C1 : VALSTACK => VALSTACK
+```
+
+### Test Operations
+
+When a test operator is the next instruction, the single argument is loaded from the `` automatically.
+
+```k
+ rule TYPE . TOP:TestOp => TYPE . TOP C1 ...
+ < TYPE > C1 : VALSTACK => VALSTACK
+```
+
+### Relationship Operations
+
+When a relationship operator is the next instruction, the two arguments are loaded from the `` automatically.
+
+```k
+ rule ITYPE . ROP:IRelOp => ITYPE . ROP C1 C2 ...
+ < ITYPE > C2 : < ITYPE > C1 : VALSTACK => VALSTACK
+ rule FTYPE . ROP:FRelOp => FTYPE . ROP C1 C2 ...
+ < FTYPE > C2 : < FTYPE > C1 : VALSTACK => VALSTACK
+```
+
+### Conversion Operations
+
+Conversion Operation convert constant elements at the top of the stack to another type.
+
+```k
+ rule TYPE:ValType . CVTOP:Cvti32Op => TYPE . CVTOP C1 ...
+ < i32 > C1 : VALSTACK => VALSTACK
+
+ rule TYPE:ValType . CVTOP:Cvti64Op => TYPE . CVTOP C1 ...
+ < i64 > C1 : VALSTACK => VALSTACK
+
+ rule TYPE:ValType . CVTOP:Cvtf32Op => TYPE . CVTOP C1 ...
+ < f32 > C1 : VALSTACK => VALSTACK
+
+ rule TYPE:ValType . CVTOP:Cvtf64Op => TYPE . CVTOP C1 ...
+ < f64 > C1 : VALSTACK => VALSTACK
+```
+
+ValStack Operations
+-------------------
+
+Operator `drop` removes a single item from the ``.
+The `select` operator picks one of the second or third stack values based on the first.
+
+```k
+ rule drop => . ...
+ _ : VALSTACK => VALSTACK
+
+ rule select => . ...
+
+ < i32 > C : < TYPE > V2:Number : < TYPE > V1:Number : VALSTACK
+ => < TYPE > #if C =/=Int 0 #then V1 #else V2 #fi : VALSTACK
+
+```
+
+Structured Control Flow
+-----------------------
+
+`nop` does nothing.
+
+```k
+ rule nop => . ...
+```
+
+`unreachable` causes an immediate `trap`.
+
+```k
+ rule unreachable => trap ...
+```
+
+Labels are administrative instructions used to mark the targets of break instructions.
+They contain the continuation to use following the label, as well as the original stack to restore.
+The supplied type represents the values that should taken from the current stack.
+
+A block is the simplest way to create targets for break instructions (ie. jump destinations).
+It simply executes the block then records a label with an empty continuation.
+
+```k
+ syntax Label ::= "label" VecType "{" Instrs "}" ValStack
+ // --------------------------------------------------------
+ rule label [ TYPES ] { _ } VALSTACK' => . ...
+ VALSTACK => #take(lengthValTypes(TYPES), VALSTACK) ++ VALSTACK'
+
+ syntax BlockMetaData ::= OptionalInt
+ // ------------------------------------
+
+ syntax Instr ::= #block(VecType, Instrs, BlockMetaData) [klabel(aBlock), symbol]
+ // --------------------------------------------------------------------------------
+ rule #block(VECTYP, IS, _) => sequenceInstrs(IS) ~> label VECTYP { .Instrs } VALSTACK ...
+ VALSTACK => .ValStack
+```
+
+The `br*` instructions search through the instruction stack (the `` cell) for the correct label index.
+Upon reaching it, the label itself is executed.
+
+Note that, unlike in the WebAssembly specification document, we do not need the special "context" operator here because the value and instruction stacks are separate.
+
+```k
+ syntax Instr ::= #br( Int ) [klabel(aBr), symbol]
+ // -------------------------------------------------
+ rule #br(_IDX) ~> (_S:Stmt => .) ...
+ rule #br(0 ) ~> label [ TYPES ] { IS } VALSTACK' => sequenceInstrs(IS) ...
+ VALSTACK => #take(lengthValTypes(TYPES), VALSTACK) ++ VALSTACK'
+ rule #br(N:Int) ~> _L:Label => #br(N -Int 1) ...
+ requires N >Int 0
+
+ syntax Instr ::= "#br_if" "(" Int ")" [klabel(aBr_if), symbol]
+ // --------------------------------------------------------------
+ rule #br_if(IDX) => #br(IDX) ...
+ < _TYPE > VAL : VALSTACK => VALSTACK
+ requires VAL =/=Int 0
+ rule #br_if(_IDX) => . ...
+ < _TYPE > VAL : VALSTACK => VALSTACK
+ requires VAL ==Int 0
+
+ syntax Instr ::= "#br_table" "(" Ints ")" [klabel(aBr_table), symbol]
+ // ---------------------------------------------------------------------
+ rule #br_table(ES) => #br(#getInts(ES, minInt(VAL, #lenInts(ES) -Int 1))) ...
+ < _TYPE > VAL : VALSTACK => VALSTACK
+```
+
+Finally, we have the conditional and loop instructions.
+
+```k
+ syntax Instr ::= #if( VecType, then : Instrs, else : Instrs, blockInfo: BlockMetaData) [klabel(aIf), symbol]
+ // ------------------------------------------------------------------------------------------------------------
+ rule #if(VECTYP, IS, _, _) => sequenceInstrs(IS) ~> label VECTYP { .Instrs } VALSTACK ...
+ < i32 > VAL : VALSTACK => VALSTACK
+ requires VAL =/=Int 0
+
+ rule #if(VECTYP, _, IS, _) => sequenceInstrs(IS) ~> label VECTYP { .Instrs } VALSTACK ...
+ < i32 > VAL : VALSTACK => VALSTACK
+ requires VAL ==Int 0
+
+ syntax Instr ::= #loop(VecType, Instrs, BlockMetaData) [klabel(aLoop), symbol]
+ // ------------------------------------------------------------------------------
+ rule #loop(VECTYP, IS, BLOCKMETA) => sequenceInstrs(IS) ~> label VECTYP { #loop(VECTYP, IS, BLOCKMETA) } VALSTACK ...
+ VALSTACK => .ValStack
+```
+
+Variable Operators
+------------------
+
+### Locals
+
+The various `init_local` variants assist in setting up the `locals` cell.
+
+```k
+ syntax Instr ::= "init_local" Int Val
+ | "init_locals" ValStack
+ | "#init_locals" Int ValStack
+ // --------------------------------------------
+ rule init_local INDEX VALUE => . ...
+ LOCALS => LOCALS [ INDEX <- VALUE ]
+
+ rule init_locals VALUES => #init_locals 0 VALUES ...
+
+ rule #init_locals _ .ValStack => . ...
+ rule #init_locals N (VALUE : VALSTACK)
+ => init_local N VALUE
+ ~> #init_locals (N +Int 1) VALSTACK
+ ...
+
+```
+
+The `*_local` instructions are defined here.
+
+```k
+ syntax Instr ::= "#local.get" "(" Int ")" [klabel(aLocal.get), symbol]
+ | "#local.set" "(" Int ")" [klabel(aLocal.set), symbol]
+ | "#local.tee" "(" Int ")" [klabel(aLocal.tee), symbol]
+ // ----------------------------------------------------------------------
+ rule #local.get(I) => . ...
+ VALSTACK => VALUE : VALSTACK
+ ... I |-> VALUE ...
+
+ rule #local.set(I) => . ...
+ VALUE : VALSTACK => VALSTACK
+ ... I |-> (_ => VALUE) ...
+
+ rule #local.tee(I) => . ...
+ VALUE : _VALSTACK
+ ... I |-> (_ => VALUE) ...
+```
+
+### Globals
+
+When globals are declared, they must also be given a constant initialization value.
+The `GlobalSpec` production is used to define all ways that a global can specified.
+Globals can either be specified by giving a type and an initializer expression; or by an import and it's expected type.
+The specification can also include export directives.
+The importing and exporting parts of specifications are dealt with in the respective sections for import and export.
+
+```k
+ syntax GlobalType ::= Mut ValType [klabel(aGlobalType), symbol]
+ // ---------------------------------------------------------------
+
+ syntax GlobalDefn ::= #global(type: GlobalType, init: Instrs, metadata: OptionalId) [klabel(aGlobalDefn), symbol]
+ syntax Alloc ::= allocglobal (OptionalId, GlobalType)
+ // ----------------------------------------------------------
+ rule #global(... type: TYP, init: IS, metadata: OID) => sequenceInstrs(IS) ~> allocglobal(OID, TYP) ...
+
+ rule allocglobal(OID:OptionalId, MUT:Mut TYP:ValType) => . ...
+ < TYP > VAL : STACK => STACK
+ CUR
+
+ CUR
+ IDS => #saveId(IDS, OID, NEXTIDX)
+ NEXTIDX => NEXTIDX +Int 1
+ GLOBS => GLOBS [ NEXTIDX <- NEXTADDR ]
+ ...
+
+ NEXTADDR => NEXTADDR +Int 1
+
+ ( .Bag
+ =>
+ NEXTADDR
+ VAL
+ MUT
+
+ )
+ ...
+
+```
+
+The `get` and `set` instructions read and write globals.
+
+```k
+ syntax Instr ::= "#global.get" "(" Int ")" [klabel(aGlobal.get), symbol]
+ | "#global.set" "(" Int ")" [klabel(aGlobal.set), symbol]
+ // ------------------------------------------------------------------------
+ rule #global.get(IDX) => . ...
+ VALSTACK => VALUE : VALSTACK
+ CUR
+
+ CUR
+ ... IDX |-> GADDR ...
+ ...
+
+
+ GADDR
+ VALUE
+ ...
+
+
+ rule #global.set(IDX) => . ...
+ VALUE : VALSTACK => VALSTACK
+ CUR
+
+ CUR
+ ... IDX |-> GADDR ...
+ ...
+
+
+ GADDR
+ _ => VALUE
+ ...
+
+```
+
+Types
+-----
+
+### Type Gathering
+
+This defines helper functions that gathers function together.
+The function `gatherTypes` keeps the `TypeDecl`s that have the same `TypeKeyWord` as we need and throws away the `TypeDecl` having different `TypeKeyWord`.
+
+```k
+ syntax VecType ::= gatherTypes ( TypeKeyWord , TypeDecls ) [function]
+ | #gatherTypes ( TypeKeyWord , TypeDecls , ValTypes ) [function]
+ // ---------------------------------------------------------------------------------
+ rule gatherTypes(TKW , TDECLS:TypeDecls) => #gatherTypes(TKW, TDECLS, .ValTypes)
+
+ rule #gatherTypes( _ , .TypeDecls , TYPES) => [ TYPES ]
+ rule #gatherTypes(TKW , TKW':TypeKeyWord _:ValTypes TDECLS:TypeDecls , TYPES) => #gatherTypes(TKW, TDECLS, TYPES) requires TKW =/=K TKW'
+ rule #gatherTypes(TKW , TKW TYPES':ValTypes TDECLS:TypeDecls , TYPES)
+ => #gatherTypes(TKW , TDECLS:TypeDecls , TYPES + TYPES')
+ rule #gatherTypes(result , param _ID:Identifier _:ValType TDECLS:TypeDecls , TYPES) => #gatherTypes(result , TDECLS , TYPES)
+ rule #gatherTypes(param , param _ID:Identifier VTYPE:ValType TDECLS:TypeDecls , TYPES) => #gatherTypes(param , TDECLS , TYPES + VTYPE .ValTypes)
+```
+
+### Type Use
+
+A type use is a reference to a type definition.
+It may optionally be augmented by explicit inlined parameter and result declarations.
+A type use should start with `'(' 'type' x:typeidx ')'` followed by a group of inlined parameter or result declarations.
+
+```k
+ syntax FuncType ::= asFuncType ( TypeDecls ) [function, klabel(TypeDeclsAsFuncType)]
+ | asFuncType ( Map, Map, TypeUse ) [function, klabel(TypeUseAsFuncType) ]
+ // --------------------------------------------------------------------------------------------
+ rule asFuncType(TDECLS:TypeDecls) => gatherTypes(param, TDECLS) -> gatherTypes(result, TDECLS)
+ rule asFuncType( _ , _ , TDECLS:TypeDecls) => asFuncType(TDECLS)
+ rule asFuncType(TYPEIDS, TYPES, (type TFIDX )) => {TYPES[#ContextLookup(TYPEIDS ,TFIDX)]}:>FuncType
+ rule asFuncType(TYPEIDS, TYPES, (type TFIDX ) TDECLS ) => asFuncType(TDECLS)
+ requires TYPES[#ContextLookup(TYPEIDS, TFIDX)] ==K asFuncType(TDECLS)
+```
+
+### Type Declaration
+
+Type could be declared explicitly and could optionally bind with an identifier.
+`identifier` for `param` will be used only when the function type is declared when defining a function.
+When defining `TypeDefn`, the `identifier` for `param` will be ignored and will not be saved into the module instance.
+
+```k
+ syntax TypeDefn ::= #type(type: FuncType, metadata: OptionalId) [klabel(aTypeDefn), symbol]
+ syntax Alloc ::= alloctype (OptionalId, FuncType)
+ // ----------------------------------------------------
+ rule #type(... type: TYPE, metadata: OID) => alloctype(OID, TYPE) ...
+
+ rule alloctype(OID, TYPE) => . ...
+ CUR
+
+ CUR
+ IDS => #saveId(IDS, OID, NEXTIDX)
+ NEXTIDX => NEXTIDX +Int 1
+ TYPES => TYPES [NEXTIDX <- TYPE]
+ ...
+
+```
+
+Function Declaration and Invocation
+-----------------------------------
+
+### Function Declaration
+
+Function declarations can look quite different depending on which fields are ommitted and what the context is.
+Here, we allow for an "abstract" function declaration using syntax `func_::___`, and a more concrete one which allows arbitrary order of declaration of parameters, locals, and results.
+The `FuncSpec` production is used to define all ways that a global can specified.
+A function can either be specified by giving a type, what locals it allocates, and a function body; or by an import and it's expected type.
+The specification can also include export directives.
+The importing and exporting parts of specifications are dealt with in the respective sections for import and export.
+
+```k
+ syntax FuncDefn ::= #func(type: Int, locals: VecType, body: Instrs, metadata: FuncMetadata) [klabel(aFuncDefn), symbol]
+ syntax Alloc ::= allocfunc ( Int , Int , FuncType , VecType , Instrs , FuncMetadata )
+ // ----------------------------------------------------------------------------------------
+ rule #func(... type: TYPIDX, locals: LOCALS, body: INSTRS, metadata: META) => allocfunc(CUR, NEXTADDR, TYPE, LOCALS, INSTRS, META) ...
+ CUR
+
+ CUR
+ ... TYPIDX |-> TYPE ...
+ NEXTIDX => NEXTIDX +Int 1
+ ADDRS => ADDRS [ NEXTIDX <- NEXTADDR ]
+ ...
+
+ NEXTADDR => NEXTADDR +Int 1
+
+ rule allocfunc(MOD, ADDR, TYPE, LOCALS, INSTRS, #meta(... id: OID, localIds: LIDS)) => . ...
+
+ ( .Bag
+ =>
+ ADDR
+ INSTRS
+ TYPE
+ LOCALS
+ MOD
+
+ OID
+ LIDS
+ ...
+
+
+ )
+ ...
+
+
+ syntax FuncMetadata ::= #meta(id: OptionalId, localIds: Map) [klabel(funcMeta), symbol]
+ // ---------------------------------------------------------------------------------------
+```
+
+### Function Invocation/Return
+
+Frames are used to store function return points.
+Similar to labels, they sit on the instruction stack (the `` cell), and `return` consumes things following it until hitting it.
+Unlike labels, only one frame can be "broken" through at a time.
+
+```k
+ syntax Frame ::= "frame" Int ValTypes ValStack Map
+ // --------------------------------------------------
+ rule frame MODIDX' TRANGE VALSTACK' LOCAL' => . ...
+ VALSTACK => #take(lengthValTypes(TRANGE), VALSTACK) ++ VALSTACK'
+ _ => LOCAL'
+ _ => MODIDX'
+```
+
+When we invoke a function, the element on the top of the stack will become the last parameter of the function.
+For example, when we call `(invoke "foo" (i64.const 100) (i64.const 43) (i32.const 22))`, `(i32.const 22)` will be on the top of ``, but it will be the last parameter of this function invocation if this function takes 3 parameters.
+That is, whenever we want to `#take` or `#drop` an array of `params`, we need to reverse the array of `params` to make the type of the last parameter matching with the type of the value on the top of stack.
+The `#take` function will return the parameter stack in the reversed order, then we need to reverse the stack again to get the actual parameter array we want.
+
+```k
+ syntax Instr ::= "(" "invoke" Int ")"
+ // -------------------------------------
+ rule ( invoke FADDR )
+ => init_locals #revs(#take(lengthValTypes(TDOMAIN), VALSTACK)) ++ #zero(TLOCALS)
+ ~> #block([TRANGE], INSTRS, .Int)
+ ~> frame MODIDX TRANGE #drop(lengthValTypes(TDOMAIN), VALSTACK) LOCAL
+ ...
+
+ VALSTACK => .ValStack
+ LOCAL => .Map
+ MODIDX => MODIDX'
+
+ FADDR
+ INSTRS
+ [ TDOMAIN ] -> [ TRANGE ]
+ [ TLOCALS ]
+ MODIDX'
+ ...
+
+
+ rule return ~> (_S:Stmt => .) ...
+ rule return ~> (_L:Label => .) ...
+ rule (return => .) ~> _FR:Frame ...
+```
+
+### Function Call
+
+`call funcidx` and `call_indirect typeidx` are 2 control instructions that invokes a function in the current frame.
+
+```k
+ syntax Instr ::= #call(Int) [klabel(aCall), symbol]
+ // ---------------------------------------------------
+ rule #call(IDX) => ( invoke FADDR ) ...
+ CUR
+
+ CUR
+ ... IDX |-> FADDR ...
+ ...
+
+```
+
+```k
+ syntax Instr ::= "#call_indirect" "(" Int ")" [klabel(aCall_indirect), symbol]
+ // ------------------------------------------------------------------------------
+ rule #call_indirect(I) => call_indirect (type I) ...
+```
+
+TODO: This is kept for compatibility with the text format.
+The `TypeUses` should be desugared to use a type-index instead.
+But this requires a recursive descent into all the instructions of a function, with feedback up to the top level.
+The types need to be inserted at the definitions level, if a previously undeclared type is present in a `call_indirect` function.
+
+```k
+ rule call_indirect TUSE:TypeUse => ( invoke FADDR ) ...
+ CUR
+ < i32 > IDX : VALSTACK => VALSTACK
+
+ CUR
+ TYPEIDS
+ TYPES
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ ... IDX |-> FADDR ...
+ ...
+
+
+ FADDR
+ FTYPE
+ ...
+
+ requires asFuncType(TYPEIDS, TYPES, TUSE) ==K FTYPE
+
+ rule call_indirect TUSE:TypeUse => trap ...
+ CUR
+ < i32 > IDX : VALSTACK => VALSTACK
+
+ CUR
+ TYPEIDS
+ TYPES
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ ... IDX |-> FADDR ...
+ ...
+
+
+ FADDR
+ FTYPE
+ ...
+
+ requires asFuncType(TYPEIDS, TYPES, TUSE) =/=K FTYPE
+
+ rule call_indirect _TUSE:TypeUse => trap ...
+ CUR
+ < i32 > IDX : VALSTACK => VALSTACK
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ TDATA
+ ...
+
+ requires notBool IDX in_keys(TDATA)
+```
+
+Table
+-----
+
+The allocation of a new `tableinst`.
+Currently at most one table may be defined or imported in a single module.
+The only allowed `TableElemType` is "funcref", so we ignore this term in the reducted sort.
+The table values are addresses into the store of functions.
+The `TableSpec` production is used to define all ways that a global can specified.
+A table can either be specified by giving its type (limits and `funcref`); by specifying a vector of its initial `elem`ents; or by an import and its expected type.
+The specification can also include export directives.
+The importing and exporting parts of specifications are dealt with in the respective sections for import and export.
+
+```k
+ syntax TableDefn ::= #table (limits: Limits, metadata: OptionalId) [klabel(aTableDefn), symbol]
+ syntax Alloc ::= alloctable (OptionalId, Int, OptionalInt)
+ // ----------------------------------------------------------
+ rule #table(... limits: #limitsMin(MIN), metadata: OID) => alloctable(OID, MIN, .Int) ...
+ requires MIN <=Int #maxTableSize()
+ rule #table(... limits: #limits(MIN, MAX), metadata: OID) => alloctable(OID, MIN, MAX) ...
+ requires MIN <=Int #maxTableSize()
+ andBool MAX <=Int #maxTableSize()
+
+ rule alloctable(ID, MIN, MAX) => . ...
+ CUR
+
+ CUR
+ IDS => #saveId(IDS, ID, 0)
+ .Map => (0 |-> NEXTADDR)
+ ...
+
+ NEXTADDR => NEXTADDR +Int 1
+
+ ( .Bag
+ =>
+ NEXTADDR
+ MAX
+ MIN
+ .Map
+
+ )
+ ...
+
+```
+
+Memory
+------
+
+When memory is allocated, it is put into the store at the next available index.
+Memory can only grow in size, so the minimum size is the initial value.
+Currently, only one memory may be accessible to a module, and thus the `` cell is an array with at most one value, at index 0.
+The `MemorySpec` production is used to define all ways that a global can specified.
+A memory can either be specified by giving its type (limits); by specifying a vector of its initial `data`; or by an import and its expected type.
+The specification can also include export directives.
+The importing and exporting parts of specifications are dealt with in the respective sections for import and export.
+
+```k
+ syntax MemoryDefn ::= #memory(limits: Limits, metadata: OptionalId) [klabel(aMemoryDefn), symbol]
+ syntax Alloc ::= allocmemory (OptionalId, Int, OptionalInt)
+ // -----------------------------------------------------------
+ rule #memory(... limits: #limitsMin(MIN), metadata: OID) => allocmemory(OID, MIN, .Int) ...
+ requires MIN <=Int #maxMemorySize()
+ rule #memory(... limits: #limits(MIN, MAX), metadata: OID) => allocmemory(OID, MIN, MAX) ...
+ requires MIN <=Int #maxMemorySize()
+ andBool MAX <=Int #maxMemorySize()
+
+ rule allocmemory(ID, MIN, MAX) => . ...
+ CUR
+
+ CUR
+ IDS => #saveId(IDS, ID, 0)
+ .Map => (0 |-> NEXTADDR)
+ ...
+
+ NEXTADDR => NEXTADDR +Int 1
+
+ ( .Bag
+ =>
+ NEXTADDR
+ MAX
+ MIN
+ ...
+
+ )
+ ...
+
+```
+
+The assorted store operations take an address of type `i32` and a value.
+The `storeX` operations first wrap the the value to be stored to the bit wdith `X`.
+The value is encoded as bytes and stored at the "effective address", which is the address given on the stack plus offset.
+
+```k
+ syntax Instr ::= #store(ValType, StoreOp, offset : Int) [klabel(aStore), symbol]
+ | IValType "." StoreOp Int Int
+ // | FValType "." StoreOp Int Float
+ | "store" "{" Int Int Number "}"
+ // -----------------------------------------------
+ rule #store(ITYPE:IValType, SOP, OFFSET) => ITYPE . SOP (IDX +Int OFFSET) VAL ...
+ < ITYPE > VAL : < i32 > IDX : VALSTACK => VALSTACK
+
+ rule store { WIDTH EA VAL } => . ...
+ CUR
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ SIZE
+ DATA => #setRange(DATA, EA, VAL, WIDTH)
+ ...
+
+ requires (EA +Int WIDTH) <=Int (SIZE *Int #pageSize())
+
+ rule store { WIDTH EA _ } => trap ...
+ CUR
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ SIZE
+ ...
+
+ requires (EA +Int WIDTH) >Int (SIZE *Int #pageSize())
+
+ rule ITYPE . store EA VAL => store { #numBytes(ITYPE) EA VAL } ...
+ rule _ . store8 EA VAL => store { 1 EA #wrap(1, VAL) } ...
+ rule _ . store16 EA VAL => store { 2 EA #wrap(2, VAL) } ...
+ rule i64 . store32 EA VAL => store { 4 EA #wrap(4, VAL) } ...
+```
+
+The assorted load operations take an address of type `i32`.
+The `loadX_sx` operations loads `X` bits from memory, and extend it to the right length for the return value, interpreting the bytes as either signed or unsigned according to `sx`.
+The value is fetched from the "effective address", which is the address given on the stack plus offset.
+Sort `Signedness` is defined in module `BYTES`.
+
+```k
+ syntax Instr ::= #load(ValType, LoadOp, offset : Int) [klabel(aLoad), symbol]
+ | "load" "{" IValType Int Int Signedness"}"
+ | "load" "{" IValType Int Int Signedness Bytes"}"
+ | "load" "{" IValType Int Int Signedness"}"
+ | IValType "." LoadOp Int
+ // ----------------------------------------
+ rule #load(ITYPE:IValType, LOP, OFFSET) => ITYPE . LOP (IDX +Int OFFSET) ...
+ < i32 > IDX : VALSTACK => VALSTACK
+
+ rule ITYPE . load EA:Int => load { ITYPE #numBytes(ITYPE) EA Unsigned } ...
+ rule ITYPE . load8_u EA:Int => load { ITYPE 1 EA Unsigned } ...
+ rule ITYPE . load16_u EA:Int => load { ITYPE 2 EA Unsigned } ...
+ rule i64 . load32_u EA:Int => load { i64 4 EA Unsigned } ...
+ rule ITYPE . load8_s EA:Int => load { ITYPE 1 EA Signed } ...
+ rule ITYPE . load16_s EA:Int => load { ITYPE 2 EA Signed } ...
+ rule i64 . load32_s EA:Int => load { i64 4 EA Signed } ...
+
+ rule load { ITYPE WIDTH EA SIGN } => load { ITYPE WIDTH EA SIGN DATA } ...
+ CUR
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ SIZE
+ DATA
+ ...
+
+ requires (EA +Int WIDTH) <=Int (SIZE *Int #pageSize())
+
+ rule load { _ WIDTH EA _ } => trap ...
+ CUR
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ SIZE
+ ...
+
+ requires (EA +Int WIDTH) >Int (SIZE *Int #pageSize())
+
+ rule load { ITYPE WIDTH EA Signed DATA } => #chop(< ITYPE > #signedWidth(WIDTH, #getRange(DATA, EA, WIDTH))) ...
+ rule load { ITYPE WIDTH EA Unsigned DATA } => < ITYPE > #getRange(DATA, EA, WIDTH) ...
+```
+
+The `size` operation returns the size of the memory, measured in pages.
+
+```k
+ rule memory.size => < i32 > SIZE ...
+ CUR
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ SIZE
+ ...
+
+```
+
+`grow` increases the size of memory in units of pages.
+Failure to grow is indicated by pushing -1 to the stack.
+Success is indicated by pushing the previous memory size to the stack.
+`grow` is non-deterministic and may fail either due to trying to exceed explicit max values, or because the embedder does not have resources available.
+By setting the `` field in the configuration to `true`, the sematnics ensure memory growth only fails if the memory in question would exceed max bounds.
+
+```k
+ syntax Instr ::= "grow" Int
+ // ---------------------------
+ rule memory.grow => grow N ...
+ < i32 > N : VALSTACK => VALSTACK
+
+ rule grow N => < i32 > SIZE ...
+ CUR
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ MAX
+ SIZE => SIZE +Int N
+ ...
+
+ requires #growthAllowed(SIZE +Int N, MAX)
+
+ rule grow N => < i32 > #unsigned(i32, -1) ...
+ DET:Bool
+ CUR
+
+ CUR
+ 0 |-> ADDR
+ ...
+
+
+ ADDR
+ MAX
+ SIZE
+ ...
+
+ requires notBool DET
+ orBool notBool #growthAllowed(SIZE +Int N, MAX)
+
+ syntax Bool ::= #growthAllowed(Int, OptionalInt) [function]
+ // -----------------------------------------------------------
+ rule #growthAllowed(SIZE, .Int ) => SIZE <=Int #maxMemorySize()
+ rule #growthAllowed(SIZE, I:Int) => #growthAllowed(SIZE, .Int) andBool SIZE <=Int I
+```
+
+However, the absolute max allowed size if 2^16 pages.
+Incidentally, the page size is 2^16 bytes.
+The maximum of table size is 2^32 bytes.
+
+```k
+ syntax Int ::= #pageSize() [function]
+ syntax Int ::= #maxMemorySize() [function]
+ syntax Int ::= #maxTableSize() [function]
+ // ------------------------------------------
+ rule #pageSize() => 65536
+ rule #maxMemorySize() => 65536
+ rule #maxTableSize() => 4294967296
+```
+
+Initializers
+------------
+
+### Table initialization
+
+Tables can be initialized with element and the element type is always `funcref`.
+The initialization of a table needs an offset and a list of functions, given as `Index`s.
+A table index is optional and will be default to zero.
+
+```k
+
+ syntax ElemDefn ::= #elem(index : Int, offset : Instrs, elemSegment : Ints) [klabel(aElemDefn), symbol]
+ | "elem" "{" Int Ints "}"
+ syntax Stmt ::= #initElements ( Int, Int, Map, Ints )
+ // -----------------------------------------------------
+ rule #elem(TABIDX, IS, ELEMSEGMENT ) => sequenceInstrs(IS) ~> elem { TABIDX ELEMSEGMENT } ...
+
+ rule elem { TABIDX ELEMSEGMENT } => #initElements ( ADDR, OFFSET, FADDRS, ELEMSEGMENT ) ...
+ CUR
+ < i32 > OFFSET : STACK => STACK
+
+ CUR
+ FADDRS
+ TABIDX |-> ADDR
+ ...
+
+
+ rule #initElements ( _, _, _, .Ints ) => . ...
+ rule #initElements ( ADDR, OFFSET, FADDRS, E:Int ES ) => #initElements ( ADDR, OFFSET +Int 1, FADDRS, ES ) ...
+
+ ADDR
+ DATA => DATA [ OFFSET <- FADDRS[E] ]
+ ...
+
+```
+
+### Memory initialization
+
+Memories can be initialized with data, specified as a list of bytes together with an offset.
+The `data` initializer simply puts these bytes into the specified memory, starting at the offset.
+
+```k
+ syntax DataDefn ::= #data(index : Int, offset : Instrs, data : Bytes) [klabel(aDataDefn), symbol]
+ | "data" "{" Int Bytes "}"
+ // --------------------------------------------
+ // Default to memory 0.
+ rule #data(IDX, IS, DATA) => sequenceInstrs(IS) ~> data { IDX DATA } ...
+
+ // For now, deal only with memory 0.
+ rule data { MEMIDX DSBYTES } => . ...
+ < i32 > OFFSET : STACK => STACK
+ CUR
+
+ CUR
+ MEMIDX |-> ADDR
+ ...
+
+
+ ADDR
+ DATA => #setRange(DATA, OFFSET, Bytes2Int(DSBYTES, LE, Unsigned), lengthBytes(DSBYTES))
+ ...
+
+
+ syntax Int ::= Int "up/Int" Int [function]
+ // ------------------------------------------
+ rule I1 up/Int I2 => (I1 +Int (I2 -Int 1)) /Int I2 requires I2 >Int 0
+```
+
+Start Function
+--------------
+
+The `start` component of a module declares the function index of a `start function` that is automatically invoked when the module is instantiated, after `tables` and `memories` have been initialized.
+
+```k
+ syntax StartDefn ::= #start(Int) [klabel(aStartDefn), symbol]
+ // -------------------------------------------------------------
+ rule #start(IDX) => ( invoke FADDR ) ...
+ CUR
+
+ CUR
+ ... IDX |-> FADDR ...
+ ...
+
+```
+
+Export
+------
+
+Exports make functions, tables, memories and globals available for importing into other modules.
+
+```k
+ syntax ExportDefn ::= #export(name : WasmString, index : Int) [klabel(aExportDefn), symbol]
+ syntax Alloc ::= ExportDefn
+ // ---------------------------
+ rule #export(ENAME, IDX) => . ...
+ CUR
+
+ CUR
+ EXPORTS => EXPORTS [ ENAME <- IDX ]
+ ...
+
+```
+
+Imports
+-------
+
+Imports need to describe the type of what is imported.
+That an import is really a subtype of the declared import needs to be checked at instantiation time.
+The value of a global gets copied when it is imported.
+
+```k
+ syntax ImportDefn ::= #import(mod : WasmString, name : WasmString, ImportDesc) [klabel(aImportDefn), symbol]
+ syntax ImportDesc ::= #funcDesc (id: OptionalId, type: Int) [klabel(aFuncDesc), symbol]
+ | #globalDesc (id: OptionalId, type: GlobalType) [klabel(aGlobalDesc), symbol]
+ | #tableDesc (id: OptionalId, type: Limits) [klabel(aTableDesc), symbol]
+ | #memoryDesc (id: OptionalId, type: Limits) [klabel(aMemoryDesc), symbol]
+ syntax Alloc ::= ImportDefn
+ // --------------------------------
+ rule #import(MOD, NAME, #funcDesc(... type: TIDX) ) => . ...
+ CUR
+
+ CUR
+ TYPES
+ FS => FS [NEXT <- ADDR]
+ NEXT => NEXT +Int 1
+ ...
+
+ ... MOD |-> MODIDX ...
+
+ MODIDX
+ ... IDX |-> ADDR ...
+ ... NAME |-> IDX ...
+ ...
+
+
+ ADDR
+ FTYPE
+ ...
+
+ requires FTYPE ==K TYPES[TIDX]
+
+ rule #import(MOD, NAME, #tableDesc(... id: OID, type: LIM) ) => . ...
+ CUR
+
+ CUR
+ IDS => #saveId(IDS, OID, 0)
+ .Map => 0 |-> ADDR
+ ...
+
+ ... MOD |-> MODIDX ...
+
+ MODIDX
+ IDS'
+ ... #ContextLookup(IDS' , TFIDX) |-> ADDR ...
+ ... NAME |-> TFIDX ...
+ ...
+
+
+ ADDR
+ MAX
+ SIZE
+ ...
+
+ requires #limitsMatchImport(SIZE, MAX, LIM)
+
+ rule #import(MOD, NAME, #memoryDesc(... id: OID, type: LIM) ) => . ...
+ CUR
+
+ CUR
+ IDS => #saveId(IDS, OID, 0)
+ .Map => 0 |-> ADDR
+ ...
+
+ ... MOD |-> MODIDX ...
+
+ MODIDX
+ IDS'
+ ... #ContextLookup(IDS' , TFIDX) |-> ADDR ...
+ ... NAME |-> TFIDX ...
+ ...
+
+
+ ADDR
+ MAX
+ SIZE
+ ...
+
+ requires #limitsMatchImport(SIZE, MAX, LIM)
+
+ rule #import(MOD, NAME, #globalDesc(... id: OID, type: MUT TYP) ) => . ...
+ CUR
+
+ CUR
+ IDS => #saveId(IDS, OID, NEXT)
+ GS => GS [NEXT <- ADDR]
+ NEXT => NEXT +Int 1
+ ...
+
+ ... MOD |-> MODIDX ...
+
+ MODIDX
+ IDS'
+ ... #ContextLookup(IDS' , TFIDX) |-> ADDR ...
+ ... NAME |-> TFIDX ...
+ ...
+
+
+ ADDR
+ _
+ MUT
+
+```
+
+Tables and memories have proper subtyping, unlike globals and functions where a type is only a subtype of itself.
+Subtyping is determined by whether the limits of one table/memory fit in the limits of another.
+The following function checks if the limits in the first parameter *match*, i.e. is a subtype of, the limits in the second.
+
+```k
+ syntax Bool ::= #limitsMatchImport(Int, OptionalInt, Limits) [function]
+ // -----------------------------------------------------------------------
+ rule #limitsMatchImport(L1, _, #limitsMin(L2:Int )) => L1 >=Int L2
+ rule #limitsMatchImport( _, .Int, #limits( _:Int, _)) => false
+ rule #limitsMatchImport(L1, U1:Int, #limits(L2:Int, U2)) => L1 >=Int L2 andBool U1 <=Int U2
+```
+
+Module Instantiation
+--------------------
+
+There is some dependencies among definitions that require that we do them in a certain order, even though they may appear in many valid orders.
+First, functions, tables, memories and globals get *allocated*.
+Then, tables, memories and globals get *instantiated* with elements, data and initialization vectors.
+However, since (currently) globals can only make use of imported globals to be instantiated, we can initialize at allocation time.
+Finally, the start function is invoked.
+Exports may appear anywhere in a module, but can only be performed after what they refer to has been allocated.
+Exports that are inlined in a definition, e.g., `func (export "foo") ...`, are safe to extract as they appear.
+Imports must appear before any allocations in a module, due to validation.
+
+A subtle point is related to tables with inline `elem` definitions: since these may refer to functions by identifier, we need to make sure that tables definitions come after function definitions.
+
+`sortModule` takes a list of definitions and returns a map with different groups of definitions, preserving the order within each group.
+The groups are chosen to represent different stages of allocation and instantiation.
+
+```k
+ syntax ModuleDecl ::= #module ( types: Defns, funcs: Defns, tables: Defns, mems: Defns, globals: Defns, elem: Defns, data: Defns, start: Defns, importDefns: Defns, exports: Defns, metadata: ModuleMetadata) [klabel(aModuleDecl), symbol]
+ // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ syntax ModuleDecl ::= #emptyModule(OptionalId) [function, total]
+ // ---------------------------------------------------------------------
+ rule #emptyModule(OID) => #module (... types: .Defns, funcs: .Defns, tables: .Defns, mems: .Defns, globals: .Defns, elem: .Defns, data: .Defns, start: .Defns, importDefns: .Defns, exports: .Defns, metadata: #meta(... id: OID, funcIds: .Map, filename: .String))
+
+ syntax ModuleMetadata ::= #meta(id: OptionalId, funcIds: Map, filename : OptionalString) [klabel(moduleMeta), symbol]
+ syntax OptionalString ::= ".String" [klabel(.String), symbol] | String
+ // ----------------------------------------------------------------------
+```
+
+A new module instance gets allocated.
+Then, the surrounding `module` tag is discarded, and the definitions are executed, putting them into the module currently being defined.
+
+```k
+ rule #module(... types: TS, funcs: FS, tables: TABS, mems: MS, globals: GS, elem: EL, data: DAT, start: S, importDefns: IS, exports: ES,
+ metadata: #meta(... id: OID, funcIds: FIDS, filename: FILE))
+ => sequenceDefns(TS)
+ ~> sequenceDefns(IS)
+ ~> sequenceDefns(FS)
+ ~> sequenceDefns(GS)
+ ~> sequenceDefns(MS)
+ ~> sequenceDefns(TABS)
+ ~> sequenceDefns(ES)
+ ~> sequenceDefns(EL)
+ ~> sequenceDefns(DAT)
+ ~> sequenceDefns(S)
+ ...
+
+ _ => NEXT
+ NEXT => NEXT +Int 1
+ IDS => #saveId(IDS, OID, NEXT)
+
+ ( .Bag
+ =>
+ NEXT
+
+ FILE
+ OID
+ FIDS
+ ...
+
+ ...
+
+ )
+ ...
+
+```
+
+After a module is instantiated, it should be saved somewhere.
+How this is done is up to the embedder.
+
+```k
+endmodule
+```
diff --git a/docs/runtimeverification-wasm-semantics/wrc20.md b/docs/runtimeverification-wasm-semantics/wrc20.md
new file mode 100644
index 000000000..b06c03c7f
--- /dev/null
+++ b/docs/runtimeverification-wasm-semantics/wrc20.md
@@ -0,0 +1,309 @@
+WRC20
+=====
+
+```k
+requires "kwasm-lemmas.md"
+```
+
+Lemmas
+------
+
+```k
+module WRC20-LEMMAS [symbolic]
+ imports WRC20
+ imports KWASM-LEMMAS
+```
+
+These conversions turns out to be helpful in this particular proof, but we don't want to apply it on all KWasm proofs.
+
+```k
+ rule X /Int N => X >>Int 8 requires N ==Int 256 [simplification]
+```
+
+TODO: The following theorems should be generalized and proven, and moved to the set of general lemmas.
+Perhaps using `requires N ==Int 2 ^Int log2Int(N)`?
+Also, some of these have concrete integers on the LHS.
+It may be better to use a symbolic value as a side condition, e.g. `rule N => foo requires N ==Int 8`, because simplifications rely on exact matching of the LHS.
+
+```k
+ rule X *Int 256 >>Int N => (X >>Int (N -Int 8)) requires N >=Int 8 [simplification]
+
+ rule (Y +Int X *Int 256) >>Int N => (Y >>Int N) +Int (X >>Int (N -Int 8)) requires N >=Int 8 [simplification]
+
+ rule (X < (X +Int (Y < (X +Int (Y < ((X <Int M
+ [simplification]
+
+ rule (X +Int (Y < X +Int ((Y <=Int 256
+ andBool 0 <=Int X
+ andBool X =Int 8
+ [simplification]
+
+ rule #wrap(N, (X +Int (Y < X +Int (#wrap(N, Y <=Int 1
+ andBool 0 <=Int X
+ andBool X =Int 8
+ [simplification]
+```
+
+```k
+endmodule
+```
+
+Macros
+------
+
+The following module gives macros for the wrc20 code so that its parts can be expressed succinctly in proofs.
+
+```k
+module WRC20
+ imports WASM-TEXT
+```
+
+A module of shorthand commands for the WRC20 module.
+
+```k
+ syntax WasmStringToken ::= "#ethereumModule" [macro]
+ // ----------------------------------------------------
+ rule #ethereumModule => #token("\"ethereum\"", "WasmStringToken")
+
+ syntax ModuleDecl ::= "#wrc20" [macro]
+ syntax Defns ::= "#wrc20Body" [macro]
+ syntax Defns ::= "#wrc20Imports" [macro]
+ syntax Defns ::= "#wrc20Functions_fastBalance" [macro]
+ syntax Defns ::= "#wrc20ReverseBytes" [macro]
+ syntax Int ::= "#wrc20ReverseBytesTypeIdx" [macro]
+ syntax FuncType ::= "#wrc20ReverseBytesType" [macro]
+ // -----------------------------------------------------------
+ rule #wrc20 => ( module #wrc20Body )
+
+ rule #wrc20Body => #wrc20Imports ++Defns #wrc20Functions_fastBalance
+
+ rule #wrc20Imports =>
+ (func String2Identifier("$revert") ( import #ethereumModule #token("\"revert\"" , "WasmStringToken") ) param i32 i32 .ValTypes .TypeDecls )
+ (func String2Identifier("$finish") ( import #ethereumModule #token("\"finish\"" , "WasmStringToken") ) param i32 i32 .ValTypes .TypeDecls )
+ (func String2Identifier("$getCallDataSize") ( import #ethereumModule #token("\"getCallDataSize\"", "WasmStringToken") ) result i32 .ValTypes .TypeDecls )
+ (func String2Identifier("$callDataCopy") ( import #ethereumModule #token("\"callDataCopy\"" , "WasmStringToken") ) param i32 i32 i32 .ValTypes .TypeDecls )
+ (func String2Identifier("$storageLoad") ( import #ethereumModule #token("\"storageLoad\"" , "WasmStringToken") ) param i32 i32 .ValTypes .TypeDecls )
+ (func String2Identifier("$storageStore") ( import #ethereumModule #token("\"storageStore\"" , "WasmStringToken") ) param i32 i32 .ValTypes .TypeDecls )
+ (func String2Identifier("$getCaller") ( import #ethereumModule #token("\"getCaller\"" , "WasmStringToken") ) param i32 .ValTypes .TypeDecls )
+ ( memory ( export #token("\"memory\"", "WasmStringToken") ) 1 )
+ .Defns
+
+ rule #wrc20Functions_fastBalance =>
+ (func ( export #token("\"main\"", "WasmStringToken") ) .TypeDecls .LocalDecls
+ block .TypeDecls
+ block .TypeDecls
+ call String2Identifier("$getCallDataSize")
+ i32.const 4
+ i32.ge_u
+ br_if 0
+ i32.const 0
+ i32.const 0
+ call String2Identifier("$revert")
+ br 1
+ .EmptyStmts
+ end
+ i32.const 0
+ i32.const 0
+ i32.const 4
+ call String2Identifier("$callDataCopy")
+ block .TypeDecls
+ i32.const 0
+ i32.load
+ i32.const 436376473:Int
+ i32.eq
+ i32.eqz
+ br_if 0
+ call String2Identifier("$do_balance")
+ br 1
+ .EmptyStmts
+ end
+ block .TypeDecls
+ i32.const 0 i32.load
+ i32.const 3181327709:Int
+ i32.eq
+ i32.eqz
+ br_if 0
+ call String2Identifier("$do_transfer")
+ br 1
+ .EmptyStmts
+ end
+ i32.const 0
+ i32.const 0
+ call String2Identifier("$revert")
+ .EmptyStmts
+ end
+ .EmptyStmts
+ )
+
+ (func String2Identifier("$do_balance") .TypeDecls .LocalDecls
+ block .TypeDecls
+ block .TypeDecls
+ call String2Identifier("$getCallDataSize")
+ i32.const 24
+ i32.eq
+ br_if 0
+ i32.const 0
+ i32.const 0
+ call String2Identifier("$revert")
+ br 1
+ .EmptyStmts
+ end
+ i32.const 0
+ i32.const 4
+ i32.const 20
+ call String2Identifier("$callDataCopy")
+ i32.const 0
+ i32.const 32
+ call String2Identifier("$storageLoad")
+ i32.const 32
+ i32.const 8
+ call String2Identifier("$finish")
+ .EmptyStmts
+ end
+ .EmptyStmts )
+
+ (func String2Identifier("$do_transfer") .TypeDecls local i64 i64 i64 .ValTypes .LocalDecls
+ block .TypeDecls
+ block .TypeDecls
+ call String2Identifier("$getCallDataSize")
+ i32.const 32
+ i32.eq
+ br_if 0
+ i32.const 0
+ i32.const 0
+ call String2Identifier("$revert")
+ br 1
+ .EmptyStmts
+ end
+ i32.const 0
+ call String2Identifier("$getCaller")
+ i32.const 32
+ i32.const 4
+ i32.const 20
+ call String2Identifier("$callDataCopy")
+ i32.const 64
+ i32.const 24
+ i32.const 8
+ call String2Identifier("$callDataCopy")
+ i32.const 64
+ i64.load
+ call String2Identifier("$i64.reverse_bytes")
+ local.set 0
+ i32.const 0
+ i32.const 64
+ call String2Identifier("$storageLoad")
+ i32.const 64
+ i64.load
+ call String2Identifier("$i64.reverse_bytes")
+ local.set 1
+ i32.const 32
+ i32.const 64
+ call String2Identifier("$storageLoad")
+ i32.const 64
+ i64.load
+ call String2Identifier("$i64.reverse_bytes")
+ local.set 2
+ block .TypeDecls
+ local.get 0
+ local.get 1
+ i64.le_u
+ br_if 0
+ i32.const 0
+ i32.const 0
+ call String2Identifier("$revert")
+ br 1
+ .EmptyStmts
+ end
+ local.get 1
+ local.get 0
+ i64.sub
+ local.set 1
+ local.get 2
+ local.get 0
+ i64.add
+ local.set 2
+ i32.const 64
+ local.get 1
+ call String2Identifier("$i64.reverse_bytes")
+ i64.store
+ i32.const 0
+ i32.const 64
+ call String2Identifier("$storageStore")
+ i32.const 64
+ local.get 2
+ call String2Identifier("$i64.reverse_bytes")
+ i64.store
+ i32.const 32
+ i32.const 64
+ call String2Identifier("$storageStore")
+ .EmptyStmts
+ end
+ .EmptyStmts
+ )
+
+ #wrc20ReverseBytes
+
+ rule #wrc20ReverseBytesTypeIdx => 1
+ rule #wrc20ReverseBytesType => [ i64 ] -> [ i64 ] [ignoreThisAttribute]
+
+ rule #wrc20ReverseBytes =>
+ (func String2Identifier("$i64.reverse_bytes") (type #wrc20ReverseBytesTypeIdx) local i64 i64 .ValTypes .LocalDecls
+ block .TypeDecls
+ loop .TypeDecls
+ local.get 1
+ i64.const 8
+ i64.ge_u
+ br_if 1
+ local.get 0
+ i64.const 56
+ local.get 1
+ i64.const 8
+ i64.mul
+ i64.sub
+ i64.shl
+ i64.const 56
+ i64.shr_u
+ i64.const 56
+ i64.const 8
+ local.get 1
+ i64.mul
+ i64.sub
+ i64.shl
+ local.get 2
+ i64.add
+ local.set 2
+ local.get 1
+ i64.const 1
+ i64.add
+ local.set 1
+ br 0
+ .EmptyStmts
+ end
+ .EmptyStmts
+ end
+ local.get 2
+ .EmptyStmts
+ )
+ .Defns
+
+ syntax Defns ::= Defns "++Defns" Defns [function, total]
+ // -------------------------------------------------------------
+ rule .Defns ++Defns DS' => DS'
+ rule (D DS) ++Defns DS' => D (DS ++Defns DS')
+```
+
+```k
+endmodule
+```