├── .github ├── actions │ └── with-docker │ │ └── action.yml └── workflows │ ├── master-push.yml │ ├── test-pr.yml │ └── update-version.yml ├── .gitignore ├── .gitmodules ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── deps ├── k_release ├── pyproject-build-systems ├── rv-nix-tools ├── uv2nix └── uv_release ├── flake.lock ├── flake.nix ├── media ├── 201803-presentation-ethcc.md ├── 201903-presentation-chalmers.md ├── 201903-presentation-edcon.md ├── 201903-report-chalmers.md ├── 201906-presentation-wasm-on-blockchain.md ├── 202001-presentation-dlab.md ├── 202001-presentation-thesis-chalmers.md ├── berlin-demo │ ├── README.md │ ├── div1-spec.k │ ├── div2-spec.k │ ├── div3-spec.k │ ├── div4-spec.k │ ├── example-execution.wast │ └── pre-run.sh ├── citations.md ├── ieee.csl ├── img │ ├── RV-logo-blue.eps │ ├── cover_image.svg │ ├── dapphub.png │ ├── ethereum.png │ ├── ewasm-contract.png │ ├── github-top-screenshot.png │ ├── github-verified-contracts-screenshot.png │ ├── k-overview.png │ ├── k.png │ ├── kevm-paper.png │ ├── maker.png │ ├── reachability-logic-inference-system.png │ └── rv.png ├── k-overview.png └── memory-demo │ ├── .gitignore │ ├── README.md │ ├── example_memory.wast │ ├── memory-spec.k │ └── wasm.k ├── nix ├── README.md ├── kwasm-pyk │ ├── build-systems-overlay.nix │ └── default.nix ├── kwasm-source │ └── default.nix └── kwasm │ ├── default.nix │ └── test.nix ├── package ├── version └── version.sh ├── pykwasm ├── .cruft.json ├── .flake8 ├── .gitignore ├── Makefile ├── README.md ├── pyproject.toml ├── src │ ├── pykwasm │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── kdist │ │ │ ├── __init__.py │ │ │ ├── plugin.py │ │ │ └── wasm-semantics │ │ │ │ ├── auxil.md │ │ │ │ ├── kwasm-lemmas.md │ │ │ │ ├── numeric.md │ │ │ │ ├── test.md │ │ │ │ ├── wasm-data.md │ │ │ │ ├── wasm-data │ │ │ │ ├── int-type.k │ │ │ │ ├── list-int.k │ │ │ │ ├── list-ref.k │ │ │ │ ├── sparse-bytes.k │ │ │ │ └── tools.k │ │ │ │ ├── wasm-text.md │ │ │ │ ├── wasm.md │ │ │ │ └── wrc20.md │ │ ├── kwasm_ast.py │ │ ├── py.typed │ │ ├── scripts │ │ │ ├── __init__.py │ │ │ ├── convert.py │ │ │ ├── kwasm.py │ │ │ └── preprocessor.py │ │ └── wasm2kast.py │ └── tests │ │ ├── __init__.py │ │ ├── conftest.py │ │ ├── integration │ │ ├── __init__.py │ │ ├── binary │ │ │ ├── basic-features.wat │ │ │ ├── datas.wat │ │ │ ├── elems.wat │ │ │ ├── exports.wat │ │ │ ├── funcs.wat │ │ │ ├── globals.wat │ │ │ ├── imports.wat │ │ │ ├── instrs.wat │ │ │ ├── memories.wat │ │ │ ├── spec_elem_0.wat │ │ │ ├── spec_elem_1.wat │ │ │ ├── spec_elem_2.wat │ │ │ ├── start.wat │ │ │ ├── tables.wat │ │ │ └── types.wat │ │ └── test_binary_parser.py │ │ └── unit │ │ ├── __init__.py │ │ ├── test_kwasm_ast.py │ │ └── test_wasm2kast.py └── uv.lock └── tests ├── conformance ├── look_for_supported.sh ├── unparseable.txt └── unsupported-llvm.txt ├── failing.proofs ├── failing.simple ├── interactive ├── config.xml ├── fac.wast ├── fac.wast.out ├── memory.wast ├── memory.wast.out ├── ret.wast ├── ret.wast.out ├── sum.wast └── sum.wast.out ├── proofs ├── functions-spec.k ├── locals-spec.k ├── loops-spec.k ├── memory-spec.k ├── simple-arithmetic-spec.k └── wrc20-spec.k ├── simple ├── address-c.wast ├── arithmetic.wast ├── bitwise.wast ├── branching.wast ├── comments.wast ├── comparison.wast ├── constants.wast ├── control-flow.wast ├── conversion.wast ├── data.wast ├── desugaring.wast ├── f64-cs.wast ├── f64_bitwise-cs.wast ├── f64_cmp-cs.wast ├── fconversions-c.wast ├── functions_call.wast ├── i64.wast ├── identifiers.wast ├── imports.wast ├── integers.wast ├── memory.wast ├── modules.wast ├── polymorphic.wast ├── start.wast ├── table.wast ├── text2abstract.wast ├── unicode.wast └── variables.wast ├── success-k.out └── success-llvm.out /.github/actions/with-docker/action.yml: -------------------------------------------------------------------------------- 1 | name: 'With Docker' 2 | description: 'Run a given stage with Docker Image' 3 | inputs: 4 | container-name: 5 | description: 'Docker container name to use' 6 | required: true 7 | runs: 8 | using: 'composite' 9 | steps: 10 | - name: 'Set up Docker' 11 | shell: bash {0} 12 | env: 13 | CONTAINER_NAME: ${{ inputs.container-name }} 14 | run: | 15 | set -euxo pipefail 16 | 17 | TAG=runtimeverificationinc/${CONTAINER_NAME} 18 | K_COMMIT=$(cat ./deps/k_release) 19 | UV_VERSION=$(cat deps/uv_release) 20 | 21 | docker build . \ 22 | --tag ${TAG} \ 23 | --build-arg K_COMMIT=${K_COMMIT} \ 24 | --build-arg UV_VERSION=$(UV_VERSION) 25 | 26 | docker run \ 27 | --name ${CONTAINER_NAME} \ 28 | --rm \ 29 | --interactive \ 30 | --tty \ 31 | --detach \ 32 | --user root \ 33 | --workdir /home/user \ 34 | ${TAG} 35 | 36 | docker cp . ${CONTAINER_NAME}:/home/user 37 | docker exec ${CONTAINER_NAME} chown -R user:user /home/user 38 | -------------------------------------------------------------------------------- /.github/workflows/master-push.yml: -------------------------------------------------------------------------------- 1 | name: 'Master Push' 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | 9 | release: 10 | name: 'Publish Release' 11 | runs-on: ubuntu-latest 12 | environment: production 13 | steps: 14 | - name: 'Check out code' 15 | uses: actions/checkout@v3 16 | with: 17 | ref: ${{ github.event.push.head.sha }} 18 | fetch-depth: 0 19 | - name: 'Make release' 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | run: | 23 | set -x 24 | VERSION=v$(cat package/version) 25 | gh release create ${VERSION} --target ${{ github.sha }} 26 | - name: 'Update dependents' 27 | run: | 28 | set -x 29 | version="$(cat package/version)" 30 | curl --fail \ 31 | -X POST \ 32 | -H "Accept: application/vnd.github+json" \ 33 | -H "Authorization: Bearer ${{ secrets.JENKINS_GITHUB_PAT }}" \ 34 | -H "X-GitHub-Api-Version: 2022-11-28" \ 35 | https://api.github.com/repos/runtimeverification/devops/dispatches \ 36 | -d '{"event_type":"on-demand-test","client_payload":{"repo":"runtimeverification/wasm-semantics","version":"'${version}'"}}' 37 | 38 | nix-cache: 39 | name: 'Populate Nix Cache' 40 | strategy: 41 | matrix: 42 | include: 43 | - runner: normal 44 | - runner: ARM64 45 | runs-on: ${{ matrix.runner }} 46 | steps: 47 | - name: 'Check out code' 48 | uses: actions/checkout@v3 49 | with: 50 | ref: ${{ github.event.push.head.sha }} 51 | fetch-depth: 0 52 | - name: 'Upgrade bash' 53 | if: ${{ contains(matrix.os, 'macos') }} 54 | run: brew install bash 55 | - name: 'Build and cache KWASM' 56 | uses: workflow/nix-shell-action@v3.4.0 57 | env: 58 | GC_DONT_GC: 1 59 | CACHIX_AUTH_TOKEN: '${{ secrets.CACHIX_PUBLIC_TOKEN }}' 60 | with: 61 | packages: jq 62 | script: | 63 | kwasm=$(nix build --extra-experimental-features 'nix-command flakes' .#kwasm --json | jq -r '.[].outputs | to_entries[].value') 64 | drv=$(nix-store --query --deriver ${kwasm}) 65 | nix-store --query --requisites --include-outputs ${drv} | cachix push k-framework 66 | -------------------------------------------------------------------------------- /.github/workflows/test-pr.yml: -------------------------------------------------------------------------------- 1 | name: 'Run Tests' 2 | on: 3 | pull_request: 4 | workflow_dispatch: 5 | concurrency: 6 | group: ${{ github.workflow }}-${{ github.ref }} 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | 11 | version-bump: 12 | name: 'Version Bump' 13 | runs-on: [self-hosted, linux, flyweight] 14 | steps: 15 | - name: 'Check out code' 16 | uses: actions/checkout@v3 17 | with: 18 | token: ${{ secrets.JENKINS_GITHUB_PAT }} 19 | # fetch-depth 0 means deep clone the repo 20 | fetch-depth: 0 21 | ref: ${{ github.event.pull_request.head.sha }} 22 | - name: 'Configure GitHub user' 23 | run: | 24 | git config user.name devops 25 | git config user.email devops@runtimeverification.com 26 | - name: 'Update version' 27 | run: | 28 | og_version=$(git show origin/${GITHUB_BASE_REF}:package/version) 29 | ./package/version.sh bump ${og_version} 30 | ./package/version.sh sub 31 | new_version=$(cat package/version) 32 | git add --update && git commit --message "Set Version: ${new_version}" || true 33 | - name: 'Push updates' 34 | run: git push origin HEAD:${GITHUB_HEAD_REF} 35 | 36 | pykwasm-code-quality-checks: 37 | name: 'Code Quality Checks' 38 | runs-on: ubuntu-latest 39 | steps: 40 | - name: 'Check out code' 41 | uses: actions/checkout@v3 42 | with: 43 | submodules: recursive 44 | - name: 'Get uv release' 45 | id: uv_release 46 | run: | 47 | echo uv_version=$(cat deps/uv_release) >> "${GITHUB_OUTPUT}" 48 | - name: 'Install uv' 49 | uses: astral-sh/setup-uv@v6 50 | with: 51 | version: ${{ steps.uv_release.outputs.uv_version }} 52 | - name: 'Run code quality checks' 53 | run: make -C pykwasm check 54 | - name: 'Run pyupgrade' 55 | run: make -C pykwasm pyupgrade 56 | - name: 'Run unit tests' 57 | run: make -C pykwasm cov-unit 58 | 59 | conformance-tests: 60 | name: 'Conformance Tests' 61 | needs: pykwasm-code-quality-checks 62 | runs-on: [self-hosted, linux, normal] 63 | timeout-minutes: 30 64 | steps: 65 | - name: 'Check out code' 66 | uses: actions/checkout@v3 67 | with: 68 | submodules: recursive 69 | - name: 'Set up Docker' 70 | uses: ./.github/actions/with-docker 71 | with: 72 | container-name: kwasm-ci-conformance-${{ github.sha }} 73 | - name: 'Build KWasm definitions' 74 | run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make build 75 | - name: 'Run integration tests' 76 | run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make -C pykwasm cov-integration 77 | - name: 'Run simple tests' 78 | run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make -j2 test-simple 79 | - name: 'Run conformance tests: run' 80 | run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make -j2 test-conformance-supported 81 | - name: 'Run conformance tests: parse' 82 | run: docker exec -u user kwasm-ci-conformance-${GITHUB_SHA} make test-conformance-parse 83 | - name: 'Tear down Docker' 84 | if: always() 85 | run: | 86 | docker stop --time=0 kwasm-ci-conformance-${GITHUB_SHA} 87 | 88 | prove-tests: 89 | name: 'Prover Tests' 90 | needs: pykwasm-code-quality-checks 91 | runs-on: [self-hosted, linux, normal] 92 | timeout-minutes: 45 93 | steps: 94 | - name: 'Check out code' 95 | uses: actions/checkout@v3 96 | with: 97 | submodules: recursive 98 | - name: 'Set up Docker' 99 | uses: ./.github/actions/with-docker 100 | with: 101 | container-name: kwasm-ci-prove-${{ github.sha }} 102 | - name: 'Build KWasm definitions' 103 | run: docker exec -u user kwasm-ci-prove-${GITHUB_SHA} make build 104 | - name: 'Run prover tests' 105 | run: docker exec -u user kwasm-ci-prove-${GITHUB_SHA} make -j6 test-prove 106 | - name: 'Tear down Docker' 107 | if: always() 108 | run: | 109 | docker stop --time=0 kwasm-ci-prove-${GITHUB_SHA} 110 | 111 | nix: 112 | name: 'Nix' 113 | strategy: 114 | fail-fast: false 115 | matrix: 116 | include: 117 | - runner: normal 118 | - runner: ARM64 119 | needs: pykwasm-code-quality-checks 120 | runs-on: ${{ matrix.runner }} 121 | timeout-minutes: 90 122 | steps: 123 | - name: 'Check out code' 124 | uses: actions/checkout@v3 125 | with: 126 | # Check out pull request HEAD instead of merge commit. 127 | ref: ${{ github.event.pull_request.head.sha }} 128 | - name: 'Build KWASM' 129 | run: GC_DONT_GC=1 nix build .#kwasm --extra-experimental-features 'nix-command flakes' --print-build-logs 130 | - name: 'Build KWASM-Pyk' 131 | run: GC_DONT_GC=1 nix build .#kwasm-pyk --extra-experimental-features 'nix-command flakes' --print-build-logs 132 | - name: 'Test KWASM' 133 | run: GC_DONT_GC=1 nix build .#kwasm-test --extra-experimental-features 'nix-command flakes' --print-build-logs 134 | -------------------------------------------------------------------------------- /.github/workflows/update-version.yml: -------------------------------------------------------------------------------- 1 | name: 'Update Version' 2 | on: 3 | push: 4 | branches: 5 | - '_update-deps/runtimeverification/k' 6 | - '_update-deps/runtimeverification/rv-nix-tools' 7 | - '_update-deps-cron/uv2nix' 8 | - '_update-deps-cron/pyproject-build-systems' 9 | 10 | # Stop in progress workflows on the same branch and same workflow to use latest committed code 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | 17 | update-versions: 18 | name: 'Update dependency versions' 19 | runs-on: ubuntu-22.04 20 | steps: 21 | - name: 'Check out code' 22 | uses: actions/checkout@v3 23 | with: 24 | submodules: recursive 25 | token: ${{ secrets.JENKINS_GITHUB_PAT }} 26 | - run: | 27 | git config user.name devops 28 | git config user.email devops@runtimeverification.com 29 | - name: 'Install Nix' 30 | uses: cachix/install-nix-action@v31.5.1 31 | with: 32 | install_url: https://releases.nixos.org/nix/nix-2.30.1/install 33 | extra_nix_config: | 34 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 35 | substituters = http://cache.nixos.org https://hydra.iohk.io 36 | trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= 37 | - name: 'Install Cachix' 38 | uses: cachix/cachix-action@v14 39 | with: 40 | name: k-framework 41 | authToken: '${{ secrets.CACHIX_PUBLIC_TOKEN }}' 42 | # note: we install the same version of `uv` as used by `uv2nix` in order to match the nix derivation 43 | - name: 'Update uv release tag' 44 | id: uv_release 45 | run: | 46 | UV2NIX_VERSION=$(cat deps/uv2nix) 47 | UV_VERSION=$(curl -s https://raw.githubusercontent.com/pyproject-nix/uv2nix/$(cat deps/uv2nix)/pkgs/uv-bin/srcs.json | jq -r .version) 48 | [[ "$UV_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] 49 | echo $UV_VERSION > deps/uv_release 50 | git add deps/uv_release && git commit -m "Sync uv version: uv ${UV_VERSION}" || true 51 | echo uv_version=$UV_VERSION >> "${GITHUB_OUTPUT}" 52 | - name: 'Install uv' 53 | uses: astral-sh/setup-uv@v6 54 | with: 55 | version: ${{ steps.uv_release.outputs.uv_version }} 56 | - name: 'Update uv files' 57 | run: | 58 | K_VERSION=$(cat deps/k_release) 59 | sed -i 's! "kframework>=[0-9\.]*",! "kframework>='${K_VERSION}'",!' pykwasm/pyproject.toml 60 | uv --project pykwasm lock --upgrade 61 | git add pykwasm/ && git commit -m "pykwasm/: sync uv files ${K_VERSION}" || true 62 | - name: 'Update Nix flake inputs' 63 | run: | 64 | K_VERSION=v"$(cat deps/k_release)" 65 | UV2NIX_VERSION=$(cat deps/uv2nix) 66 | PYPROJECT_BUILD_SYSTEMS_VERSION=$(cat deps/pyproject-build-systems) 67 | RV_NIX_TOOLS_VERSION=$(cat deps/rv-nix-tools) 68 | sed -i 's! k-framework.url = "github:runtimeverification/k/v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+"! k-framework.url = "github:runtimeverification/k/'"${K_VERSION}"'"!' flake.nix 69 | sed -i 's! uv2nix.url = "github:pyproject-nix/uv2nix/[a-z0-9\.]*"! uv2nix.url = "github:pyproject-nix/uv2nix/'"${UV2NIX_VERSION}"'"!' flake.nix 70 | sed -i 's! pyproject-build-systems.url = "github:pyproject-nix/build-system-pkgs/[a-z0-9\.]*"! pyproject-build-systems.url = "github:pyproject-nix/build-system-pkgs/'"${PYPROJECT_BUILD_SYSTEMS_VERSION}"'"!' flake.nix 71 | sed -i 's! rv-nix-tools.url = "github:runtimeverification/rv-nix-tools/[a-z0-9\.]*"! rv-nix-tools.url = "github:runtimeverification/rv-nix-tools/'"${RV_NIX_TOOLS_VERSION}"'"!' flake.nix 72 | nix flake update 73 | git add flake.nix flake.lock && git commit -m 'flake.{nix,lock}: update Nix derivations' || true 74 | - name: 'Push updates' 75 | run: git push 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.kwasm-logs/ 2 | /tests/*/*-out 3 | 4 | *.pdf 5 | *.sty 6 | 7 | .krun* 8 | .kprove* 9 | .kompile* 10 | 11 | .envrc 12 | result 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tests/wasm-tests"] 2 | path = tests/wasm-tests 3 | url = https://github.com/webassembly/spec 4 | ignore = untracked 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributor License Agreement 2 | 3 | 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. 4 | 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. 5 | 6 | 1. *Definitions.* 7 | 8 | - “Contribution” means any work of authorship that is submitted by You to Runtime in which You own or assert ownership of the Copyright. 9 | - “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.” 10 | - “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. 11 | 12 | 2. *Your Submission.* 13 | You must agree to the terms of this Agreement before making a Submission to Runtime. 14 | This Agreement covers any and all Submissions that You make to Runtime now or in the future (except as described in Section 4 below). 15 | 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. 16 | 17 | 3. *Original Work.* 18 | You warrant that each of Your Submissions is entirely Your original work. 19 | 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. 20 | 21 | 4. *Your Employer.* 22 | 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. 23 | 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. 24 | 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. 25 | 26 | 5. *Licenses; Moral Rights.* 27 | 28 | 5.1. *Copyright License.* 29 | 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. 30 | 31 | 5.2. *Patent License.* 32 | 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. 33 | 34 | 5.3. *Moral Rights.* 35 | 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. 36 | 37 | 5.4. *Other Rights Reserved.* 38 | Each party reserves all rights not expressly granted in this Agreement. 39 | 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. 40 | No additional licenses or rights whatsoever (including, without limitation, any implied licenses) are granted hereby, by implication or otherwise. 41 | 42 | 6. *Representations and Warranties.* 43 | 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. 44 | 45 | 7. *Disclaimer.* 46 | You are not expected to provide support for Your Submission, unless You choose to do so. 47 | 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. 48 | 49 | 8. *Notice to Runtime.* 50 | 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. 51 | 52 | 9. *Information about Submissions.* 53 | 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. 54 | 55 | 10. *Governing Law/Jurisdiction.* 56 | 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. 57 | The parties waive all defenses of lack of personal jurisdiction and forum non-conveniens. 58 | 59 | 11. *Entire Agreement/Assignment.* 60 | 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. 61 | This Agreement may be assigned by Runtime. 62 | 63 | By signing, You accept and agree to the terms of this Contributor License Agreement for Your present and all future Submissions to Runtime. 64 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG K_COMMIT 2 | FROM runtimeverificationinc/kframework-k:ubuntu-jammy-${K_COMMIT} 3 | 4 | RUN apt-get update \ 5 | && apt-get upgrade --yes \ 6 | && apt-get install --yes \ 7 | curl wabt 8 | 9 | ARG USER_ID=1000 10 | ARG GROUP_ID=1000 11 | RUN groupadd -g $GROUP_ID user && useradd -m -u $USER_ID -s /bin/sh -g user user 12 | 13 | USER user:user 14 | WORKDIR /home/user 15 | 16 | ENV PATH=/home/user/.local/bin:${PATH} 17 | 18 | ARG UV_VERSION 19 | RUN curl -LsSf https://astral.sh/uv/$UV_VERSION/install.sh | sh \ 20 | && uv --version 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | The WebAssembly Semantics in K Release License 3 | ============================================================================== 4 | University of Illinois/NCSA 5 | Open Source License 6 | 7 | Copyright (c) 2009-2019 University of Illinois at Urbana-Champaign. 8 | All rights reserved. 9 | 10 | Developed by: 11 | 12 | K Team (http://kframework.org) 13 | with members from: 14 | 15 | * University of Illinois at Urbana-Champaign (http://fsl.cs.illinois.edu/) 16 | * Runtime Verification, Inc (https://www.runtimeverification.com) 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy of 19 | this software and associated documentation files (the "Software"), to deal with 20 | the Software without restriction, including without limitation the rights to 21 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 22 | of the Software, and to permit persons to whom the Software is furnished to do 23 | so, subject to the following conditions: 24 | 25 | 26 | * Redistributions of source code must retain the above copyright notice, 27 | this list of conditions and the following disclaimers. 28 | 29 | * Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimers in the 31 | documentation and/or other materials provided with the distribution. 32 | 33 | * Neither the names of the K Team, Runtime Verification, the University of 34 | Illinois at Urbana-Champaign, nor the names of its contributors may be 35 | used to endorse or promote products derived from this Software without 36 | specific prior written permission. 37 | 38 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 40 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 41 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 42 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 43 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 44 | SOFTWARE. 45 | 46 | ============================================================================== 47 | Copyrights and Licenses for Third Party Software Distributed with the WebAssembly 48 | Semantics in K: 49 | ============================================================================== 50 | The WebAssembly Semantics in K software contains code written by third parties. 51 | Licenses for this software can be found in the licenses directory 52 | in the file as specified below. These files will describe the copyrights, 53 | license, and restrictions which apply to that code. 54 | 55 | The disclaimer of warranty in the University of Illinois Open Source License 56 | applies to all code in the WebAssembly Semantics in K Distribution, and nothing 57 | in any of the other licenses gives permission to use the names of the K Team, 58 | Runtime Verification, or the University of Illinois 59 | to endorse or promote products derived from this Software. 60 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | UV := uv 2 | UV_RUN := $(UV) run -- 3 | 4 | 5 | .PHONY: all \ 6 | test test-execution test-simple test-prove \ 7 | test-conformance test-conformance-parse test-conformance-supported \ 8 | media presentations reports 9 | 10 | 11 | all: build 12 | 13 | 14 | # Building Definition 15 | # ------------------- 16 | 17 | ifneq ($(NIX),1) 18 | UV := uv --project pykwasm 19 | UV_RUN := $(UV) run -- 20 | KDIST := $(UV_RUN) kdist 21 | endif 22 | 23 | .PHONY: build 24 | build: 25 | $(KDIST) -v build -j3 wasm-semantics.* 26 | 27 | .PHONY: clean 28 | clean: 29 | $(KDIST) clean 30 | 31 | 32 | # Testing 33 | # ------- 34 | 35 | TEST := $(UV_RUN) kwasm 36 | CHECK := git --no-pager diff --no-index --ignore-all-space -R 37 | 38 | TEST_CONCRETE_BACKEND := llvm 39 | TEST_SYMBOLIC_BACKEND := haskell 40 | 41 | test: test-execution test-prove 42 | 43 | # Generic Test Harnesses 44 | 45 | tests/%.run: tests/% 46 | $(TEST) run $< > tests/$*.$(TEST_CONCRETE_BACKEND)-out 47 | $(CHECK) tests/$*.$(TEST_CONCRETE_BACKEND)-out tests/success-$(TEST_CONCRETE_BACKEND).out 48 | rm -rf tests/$*.$(TEST_CONCRETE_BACKEND)-out 49 | 50 | tests/%.run-term: tests/% 51 | $(TEST) run $< > tests/$*.$(TEST_CONCRETE_BACKEND)-out 52 | grep --after-context=2 "" tests/$*.$(TEST_CONCRETE_BACKEND)-out > tests/$*.$(TEST_CONCRETE_BACKEND)-out-term 53 | $(CHECK) tests/$*.$(TEST_CONCRETE_BACKEND)-out-term tests/success-k.out 54 | rm -rf tests/$*.$(TEST_CONCRETE_BACKEND)-out 55 | rm -rf tests/$*.$(TEST_CONCRETE_BACKEND)-out-term 56 | 57 | tests/%.parse: tests/% 58 | K_OPTS='-Xmx16G -Xss512m' $(TEST) kast --output kore $< > $@-out 59 | rm -rf $@-out 60 | 61 | tests/%.prove: tests/% 62 | $(eval SOURCE_DIR := $(shell $(KDIST) which wasm-semantics.source)) 63 | $(TEST) prove $< kwasm-lemmas -I $(SOURCE_DIR)/wasm-semantics -w2e --haskell-backend-command "kore-exec --smt-timeout 5000" 64 | 65 | tests/proofs/wrc20-spec.k.prove: tests/proofs/wrc20-spec.k 66 | $(eval SOURCE_DIR := $(shell $(KDIST) which wasm-semantics.source)) 67 | $(TEST) prove $< wrc20 -I $(SOURCE_DIR)/wasm-semantics -w2e --haskell-backend-command "kore-exec --smt-timeout 500" 68 | 69 | ### Execution Tests 70 | 71 | test-execution: test-simple 72 | 73 | simple_tests := $(wildcard tests/simple/*.wast) 74 | simple_tests_failing := $(shell cat tests/failing.simple) 75 | simple_tests_passing := $(filter-out $(simple_tests_failing), $(simple_tests)) 76 | 77 | test-simple: $(simple_tests_passing:=.run) 78 | 79 | ### Conformance Tests 80 | 81 | conformance_tests:=$(wildcard tests/wasm-tests/test/core/*.wast) 82 | unsupported_conformance_tests:=$(patsubst %, tests/wasm-tests/test/core/%, $(shell cat tests/conformance/unsupported-$(TEST_CONCRETE_BACKEND).txt)) 83 | unparseable_conformance_tests:=$(patsubst %, tests/wasm-tests/test/core/%, $(shell cat tests/conformance/unparseable.txt)) 84 | parseable_conformance_tests:=$(filter-out $(unparseable_conformance_tests), $(conformance_tests)) 85 | supported_conformance_tests:=$(filter-out $(unsupported_conformance_tests), $(parseable_conformance_tests)) 86 | 87 | test-conformance-parse: $(parseable_conformance_tests:=.parse) 88 | test-conformance-supported: $(supported_conformance_tests:=.run-term) 89 | 90 | test-conformance: test-conformance-parse test-conformance-supported 91 | 92 | ### Proof Tests 93 | 94 | proof_tests := $(wildcard tests/proofs/*-spec.k) 95 | proof_tests_failing := $(shell cat tests/failing.proofs) 96 | proof_tests_passing := $(filter-out $(proof_tests_failing), $(proof_tests)) 97 | 98 | test-prove: $(proof_tests_passing:=.prove) 99 | 100 | 101 | # Analysis 102 | # -------- 103 | 104 | json_build := $(haskell_dir)/parsed.json 105 | 106 | $(json_build): 107 | $(MAKE) build-haskell -B KOMPILE_OPTS="--emit-json" 108 | 109 | graph-imports: $(json_build) 110 | kpyk $(haskell_dir) graph-imports 111 | 112 | 113 | # Presentation 114 | # ------------ 115 | 116 | media: presentations reports 117 | 118 | media/%.pdf: TO_FORMAT=beamer 119 | presentations: $(patsubst %.md, %.pdf, $(wildcard media/*-presentation-*.md)) 120 | 121 | media/201903-report-chalmers.pdf: TO_FORMAT=latex 122 | reports: media/201903-report-chalmers.pdf 123 | 124 | media/%.pdf: media/%.md media/citations.md 125 | cat $^ | pandoc --from markdown-latex_macros --to $(TO_FORMAT) --filter pandoc-citeproc --output $@ 126 | 127 | media-clean: 128 | rm media/*.pdf 129 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | KWasm: Semantics of WebAssembly in K 2 | ==================================== 3 | 4 | ### Want to Support KWasm Development? 5 | [Contribute to our Gitcoin Grant.](https://gitcoin.co/grants/592/kewasm-and-kwasm) 6 | 7 | --- 8 | 9 | This repository presents the formal semantics of [WebAssembly]. 10 | KWasm is a mature and production-ready semantics for WebAssembly, actively developed and maintained since 2019. 11 | 12 | For examples of current capabilities, see the unit tests under the `tests/simple` directory. 13 | 14 | Repository Structure 15 | -------------------- 16 | 17 | ### Semantics Layout 18 | 19 | The following files constitute the KWasm semantics: 20 | 21 | - [wasm-data.md](pykwasm/src/pykwasm/kdist/wasm-semantics/wasm-data.md) provides the (functional) data of WebAssembly (basic types, type constructors, and values). 22 | - [numeric.md](pykwasm/src/pykwasm/kdist/wasm-semantics/numeric.md) provides the functional rules for numeric operators. 23 | - [wasm.md](pykwasm/src/pykwasm/kdist/wasm-semantics/wasm.md) is the main KWasm semantics, containing the configuration and transition rules of WebAssembly. 24 | 25 | These additional files extend the semantics to make the repository more useful: 26 | 27 | - [test.md](test.md) is an execution harness for KWasm, providing a simple language for describing tests/programs. 28 | 29 | ### Example usage: `./kwasm` runner script 30 | 31 | After building the definition, you can run the definition using `./kwasm`. 32 | The most up-to-date documentation will always be in `./kwasm help`. 33 | 34 | Run the file `tests/simple/arithmetic.wast`: 35 | 36 | ```sh 37 | ./kwasm run tests/simple/arithmetic.wast 38 | ``` 39 | 40 | To run proofs, you can similarly use `./kwasm`, but must specify the module to use for proving. 41 | For example, to prove the specification `tests/proofs/simple-arithmetic-spec.k`: 42 | 43 | ```sh 44 | ./kwasm prove tests/proofs/simple-arithmetic-spec.k kwasm-lemmas 45 | ``` 46 | 47 | To prove WRC-20 specifications: 48 | 49 | ```sh 50 | ./kwasm prove tests/proofs/wrc20-spec.k wrc20 51 | ``` 52 | 53 | You can optionally override the default backend using the `--backend BACKEND` flag: 54 | 55 | ```sh 56 | ./kwasm run --backend llvm tests/simple/arithmetic.wast 57 | ./kwasm prove --backend haskell tests/proofs/simple-arithmetic-spec.k kwasm-lemmas 58 | ``` 59 | 60 | Installing/Building 61 | ------------------- 62 | 63 | ### K Backends 64 | 65 | There are two backends of K available, the LLVM backend for concrete execution, and the Haskell backend for symbolic reasoning and proofs. 66 | This repository generates the build-products for the backends in `.build/defn/llvm` and `.build/defn/haskell`. 67 | 68 | ### Dependencies 69 | 70 | The following are needed for building/running KWasm: 71 | 72 | - [git](https://git-scm.com/) 73 | - [Pandoc >= 1.17](https://pandoc.org) is used to generate the `*.k` files from the `*.md` files. 74 | - GNU [Bison](https://www.gnu.org/software/bison/), [Flex](https://github.com/westes/flex), and [Autoconf](http://www.gnu.org/software/autoconf/). 75 | - GNU [libmpfr](http://www.mpfr.org/) and [libtool](https://www.gnu.org/software/libtool/). 76 | - Java 8 JDK (eg. [OpenJDK](http://openjdk.java.net/)) 77 | - [Haskell Stack](https://docs.haskellstack.org/en/stable/install_and_upgrade/#installupgrade). 78 | Note that the version of the `stack` tool provided by your package manager might not be recent enough. 79 | Please follow installation instructions from the Haskell Stack website linked above. 80 | - [LLVM](https://llvm.org/) For building the LLVM backend. 81 | - [Z3](https://github.com/Z3Prover/z3) version 4.8.15 82 | 83 | On Ubuntu >= 15.04 (for example): 84 | 85 | ```sh 86 | sudo apt-get install --yes \ 87 | autoconf bison clang++-8 clang-8 cmake curl flex gcc libboost-test-dev libffi-dev \ 88 | libgmp-dev libjemalloc-dev libmpfr-dev libprocps-dev libprotobuf-dev libtool \ 89 | libyaml-dev lld-8 llvm llvm-8 llvm-8-tools maven openjdk-8-jdk pandoc pkg-config \ 90 | protobuf-compiler python3 python-pygments python-recommonmark python-sphinx time \ 91 | zlib1g-dev 92 | ``` 93 | 94 | To upgrade `stack` (if needed): 95 | 96 | ```sh 97 | stack upgrade 98 | export PATH=$HOME/.local/bin:$PATH 99 | ``` 100 | 101 | After installing the above dependencies, make sure the submodules are setup: 102 | 103 | ```sh 104 | git submodule update --init --recursive 105 | ``` 106 | 107 | Install repository specific dependencies: 108 | 109 | ```sh 110 | make deps 111 | ``` 112 | 113 | #### Installing Z3 114 | 115 | Note that KWASM requires Z3 version 4.8.15, which you may need to install from a 116 | source build if your package manager supplies a different version. To do so, 117 | follow the instructions 118 | [here](https://github.com/Z3Prover/z3#building-z3-using-make-and-gccclang) after 119 | checking out the correct tag in the Z3 repository: 120 | 121 | ```sh 122 | git clone https://github.com/Z3Prover/z3.git 123 | cd z3 124 | git checkout z3-4.8.15 125 | python scripts/mk_make.py 126 | cd build 127 | make 128 | sudo make install 129 | ``` 130 | 131 | ### Building 132 | 133 | And then build the semantics: 134 | 135 | ```sh 136 | make build 137 | ``` 138 | 139 | To only build a specific backend, you can do `make build-llvm` or `make build-haskell`. 140 | 141 | ### Media and documents 142 | 143 | The `media/` directory contains presentations and reports about about KWasm. 144 | 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. 145 | 146 | [GhostScript](https://www.ghostscript.com/) is a dependency for building documents of type `report`. 147 | 148 | ```sh 149 | sudo apt install ghostscript 150 | ``` 151 | 152 | To build all documents in the media file: 153 | 154 | ```sh 155 | make media 156 | ``` 157 | 158 | Testing 159 | ------- 160 | 161 | The target `test` contains all the currently passing tests. 162 | 163 | ```sh 164 | make test 165 | ``` 166 | 167 | Resources 168 | --------- 169 | 170 | [WebAssembly]: 171 | -------------------------------------------------------------------------------- /deps/k_release: -------------------------------------------------------------------------------- 1 | 7.1.288 2 | -------------------------------------------------------------------------------- /deps/pyproject-build-systems: -------------------------------------------------------------------------------- 1 | dbfc0483b5952c6b86e36f8b3afeb9dde30ea4b5 2 | -------------------------------------------------------------------------------- /deps/rv-nix-tools: -------------------------------------------------------------------------------- 1 | 854d4f05ea78547d46e807b414faad64cea10ae4 -------------------------------------------------------------------------------- /deps/uv2nix: -------------------------------------------------------------------------------- 1 | be511633027f67beee87ab499f7b16d0a2f7eceb 2 | -------------------------------------------------------------------------------- /deps/uv_release: -------------------------------------------------------------------------------- 1 | 0.8.22 2 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "K Semantics of WebAssembly"; 3 | 4 | inputs = { 5 | rv-nix-tools.url = "github:runtimeverification/rv-nix-tools/854d4f05ea78547d46e807b414faad64cea10ae4"; 6 | nixpkgs.follows = "rv-nix-tools/nixpkgs"; 7 | 8 | k-framework.url = "github:runtimeverification/k/v7.1.288"; 9 | k-framework.inputs.nixpkgs.follows = "nixpkgs"; 10 | 11 | flake-utils.follows = "k-framework/flake-utils"; 12 | 13 | uv2nix.url = "github:pyproject-nix/uv2nix/be511633027f67beee87ab499f7b16d0a2f7eceb"; 14 | # uv2nix requires a newer version of nixpkgs 15 | # therefore, we pin uv2nix specifically to a newer version of nixpkgs 16 | # until we replaced our stale version of nixpkgs with an upstream one as well 17 | # but also uv2nix requires us to call it with `callPackage`, so we add stuff 18 | # from the newer nixpkgs to our stale nixpkgs via an overlay 19 | nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; 20 | uv2nix.inputs.nixpkgs.follows = "nixpkgs-unstable"; 21 | # uv2nix.inputs.nixpkgs.follows = "nixpkgs"; 22 | pyproject-build-systems.url = "github:pyproject-nix/build-system-pkgs/dbfc0483b5952c6b86e36f8b3afeb9dde30ea4b5"; 23 | pyproject-build-systems = { 24 | inputs.nixpkgs.follows = "nixpkgs"; 25 | inputs.uv2nix.follows = "uv2nix"; 26 | inputs.pyproject-nix.follows = "uv2nix/pyproject-nix"; 27 | }; 28 | pyproject-nix.follows = "uv2nix/pyproject-nix"; 29 | }; 30 | 31 | outputs = { 32 | self, 33 | rv-nix-tools, 34 | nixpkgs, 35 | flake-utils, 36 | k-framework, 37 | uv2nix, 38 | pyproject-nix, 39 | pyproject-build-systems, 40 | nixpkgs-unstable, 41 | ... }: 42 | let 43 | pythonVer = "310"; 44 | in flake-utils.lib.eachDefaultSystem (system: 45 | let 46 | pkgs-unstable = import nixpkgs-unstable { 47 | inherit system; 48 | }; 49 | # for uv2nix, remove this once we updated to a newer version of nixpkgs 50 | staleNixpkgsOverlay = final: prev: { 51 | inherit (pkgs-unstable) replaceVars; 52 | }; 53 | uvOverlay = final: prev: { 54 | uv = uv2nix.packages.${final.system}.uv-bin; 55 | }; 56 | # create custom overlay for k, because the overlay in k-framework currently also includes a lot of other stuff instead of only k 57 | kOverlay = final: prev: { 58 | k = k-framework.packages.${final.system}.k; 59 | }; 60 | kwasmOverlay = final: prev: 61 | let 62 | python = final."python${pythonVer}"; 63 | kwasm-pyk = final.callPackage ./nix/kwasm-pyk { 64 | inherit pyproject-nix pyproject-build-systems uv2nix python; 65 | }; 66 | kwasm = final.callPackage ./nix/kwasm { 67 | inherit kwasm-pyk; 68 | rev = self.rev or null; 69 | }; 70 | kwasm-test = final.callPackage ./nix/kwasm/test.nix { 71 | inherit kwasm kwasm-pyk; 72 | }; 73 | in { 74 | inherit kwasm kwasm-pyk kwasm-test; 75 | }; 76 | pkgs = import nixpkgs { 77 | inherit system; 78 | overlays = [ 79 | staleNixpkgsOverlay 80 | uvOverlay 81 | kOverlay 82 | kwasmOverlay 83 | ]; 84 | }; 85 | python = pkgs."python${pythonVer}"; 86 | in { 87 | devShells.defualt = pkgs.mkShell { 88 | packages = with pkgs; [ 89 | k 90 | python 91 | uv 92 | which 93 | ]; 94 | env = { 95 | # prevent uv from managing Python downloads and force use of specific 96 | UV_PYTHON_DOWNLOADS = "never"; 97 | UV_PYTHON = python.interpreter; 98 | }; 99 | shellHook = '' 100 | unset PYTHONPATH 101 | '' + pkgs.lib.strings.optionalString (pkgs.stdenv.isAarch64 && pkgs.stdenv.isDarwin) '' 102 | export APPLE_SILICON=true 103 | ''; 104 | }; 105 | packages = rec { 106 | inherit (pkgs) kwasm kwasm-pyk kwasm-test; 107 | default = kwasm; 108 | }; 109 | } 110 | ) // { 111 | overlays.default = final: prev: { 112 | inherit (self.packages.${final.system}) kwasm; 113 | }; 114 | }; 115 | } 116 | -------------------------------------------------------------------------------- /media/berlin-demo/README.md: -------------------------------------------------------------------------------- 1 | The files in this directory give a demo of a simple Wasm program, and of trying to prove a property of division. 2 | 3 | Standing in this directory, do 4 | 5 | ```sh 6 | ./pre-run.sh 7 | ``` 8 | 9 | This will run the `example-execution.wast` file, and perform proofs on the `div*-spec.k` files. 10 | Two of the proofs will fail, so an error message and non-zero exit codes is to be expected. 11 | 12 | You can then explore exection and proofs with `./kwasm klab-view [FILENAME]`. 13 | For example, `./kwasm klab-view div3-spec.k` 14 | See the documentation for [KLab](https://github.com/dapphub/klab) for details of how to use KLab 15 | -------------------------------------------------------------------------------- /media/berlin-demo/div1-spec.k: -------------------------------------------------------------------------------- 1 | requires "kwasm-lemmas.k" 2 | 3 | module DIV1-SPEC 4 | imports WASM 5 | imports KWASM-LEMMAS 6 | 7 | // Try to prove an incorrect property of unsigned division: 8 | // If X' = X / Y, then X' < X. 9 | 10 | rule (local.set 0 11 | (i32.div_u (local.get 0) (local.get 1))) 12 | // Rewriting to "." means we expect the program to complete 13 | // without trapping. 14 | => . 15 | 16 | 17 | 0 |-> < i32 > (X => X') 18 | 1 |-> < i32 > Y 19 | 20 | // We must specify that X and Y fulfill the invariant for locals to 21 | // be in the unsigned range. Otherwise, X and Y can be *any* integers. 22 | requires #inUnsignedRange(i32, X) 23 | andBool #inUnsignedRange(i32, Y) 24 | ensures X' 0, 11 | // then X' < X 12 | 13 | rule (if (local.get 1) 14 | (then (local.set 0 15 | (i32.div_u (local.get 0) (local.get 1)))) 16 | (else 17 | 18 | (local.set 0 (i32.const 0)))) 19 | => . 20 | 21 | 22 | 0 |-> < i32 > (X => X') 23 | 1 |-> < i32 > Y 24 | 25 | requires #inUnsignedRange(i32, X) 26 | andBool #inUnsignedRange(i32, Y) 27 | 28 | andBool X =/=Int 0 29 | ensures X' 0, 11 | // and Y > 1, 12 | // then X' < X 13 | rule (if (local.get 1) 14 | (then (local.set 0 15 | (i32.div_u (local.get 0) (local.get 1)))) 16 | (else 17 | 18 | (local.set 0 (i32.const 0)))) 19 | => . 20 | 21 | 22 | 0 |-> < i32 > (X => X') 23 | 1 |-> < i32 > Y 24 | 25 | requires #inUnsignedRange(i32, X) 26 | andBool #inUnsignedRange(i32, Y) 27 | andBool Y =/=Int 1 28 | andBool X =/=Int 0 29 | ensures X' 0, 11 | // and Y > 1, 12 | // then X' < X 13 | 14 | // Has en extra neat demonstration, that the `br_if` will not cause a branch, 15 | // because we know the value of Y at that point. 16 | 17 | rule (if (local.get 1) 18 | (then (local.set 0 19 | (i32.div_u (local.get 0) (local.get 1)))) 20 | (else 21 | (br_if 0 (local.get 1)) // Will not branch, due to our constraints. 22 | (local.set 0 (i32.const 0)))) 23 | => . 24 | 25 | 26 | 0 |-> < i32 > (X => X') 27 | 1 |-> < i32 > Y 28 | 29 | requires #inUnsignedRange(i32, X) 30 | andBool #inUnsignedRange(i32, Y) 31 | andBool Y =/=Int 1 32 | andBool X =/=Int 0 33 | ensures X' 4 : < i32 > 24 : .ValStack 2 | 3 | (local.get 1) 4 | (local.get 0) 5 | (i32.div_u) 6 | (local.set 0) -------------------------------------------------------------------------------- /media/berlin-demo/pre-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd ../.. 4 | rm -rf .build/klab 5 | ./build 6 | ./kwasm klab-run media/berlin-demo/example-execution.wast 7 | for i in `seq 4`; do 8 | FILE=div$i-spec.k 9 | echo "" 10 | echo "" 11 | echo "$FILE" 12 | ./kwasm klab-prove media/berlin-demo/$FILE -m KWASM-LEMMAS 13 | done 14 | 15 | cd - 16 | -------------------------------------------------------------------------------- /media/citations.md: -------------------------------------------------------------------------------- 1 | --- 2 | csl: media/ieee.csl 3 | references: 4 | - id: bogdanas-rosu-k-java 5 | type: paper-conference 6 | author: 7 | - family: Bogdănaş 8 | given: Denis 9 | - family: Roşu 10 | given: Grigore 11 | issued: 12 | - year: 2015 13 | title: 'K-Java: A Complete Semantics of Java' 14 | container-title: Proceedings of the 42nd symposium on principles of programming 15 | languages (popl’15) 16 | publisher: ACM 17 | page: 445-456 18 | DOI: http://dx.doi.org/10.1145/2676726.2676982 19 | 20 | - id: hathhorn-ellison-rosu-k-c 21 | type: paper-conference 22 | author: 23 | - family: Hathhorn 24 | given: Chris 25 | - family: Ellison 26 | given: Chucky 27 | - family: Roşu 28 | given: Grigore 29 | issued: 30 | - year: 2015 31 | title: Defining the undefinedness of c 32 | container-title: Proceedings of the 36th acm sigplan conference on programming language 33 | design and implementation (pldi’15) 34 | publisher: ACM 35 | page: 336-345 36 | DOI: http://dx.doi.org/10.1145/2813885.2737979 37 | 38 | - id: park-stefanescu-rosu-k-js 39 | type: paper-conference 40 | author: 41 | - family: Park 42 | given: Daejun 43 | - family: Ştefănescu 44 | given: Andrei 45 | - family: Roşu 46 | given: Grigore 47 | issued: 48 | - year: 2015 49 | title: 'KJS: A complete formal semantics of JavaScript' 50 | title-short: KJS 51 | container-title: Proceedings of the 36th acm sigplan conference on programming language 52 | design and implementation (pldi’15) 53 | publisher: ACM 54 | page: 346-356 55 | DOI: http://dx.doi.org/10.1145/2737924.2737991 56 | 57 | - id: hildenbrandt-saxena-zhu-rosu-k-evm 58 | type: paper-conference 59 | author: 60 | - family: Hildenbrandt 61 | given: Everett 62 | - family: Saxena 63 | given: Manasvi 64 | - family: Zhu 65 | given: Xiaoran 66 | - family: Rodrigues 67 | given: Nishant 68 | - family: Daian 69 | given: Philip 70 | - family: Guth 71 | given: Dwight 72 | - family: Moore 73 | given: Brandon 74 | - family: Zhang 75 | given: Yi 76 | - family: Park 77 | given: Daejun 78 | - family: Ştefănescu 79 | given: Andrei 80 | - family: Roşu 81 | given: Grigore 82 | issued: 83 | - year: 2018 84 | title: 'KEVM: A complete semantics of the ethereum virtual machine' 85 | title-short: KEVM 86 | container-title: 2018 ieee 31st computer security foundations symposium 87 | publisher: IEEE 88 | page: 204-217 89 | 90 | - id: kheradmand-rosu-k-p4 91 | type: report 92 | author: 93 | - family: Kheradmand 94 | given: Ali 95 | - family: Roşu 96 | given: Grigore 97 | issued: 98 | - year: 2018 99 | title: 'P4K: A formal semantics of p4 and applications' 100 | title-short: P4K 101 | publisher: University of Illinois at Urbana-Champaign 102 | number: https://arxiv.org/abs/1804.01468 103 | 104 | - id: kasampalis-guth-moore-rosu-johnson-k-iele 105 | type: report 106 | author: 107 | - family: Kasampalis 108 | given: Theodoros 109 | - family: Guth 110 | given: Dwight 111 | - family: Moore 112 | given: Brandon 113 | - family: Serbanuta 114 | given: Traian 115 | - family: Serbanuta 116 | given: Virgil 117 | - family: Filaretti 118 | given: Daniele 119 | - family: Rosu 120 | given: Grigore 121 | - family: Johnson 122 | given: Ralph 123 | issued: 124 | - year: 2018 125 | title: 'IELE: An intermediate-level blockchain language designed and implemented 126 | using formal semantics' 127 | title-short: IELE 128 | publisher: University of Illinois 129 | number: http://hdl.handle.net/2142/100320 130 | 131 | - id: stefanescu-park-yuwen-li-rosu-reachability-prover 132 | type: paper-conference 133 | author: 134 | - family: Ştefănescu 135 | given: Andrei 136 | - family: Park 137 | given: Daejun 138 | - family: Yuwen 139 | given: Shijiao 140 | - family: Li 141 | given: Yilong 142 | - family: Roşu 143 | given: Grigore 144 | issued: 145 | - year: 2016 146 | month: 11 147 | title: Semantics-based program verifiers for all languages 148 | container-title: Proceedings of the 31th conference on object-oriented programming, 149 | systems, languages, and applications (oopsla’16) 150 | publisher: ACM 151 | page: 74-91 152 | DOI: http://dx.doi.org/10.1145/2983990.2984027 153 | 154 | - id: alpuente-cuenca-ortega-escobar-meseguer 155 | type: article-journal 156 | author: 157 | - family: Alpuente 158 | given: María 159 | - family: Cuenca-Ortega 160 | given: Angel 161 | - family: Escobar 162 | given: Santiago 163 | - family: Meseguer 164 | given: José 165 | issued: 166 | - year: 2016 167 | title: Partial evaluation of order-sorted equational programs modulo axioms 168 | container-title: CoRR 169 | volume: abs/1608.03424 170 | URL: http://arxiv.org/abs/1608.03424 171 | 172 | - id: meseguer-rusu-generalized-rewrite-coherence-completion 173 | type: paper-conference 174 | author: 175 | - family: Meseguer 176 | given: José 177 | editor: 178 | - family: Rusu 179 | given: Vlad 180 | issued: 181 | - year: '2018' 182 | title: Generalized rewrite theories and coherence completion 183 | container-title: Rewriting logic and its applications - 12th international workshop, 184 | wrla 2018, held as a satellite event of etaps, 2018, proceedings 185 | collection-title: Lecture notes in computer science (including subseries lecture 186 | notes in artificial intelligence and lecture notes in bioinformatics) 187 | publisher: Springer-Verlag 188 | page: '164-183' 189 | keyword: Coherence, Rewriting, Symbolic execution, Variants 190 | DOI: 10.1007/978-3-319-99840-4_10 191 | ISBN: '9783319998398' 192 | 193 | 194 | - id: rossberg-web-up-to-speed 195 | type: article-journal 196 | author: 197 | - family: Rossberg 198 | given: Andreas 199 | - family: Titzer 200 | given: Ben L. 201 | - family: Haas 202 | given: Andreas 203 | - family: Schuff 204 | given: Derek L. 205 | - family: Gohman 206 | given: Dan 207 | - family: Wagner 208 | given: Luke 209 | - family: Zakai 210 | given: Alon 211 | - family: Bastien 212 | given: J. F. 213 | - family: Holman 214 | given: Michael 215 | issued: 216 | - year: 2018 217 | title: Bringing the web up to speed with webassembly. 218 | container-title: Communications of the ACM 219 | page: 107 - 115 220 | volume: '61' 221 | issue: '12' 222 | abstract: This article discusses the implementation of the low-level computer programming 223 | language for software known as WebAssembly. The authors comment on the use of 224 | WebAssembly in advanced web applications, including three-dimensional visualization, 225 | audio and video software, and gaming. The benefits of WebAssembly include its 226 | ability to function independent of the computer hardware and operating system 227 | on which it runs. 228 | keyword: PROGRAMMING languages, ASSEMBLY languages (Electronic computers), COMPUTER 229 | operating systems, COMPUTER software, THREE-dimensional imaging, WEB-based user 230 | interfaces 231 | ISSN: '00010782' 232 | 233 | ... 234 | 235 | -------------------------------------------------------------------------------- /media/img/RV-logo-blue.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/RV-logo-blue.eps -------------------------------------------------------------------------------- /media/img/dapphub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/dapphub.png -------------------------------------------------------------------------------- /media/img/ethereum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/ethereum.png -------------------------------------------------------------------------------- /media/img/ewasm-contract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/ewasm-contract.png -------------------------------------------------------------------------------- /media/img/github-top-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/github-top-screenshot.png -------------------------------------------------------------------------------- /media/img/github-verified-contracts-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/github-verified-contracts-screenshot.png -------------------------------------------------------------------------------- /media/img/k-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/k-overview.png -------------------------------------------------------------------------------- /media/img/k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/k.png -------------------------------------------------------------------------------- /media/img/kevm-paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/kevm-paper.png -------------------------------------------------------------------------------- /media/img/maker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/maker.png -------------------------------------------------------------------------------- /media/img/reachability-logic-inference-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/reachability-logic-inference-system.png -------------------------------------------------------------------------------- /media/img/rv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/img/rv.png -------------------------------------------------------------------------------- /media/k-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/media/k-overview.png -------------------------------------------------------------------------------- /media/memory-demo/.gitignore: -------------------------------------------------------------------------------- 1 | .krun-* 2 | *-kompiled 3 | 4 | -------------------------------------------------------------------------------- /media/memory-demo/README.md: -------------------------------------------------------------------------------- 1 | Building and running example 2 | 3 | ``` 4 | kompile --syntax-module WASM wasm.k 5 | krun example-memory.wast 6 | ``` 7 | 8 | Proving 9 | 10 | ``` 11 | kompile --syntax-module WASM --backend java wasm.k 12 | kprove memory-spec.k 13 | ``` 14 | -------------------------------------------------------------------------------- /media/memory-demo/example_memory.wast: -------------------------------------------------------------------------------- 1 | (i64.const 10) 2 | (memory) 3 | (memory.size) 4 | (memory.grow (i32.const 5)) 5 | (memory.size) 6 | 7 | -------------------------------------------------------------------------------- /media/memory-demo/memory-spec.k: -------------------------------------------------------------------------------- 1 | module MEMORY-SPEC 2 | imports WASM 3 | 4 | rule ( memory.size ) => (i32.const SZ) ... 5 | 0 |-> A 6 | 7 | A 8 | SZ 9 | 10 | 11 | rule (memory.grow (i32.const X)) => (i32.const SZ) ... 12 | 0 |-> A 13 | 14 | A 15 | SZ => (SZ +Int X) 16 | 17 | // Necessary conditions. Remove them to see what happens! 18 | false 19 | requires X >=Int 0 20 | andBool X <=Int (2 ^Int 16) 21 | andBool SZ >=Int 0 22 | 23 | rule (memory.grow (i32.const X)) => (i32.const -1) ... 24 | 0 |-> A 25 | 26 | A 27 | SZ 28 | 29 | // Necessary conditions. Remove them to see what happens! 30 | true 31 | requires X >=Int (2 ^Int 16) 32 | andBool X =Int 0 34 | 35 | endmodule 36 | -------------------------------------------------------------------------------- /media/memory-demo/wasm.k: -------------------------------------------------------------------------------- 1 | module WASM 2 | imports DOMAINS 3 | 4 | // Solutions to the TODOs are in a comment at the bottom of the file. 5 | 6 | configuration 7 | $PGM:Instrs 8 | .Stack 9 | // TODO: Extend the configuration to have a current frame and and a store. 10 | 11 | 12 | // Useful definitions. 13 | 14 | syntax Instrs ::= List{Instr, ""} 15 | // --------------------------------- 16 | rule .Instrs => . 17 | rule I IS:Instrs => I ~> IS ... 18 | 19 | syntax Stack ::= ".Stack" | StackItem ":" Stack 20 | syntax StackItem ::= "<" IType ">" Int 21 | // -------------------------------------- 22 | 23 | syntax IType ::= "i32" | "i64" 24 | // ------------------------------ 25 | 26 | // Functions. 27 | 28 | syntax Int ::= #chop(IType, Int) [function] 29 | // ------------------------------------------- 30 | rule #chop(i32, I) => I modInt (2 ^Int 32) 31 | rule #chop(i64, I) => I modInt (2 ^Int 64) 32 | 33 | 34 | // Basic instructions. 35 | syntax Instr ::= "(" IType "." "const" Int ")" 36 | // ---------------------------------------------- 37 | rule ( ITYPE . const I ) => . ... 38 | S => < ITYPE > #chop(ITYPE, I) : S 39 | 40 | // Memory instructions. 41 | 42 | // Memory instantiation. 43 | syntax Instr ::= "(" "memory" ")" 44 | // --------------------------------- 45 | // TODO: Add a rule that: 46 | // allocates memory with size 0 to the store, and stores saves the address 47 | // to that memory in the current frame. 48 | 49 | syntax Instr ::= "(" "memory.size" ")" 50 | // -------------------------------------- 51 | // TODO: Add a rule that: 52 | // Looks up the memory of the current frame in the store, and pushes its 53 | // size to the stack. 54 | 55 | syntax Instr ::= "(" "memory.grow" ")" | "(" "memory.grow" Instr ")" 56 | // -------------------------------------------------------------------- 57 | // TODO: Add a rule that: 58 | // Unfolds the folded syntax rule. 59 | // TODO: Add a rule that: 60 | // Grows the current memory by a specified value (look at the top of the 61 | // stack). This rule should only apply if the resulting memory size is less 62 | // than 2^16 pages. 63 | // TODO: Add a rule that: 64 | // Only applies if we have a toggle set in the configuration, called 65 | // . If so, it just pushes (i32.const -1). 66 | 67 | endmodule 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | /* 86 | 87 | configuration 88 | $PGM:Instrs 89 | .Stack 90 | 91 | 92 | .Map 93 | 94 | 95 | 96 | 0 97 | 98 | 99 | 0 100 | 0 101 | 102 | 103 | 104 | false 105 | 106 | rule (( memory ) ~> ELSE) => ELSE 107 | .Map => 0 |-> NEXT 108 | NEXT => NEXT +Int 1 109 | 110 | (.Bag => 111 | 112 | NEXT 113 | ... 114 | ) 115 | ... 116 | 117 | 118 | syntax Instr ::= "(" "memory.size" ")" 119 | // -------------------------------------- 120 | rule ( memory.size ) => ( i32.const SZ ) ... 121 | 0 |-> A 122 | 123 | A 124 | SZ 125 | ... 126 | 127 | rule ( memory.size ) => ( i32.const -1 ) ... 128 | 129 | syntax Instr ::= "(" "memory.grow" ")" | "(" "memory.grow" Instr ")" 130 | // -------------------------------------------------------------------- 131 | rule (memory.grow I:Instr) => I ~> (memory.grow) ... 132 | rule (memory.grow) => (i32.const SZ) ... 133 | < i32 > V : S => S 134 | 0 |-> A 135 | 136 | A 137 | SZ => SZ +Int V 138 | 139 | requires SZ +Int V (memory.grow) => (i32.const -1) ... 141 | < i32 > _ : S => S 142 | true 143 | 144 | */ -------------------------------------------------------------------------------- /nix/README.md: -------------------------------------------------------------------------------- 1 | ## Notes 2 | #### git submodules 3 | If you use git submodules that are not required for building the project with `nix`, then you should add these directories to the `gitignoreSourcePure` list in `nix/pykwasm/default.nix`, see the respective left-over `TODO` in the nix file. Otherwise, the nix build that is uploaded to the nix binary cache by CI might not match the version that is requested by `kup`, in case this project is offered as a package by `kup`. This is due to weird behaviour in regards to git submodules by `git` and `nix`, where a submodule directory might exist and be empty or instead not exist, which impacts the resulting nix hash, which is of impartance when offering/downloading cached nix derivations. See [runtimeverification/k/pull/4804](https://github.com/runtimeverification/k/pull/4804) for more information. -------------------------------------------------------------------------------- /nix/kwasm-pyk/build-systems-overlay.nix: -------------------------------------------------------------------------------- 1 | final: prev: 2 | let 3 | inherit (final) resolveBuildSystem; 4 | inherit (builtins) mapAttrs; 5 | 6 | # Build system dependencies specified in the shape expected by resolveBuildSystem 7 | # The empty lists below are lists of optional dependencies. 8 | # 9 | # A package `foo` with specification written as: 10 | # `setuptools-scm[toml]` in pyproject.toml would be written as 11 | # `foo.setuptools-scm = [ "toml" ]` in Nix 12 | buildSystemOverrides = { 13 | # add dependencies here, e.g.: 14 | # pyperclip.setuptools = [ ]; 15 | py-wasm.setuptools = [ ]; 16 | }; 17 | in 18 | mapAttrs ( 19 | name: spec: 20 | prev.${name}.overrideAttrs (old: { 21 | nativeBuildInputs = old.nativeBuildInputs ++ resolveBuildSystem spec; 22 | }) 23 | ) buildSystemOverrides 24 | -------------------------------------------------------------------------------- /nix/kwasm-pyk/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | callPackage, 4 | nix-gitignore, 5 | 6 | pyproject-nix, 7 | pyproject-build-systems, 8 | uv2nix, 9 | 10 | python 11 | }: 12 | let 13 | pyproject-util = callPackage pyproject-nix.build.util {}; 14 | pyproject-packages = callPackage pyproject-nix.build.packages { 15 | inherit python; 16 | }; 17 | 18 | # load a uv workspace from a workspace root 19 | workspace = uv2nix.lib.workspace.loadWorkspace { 20 | workspaceRoot = (callPackage ../kwasm-source { }) + /pykwasm; 21 | }; 22 | 23 | # create overlay 24 | lockFileOverlay = workspace.mkPyprojectOverlay { 25 | # prefer "wheel" over "sdist" due to maintance overhead 26 | # there is no bundled set of overlays for "sdist" in uv2nix, in contrast to poetry2nix 27 | sourcePreference = "wheel"; 28 | }; 29 | 30 | buildSystemsOverlay = import ./build-systems-overlay.nix; 31 | 32 | # construct package set 33 | pythonSet = pyproject-packages.overrideScope (lib.composeManyExtensions [ 34 | # make build tools available by default as these are not necessarily specified in python lock files 35 | pyproject-build-systems.overlays.default 36 | # include all packages from the python lock file 37 | lockFileOverlay 38 | # add build system overrides to certain python packages 39 | buildSystemsOverlay 40 | ]); 41 | in pyproject-util.mkApplication { 42 | # default dependancy group enables no optional dependencies and no dependency-groups 43 | venv = pythonSet.mkVirtualEnv "pykwasm-env" workspace.deps.default; 44 | package = pythonSet.pykwasm; 45 | } 46 | -------------------------------------------------------------------------------- /nix/kwasm-source/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | nix-gitignore, 4 | stdenvNoCC, 5 | }: 6 | let 7 | kwasm-root-source = lib.cleanSource (nix-gitignore.gitignoreSourcePure [ 8 | ../../.gitignore 9 | ".github/" 10 | "result*" 11 | "*.nix" 12 | "flake.lock" 13 | "/deps/" 14 | # include other directories with their own `.gitingore` individually 15 | "pykwasm/" 16 | # do not include submodule directories that might be initialized empty or non-existent 17 | ] ../../. 18 | ); 19 | kwasm-pyk-source = lib.cleanSource (nix-gitignore.gitignoreSourcePure [ 20 | ../../pykwasm/.gitignore 21 | # do not include submodule directories that might be initialized empty or non-existent 22 | ] ../../pykwasm/. 23 | ); 24 | in stdenvNoCC.mkDerivation { 25 | name = "kwasm-source"; 26 | 27 | dontUnpack = true; 28 | dontConfigure = true; 29 | dontBuild = true; 30 | 31 | installPhase = '' 32 | mkdir -p $out 33 | cp -r ${kwasm-root-source}/. $out/ 34 | cp -r ${kwasm-pyk-source}/. $out/pykwasm/ 35 | ''; 36 | } 37 | -------------------------------------------------------------------------------- /nix/kwasm/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | makeWrapper, 5 | callPackage, 6 | 7 | k, 8 | which, 9 | 10 | kwasm-pyk, 11 | rev ? null 12 | }: 13 | 14 | stdenv.mkDerivation { 15 | pname = "kwasm"; 16 | version = if (rev != null) then rev else "dirty"; 17 | nativeBuildInputs = [ 18 | k 19 | kwasm-pyk 20 | makeWrapper 21 | ]; 22 | 23 | src = callPackage ../kwasm-source { }; 24 | 25 | enableParallelBuilding = true; 26 | 27 | buildPhase = '' 28 | export XDG_CACHE_HOME=$(pwd) 29 | kwasm-kdist -v build -j4 30 | ''; 31 | 32 | installPhase = '' 33 | mkdir -p $out 34 | cp -r ./kdist-*/* $out/ 35 | mkdir -p $out/bin 36 | makeWrapper ${kwasm-pyk}/bin/kwasm $out/bin/kwasm \ 37 | --prefix PATH : ${lib.makeBinPath [ which k ]} \ 38 | --set KDIST_DIR $out 39 | ''; 40 | } 41 | -------------------------------------------------------------------------------- /nix/kwasm/test.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenv, 3 | callPackage, 4 | 5 | which, 6 | git, 7 | 8 | kwasm, 9 | kwasm-pyk, 10 | rev ? null 11 | }: 12 | 13 | stdenv.mkDerivation { 14 | pname = "kwasm-test"; 15 | version = if (rev != null) then rev else "dirty"; 16 | 17 | src = callPackage ../kwasm-source { }; 18 | 19 | nativeBuildInputs = [ 20 | kwasm 21 | which 22 | git 23 | ]; # kwasm-pyk? 24 | 25 | patchPhase = '' 26 | runHook prePatch 27 | # the nix derivation uses the kwasm binary instead of `uv --directory pykwasm run -- kwasm`, which changes directory 28 | # therefore replace '../$<' with '$<' 29 | substituteInPlace Makefile \ 30 | --replace-fail '$(TEST)' '${kwasm}/bin/kwasm' \ 31 | --replace-fail '$(KDIST)' '${kwasm-pyk}/bin/kwasm-kdist' \ 32 | --replace-fail '$(SOURCE_DIR)' '${kwasm}/wasm-semantics/source' 33 | runHook postPatch 34 | ''; 35 | 36 | buildPhase = '' 37 | export XDG_CACHE_HOME=$(pwd) 38 | make \ 39 | NIX=1 \ 40 | -j$NIX_BUILD_CORES \ 41 | test 42 | ''; 43 | 44 | installPhase = '' 45 | touch $out 46 | ''; 47 | } 48 | -------------------------------------------------------------------------------- /package/version: -------------------------------------------------------------------------------- 1 | 0.1.137 2 | -------------------------------------------------------------------------------- /package/version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -xeuo pipefail 4 | 5 | notif() { echo "== $@" >&2 ; } 6 | fatal() { echo "[FATAL] $@" ; exit 1 ; } 7 | 8 | version_file="package/version" 9 | 10 | version_bump() { 11 | local version release_commit version_major version_minor version_patch new_version current_version current_version_major current_version_minor current_version_patch 12 | version="$1" ; shift 13 | version_major="$(echo ${version} | cut --delimiter '.' --field 1)" 14 | version_minor="$(echo ${version} | cut --delimiter '.' --field 2)" 15 | version_patch="$(echo ${version} | cut --delimiter '.' --field 3)" 16 | current_version="$(cat ${version_file})" 17 | current_version_major="$(echo ${current_version} | cut --delimiter '.' --field 1)" 18 | current_version_minor="$(echo ${current_version} | cut --delimiter '.' --field 2)" 19 | current_version_patch="$(echo ${current_version} | cut --delimiter '.' --field 3)" 20 | new_version="${version}" 21 | if [[ "${version_major}" == "${current_version_major}" ]] && [[ "${version_minor}" == "${current_version_minor}" ]]; then 22 | new_version="${version_major}.${version_minor}.$((version_patch + 1))" 23 | fi 24 | echo "${new_version}" > "${version_file}" 25 | notif "Version: ${new_version}" 26 | } 27 | 28 | version_sub() { 29 | local version 30 | version="$(cat $version_file)" 31 | sed --in-place 's/^version = ".*"$/version = "'${version}'"/' pykwasm/pyproject.toml 32 | } 33 | 34 | version_command="$1" ; shift 35 | 36 | case "${version_command}" in 37 | bump) version_bump "$@" ;; 38 | sub) version_sub "$@" ;; 39 | *) fatal "No command: ${version_command}" ;; 40 | esac 41 | -------------------------------------------------------------------------------- /pykwasm/.cruft.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "https://github.com/runtimeverification/python-project-template.git", 3 | "commit": "7a095b4dd0a51916da0a728b8fdd9adf7e469a68", 4 | "checkout": null, 5 | "context": { 6 | "cookiecutter": { 7 | "project_name": "pykwasm", 8 | "project_slug": "pykwasm", 9 | "package_name": "pykwasm", 10 | "version": "0.1.0", 11 | "description": "", 12 | "author_name": "Runtime Verification, Inc.", 13 | "author_email": "contact@runtimeverification.com", 14 | "_template": "https://github.com/runtimeverification/python-project-template.git", 15 | "_commit": "7a095b4dd0a51916da0a728b8fdd9adf7e469a68" 16 | } 17 | }, 18 | "directory": null 19 | } 20 | -------------------------------------------------------------------------------- /pykwasm/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | extend-select = B9, TC1 4 | extend-ignore = B950,E,W1,W2,W3,W4,W5 5 | per-file-ignores = 6 | */__init__.py: F401 7 | # TODO fix these warnings 8 | src/pykwasm/kwasm_ast.py: N802 9 | src/pykwasm/wasm2kast.py: N806 10 | type-checking-strict = true 11 | -------------------------------------------------------------------------------- /pykwasm/.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | __pycache__/ 3 | .coverage 4 | -------------------------------------------------------------------------------- /pykwasm/Makefile: -------------------------------------------------------------------------------- 1 | UV := uv 2 | UV_RUN := $(UV) run -- 3 | 4 | 5 | default: check test-unit 6 | 7 | all: check cov 8 | 9 | .PHONY: clean 10 | clean: 11 | rm -rf dist .coverage cov-* .mypy_cache .pytest_cache 12 | find -type d -name __pycache__ -prune -exec rm -rf {} \; 13 | 14 | .PHONY: build 15 | build: 16 | $(UV) build 17 | 18 | 19 | # Tests 20 | 21 | test: test-all 22 | 23 | .PHONY: test-all 24 | test-all: 25 | $(UV_RUN) pytest src/tests --maxfail=1 --verbose --durations=0 --numprocesses=4 --dist=worksteal $(TEST_ARGS) 26 | 27 | .PHONY: test-unit 28 | test-unit: 29 | $(UV_RUN) pytest src/tests/unit --maxfail=1 --verbose $(TEST_ARGS) 30 | 31 | .PHONY: test-integration 32 | test-integration: 33 | $(UV_RUN) pytest src/tests/integration --maxfail=1 --verbose --durations=0 --numprocesses=4 --dist=worksteal $(TEST_ARGS) 34 | 35 | 36 | # Coverage 37 | 38 | COV_ARGS := 39 | 40 | cov: cov-all 41 | 42 | cov-%: TEST_ARGS += --cov=pykwasm --no-cov-on-fail --cov-branch --cov-report=term 43 | 44 | cov-all: TEST_ARGS += --cov-report=html:cov-all-html $(COV_ARGS) 45 | cov-all: test-all 46 | 47 | cov-unit: TEST_ARGS += --cov-report=html:cov-unit-html $(COV_ARGS) 48 | cov-unit: test-unit 49 | 50 | cov-integration: TEST_ARGS += --cov-report=html:cov-integration-html $(COV_ARGS) 51 | cov-integration: test-integration 52 | 53 | 54 | # Checks and formatting 55 | 56 | format: autoflake isort black 57 | check: check-flake8 check-mypy check-autoflake check-isort check-black 58 | 59 | .PHONY: check-flake8 60 | check-flake8: 61 | $(UV_RUN) flake8 src 62 | 63 | .PHONY: check-mypy 64 | check-mypy: 65 | $(UV_RUN) mypy src 66 | 67 | .PHONY: autoflake 68 | autoflake: 69 | $(UV_RUN) autoflake --quiet --in-place src 70 | 71 | .PHONY: check-autoflake 72 | check-autoflake: 73 | $(UV_RUN) autoflake --quiet --check src 74 | 75 | .PHONY: isort 76 | isort: 77 | $(UV_RUN) isort src 78 | 79 | .PHONY: check-isort 80 | check-isort: 81 | $(UV_RUN) isort --check src 82 | 83 | .PHONY: black 84 | black: 85 | $(UV_RUN) black src 86 | 87 | .PHONY: check-black 88 | check-black: 89 | $(UV_RUN) black --check src 90 | 91 | 92 | # Optional tools 93 | 94 | SRC_FILES := $(shell find src -type f -name '*.py') 95 | 96 | .PHONY: pyupgrade 97 | pyupgrade: 98 | $(UV_RUN) pyupgrade --py310-plus $(SRC_FILES) 99 | -------------------------------------------------------------------------------- /pykwasm/README.md: -------------------------------------------------------------------------------- 1 | # pykwasm 2 | 3 | 4 | ## Installation 5 | 6 | Prerequsites: `python >= 3.10`, [`uv`](https://docs.astral.sh/uv/). 7 | 8 | ```bash 9 | make build 10 | pip install dist/*.whl # install pykwasm globally 11 | ``` 12 | 13 | ## Binary parser: `wasm2kast` 14 | 15 | This command converts a binary Wasm module into the Kast format accepted by KWasm. After installing the package 16 | with `poetry install`, run the command with the file path to a binary Wasm file: 17 | 18 | ```bash 19 | poetry run wasm2kast 20 | ``` 21 | 22 | 23 | ## For Developers 24 | 25 | Use `make` to run common tasks (see the [Makefile](Makefile) for a complete list of available targets). 26 | 27 | * `make build`: Build wheel 28 | * `make check`: Check code style 29 | * `make format`: Format code 30 | * `make test-unit`: Run unit tests 31 | * `make test-integration`: Run integration tests 32 | 33 | -------------------------------------------------------------------------------- /pykwasm/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "pykwasm" 7 | version = "0.1.137" 8 | description = "" 9 | readme = "README.md" 10 | requires-python = "~=3.10" 11 | dependencies = [ 12 | "kframework>=7.1.288", 13 | "py-wasm@git+https://github.com/runtimeverification/py-wasm.git@0.2.1" 14 | ] 15 | 16 | [[project.authors]] 17 | name = "Runtime Verification, Inc." 18 | email = "contact@runtimeverification.com" 19 | 20 | [project.scripts] 21 | wasm2kast = "pykwasm.wasm2kast:main" 22 | kwasm = "pykwasm.scripts.kwasm:main" 23 | kwasm-convert = "pykwasm.scripts.convert:main" 24 | kwasm-preprocess = "pykwasm.scripts.preprocessor:main" 25 | kwasm-kdist = "pyk.kdist.__main__:main" 26 | 27 | [project.entry-points.kdist] 28 | wasm-semantics = "pykwasm.kdist.plugin" 29 | 30 | [dependency-groups] 31 | dev = [ 32 | "autoflake", 33 | "black", 34 | "flake8", 35 | "flake8-bugbear", 36 | "flake8-comprehensions", 37 | "flake8-quotes", 38 | "flake8-type-checking", 39 | "isort", 40 | "mypy", 41 | "pep8-naming", 42 | "pytest", 43 | "pytest-cov", 44 | "pytest-mock", 45 | "pytest-xdist", 46 | "pyupgrade", 47 | ] 48 | 49 | [tool.hatch.metadata] 50 | allow-direct-references = true 51 | 52 | [tool.isort] 53 | profile = "black" 54 | line_length = 120 55 | skip=["wasm"] 56 | 57 | [tool.autoflake] 58 | recursive = true 59 | expand-star-imports = true 60 | remove-all-unused-imports = true 61 | ignore-init-module-imports = true 62 | remove-duplicate-keys = true 63 | remove-unused-variables = true 64 | 65 | [tool.black] 66 | line-length = 120 67 | skip-string-normalization = true 68 | 69 | [tool.mypy] 70 | disallow_untyped_defs = true 71 | # TODO fix type errors 72 | exclude = [ 73 | 'src/pykwasm/wasm2kast\.py', 74 | 'src/wasm/*', 75 | 'src/tests/unit/test_wasm2kast\.py', 76 | ] 77 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/pykwasm/src/pykwasm/__init__.py -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/__main__.py: -------------------------------------------------------------------------------- 1 | def main() -> None: 2 | print('Hello world!') 3 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/kdist/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/pykwasm/src/pykwasm/kdist/__init__.py -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/kdist/plugin.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import shutil 4 | from pathlib import Path 5 | from typing import TYPE_CHECKING 6 | 7 | from pyk.kbuild.utils import k_version 8 | from pyk.kdist.api import Target 9 | from pyk.ktool.kompile import PykBackend, kompile 10 | 11 | if TYPE_CHECKING: 12 | from collections.abc import Callable, Mapping 13 | from typing import Any, Final 14 | 15 | 16 | class SourceTarget(Target): 17 | SRC_DIR: Final = Path(__file__).parent 18 | 19 | def build(self, output_dir: Path, deps: dict[str, Path], args: dict[str, Any], verbose: bool) -> None: 20 | shutil.copytree(self.SRC_DIR / 'wasm-semantics', output_dir / 'wasm-semantics') 21 | 22 | def source(self) -> tuple[Path, ...]: 23 | return (self.SRC_DIR,) 24 | 25 | 26 | class KompileTarget(Target): 27 | _kompile_args: Callable[[Path], Mapping[str, Any]] 28 | 29 | def __init__(self, kompile_args: Callable[[Path], Mapping[str, Any]]): 30 | self._kompile_args = kompile_args 31 | 32 | def build(self, output_dir: Path, deps: dict[str, Path], args: dict[str, Any], verbose: bool) -> None: 33 | kompile_args = self._kompile_args(deps['wasm-semantics.source']) 34 | kompile(output_dir=output_dir, verbose=verbose, **kompile_args) 35 | 36 | def context(self) -> dict[str, str]: 37 | return {'k-version': k_version().text} 38 | 39 | def deps(self) -> tuple[str]: 40 | return ('wasm-semantics.source',) 41 | 42 | 43 | __TARGETS__: Final = { 44 | 'source': SourceTarget(), 45 | 'llvm': KompileTarget( 46 | lambda src_dir: { 47 | 'backend': PykBackend.LLVM, 48 | 'main_file': src_dir / 'wasm-semantics/test.md', 49 | 'main_module': 'WASM-TEST', 50 | 'syntax_module': 'WASM-TEST-SYNTAX', 51 | 'md_selector': 'k', 52 | 'warnings_to_errors': True, 53 | 'gen_glr_bison_parser': True, 54 | 'opt_level': 3, 55 | 'ccopts': ['-g'], 56 | }, 57 | ), 58 | 'kwasm-lemmas': KompileTarget( 59 | lambda src_dir: { 60 | 'backend': PykBackend.HASKELL, 61 | 'main_file': src_dir / 'wasm-semantics/kwasm-lemmas.md', 62 | 'main_module': 'KWASM-LEMMAS', 63 | 'syntax_module': 'WASM-TEXT-SYNTAX', 64 | 'md_selector': 'k', 65 | 'warnings_to_errors': True, 66 | }, 67 | ), 68 | 'wrc20': KompileTarget( 69 | lambda src_dir: { 70 | 'backend': PykBackend.HASKELL, 71 | 'main_file': src_dir / 'wasm-semantics/wrc20.md', 72 | 'main_module': 'WRC20-LEMMAS', 73 | 'syntax_module': 'WASM-TEXT-SYNTAX', 74 | 'md_selector': 'k', 75 | 'warnings_to_errors': True, 76 | }, 77 | ), 78 | } 79 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/kdist/wasm-semantics/auxil.md: -------------------------------------------------------------------------------- 1 | Auxiliary Wasm Commands 2 | ======================= 3 | 4 | Generally useful commands that are not part of the actual Wasm semantics. 5 | 6 | ```k 7 | requires "wasm.md" 8 | 9 | module WASM-AUXIL-SYNTAX 10 | imports WASM-SYNTAX 11 | 12 | syntax Stmt ::= Auxil 13 | // --------------------- 14 | 15 | syntax Auxil ::= "#clearConfig" 16 | // ------------------------------- 17 | endmodule 18 | 19 | module WASM-AUXIL 20 | imports WASM-AUXIL-SYNTAX 21 | imports WASM 22 | 23 | rule [clearConfig]: 24 | #clearConfig => .K ... 25 | _ => .Int 26 | _ => .ValStack 27 | _ => .Map 28 | _ => .Bag 29 | _ => .Map 30 | _ => 0 31 | _ => .Map 32 | 33 | _ => 0 34 | _ => .Bag 35 | _ => 0 36 | _ => .Bag 37 | _ => 0 38 | _ => .Bag 39 | _ => 0 40 | _ => .Bag 41 | _ => 0 42 | _ => .Bag 43 | 44 | 45 | endmodule 46 | ``` 47 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/kdist/wasm-semantics/wasm-data/int-type.k: -------------------------------------------------------------------------------- 1 | 2 | module INT-TYPE 3 | imports INT 4 | 5 | syntax WrappedInt 6 | syntax Int 7 | 8 | syntax WrappedInt ::= wrap(Int) [symbol(wrapInt)] 9 | syntax Int ::= unwrap(WrappedInt) [function, total, injective, symbol(unwrapInt)] 10 | rule unwrap(wrap(A:Int)) => A 11 | endmodule 12 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/kdist/wasm-semantics/wasm-data/list-int.k: -------------------------------------------------------------------------------- 1 | requires "int-type.k" 2 | 3 | module LIST-INT 4 | imports private INT-SYNTAX 5 | imports private BASIC-K 6 | imports INT-TYPE 7 | 8 | syntax Int 9 | 10 | syntax ListInt [hook(LIST.List)] 11 | syntax ListInt ::= ListInt ListInt 12 | [ left, function, total, hook(LIST.concat), 13 | symbol(_ListInt_), smtlib(smt_seq_concat), 14 | assoc, unit(.ListInt), element(ListIntItem), 15 | format(%1%n%2), update(ListInt:set) 16 | ] 17 | syntax ListInt ::= ".ListInt" 18 | [ function, total, hook(LIST.unit), symbol(.ListInt), 19 | smtlib(smt_seq_nil) 20 | ] 21 | syntax ListInt ::= ListItem(WrappedInt) 22 | [ function, total, hook(LIST.element), symbol(ListIntItem), 23 | smtlib(smt_seq_elem) 24 | ] 25 | syntax WrappedInt ::= ListInt "[" Int "]" 26 | [ function, hook(LIST.get), symbol(ListInt:get) ] 27 | syntax ListInt ::= ListInt "[" index: Int "<-" value: WrappedInt "]" 28 | [function, hook(LIST.update), symbol(ListInt:set)] 29 | syntax ListInt ::= makeListInt(length: Int, value: WrappedInt) 30 | [function, hook(LIST.make)] 31 | syntax ListInt ::= updateList(dest: ListInt, index: Int, src: ListInt) 32 | [function, hook(LIST.updateAll)] 33 | syntax ListInt ::= fillList(ListInt, index: Int, length: Int, value: WrappedInt) 34 | [function, hook(LIST.fill)] 35 | syntax ListInt ::= range(ListInt, fromFront: Int, fromBack: Int) 36 | [function, hook(LIST.range), symbol(ListInt:range)] 37 | syntax Bool ::= WrappedInt "in" ListInt 38 | [function, total, hook(LIST.in), symbol(_inListInt_)] 39 | syntax Int ::= size(ListInt) 40 | [function, total, hook(LIST.size), symbol(sizeListInt), smtlib(smt_seq_len)] 41 | endmodule 42 | 43 | module LIST-INT-PRIMITIVE 44 | imports BOOL 45 | imports INT 46 | imports LIST-INT 47 | 48 | syntax WrappedInt ::= ListInt "[" Int "]" "orDefault" WrappedInt 49 | [ function, total, symbol(ListInt:getOrDefault) ] 50 | 51 | syntax Int ::= ListInt "{{" Int "}}" 52 | [function, symbol(ListInt:primitiveLookup)] 53 | // ----------------------------------------------------------- 54 | rule L:ListInt {{ I:Int }} => unwrap( L[ I ] ) 55 | 56 | syntax Int ::= ListInt "{{" Int "}}" "orDefault" Int 57 | [ function, total, symbol(ListInt:primitiveLookupOrDefault) ] 58 | // ----------------------------------------------------------------------------- 59 | rule L:ListInt {{ I:Int }} orDefault Value:Int 60 | => unwrap( L [I] orDefault wrap(Value) ) 61 | 62 | rule ListItem(V:WrappedInt) _:ListInt [0] orDefault _:WrappedInt 63 | => V 64 | rule _:ListInt ListItem(V:WrappedInt) [-1] orDefault _:WrappedInt 65 | => V 66 | rule .ListInt [_:Int] orDefault D:WrappedInt => D 67 | 68 | rule ListItem(_:WrappedInt) L:ListInt [I:Int] orDefault D:WrappedInt 69 | => L[I -Int 1] orDefault D 70 | requires 0 L[I +Int 1] orDefault D 73 | requires I D 76 | requires notBool (0 -Int size(L) <=Int I andBool I ListItem(wrap(B)) 82 | 83 | 84 | syntax ListInt ::= ListInt "{{" Int "<-" Int "}}" 85 | [function, symbol(ListInt:primitiveSet)] 86 | // ----------------------------------------------------------- 87 | rule L:ListInt {{ I:Int <- V:Int }} 88 | => L[ I <- wrap(V)] 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/kdist/wasm-semantics/wasm-data/list-ref.k: -------------------------------------------------------------------------------- 1 | 2 | 3 | module LIST-REF 4 | imports WASM-DATA-INTERNAL-SYNTAX 5 | imports private INT-SYNTAX 6 | imports private BASIC-K 7 | 8 | syntax Int 9 | 10 | syntax ListRef [hook(LIST.List)] 11 | syntax ListRef ::= ListRef ListRef 12 | [ left, function, total, hook(LIST.concat), 13 | symbol(_ListRef_), smtlib(smt_seq_concat), 14 | assoc, unit(.ListRef), element(ListRefItem), 15 | format(%1%n%2), update(ListRef:set) 16 | ] 17 | syntax ListRef ::= ".ListRef" 18 | [ function, total, hook(LIST.unit), symbol(.ListRef), 19 | smtlib(smt_seq_nil) 20 | ] 21 | syntax ListRef ::= ListItem(RefVal) 22 | [ function, total, hook(LIST.element), symbol(ListRefItem), 23 | smtlib(smt_seq_elem) 24 | ] 25 | syntax RefVal ::= ListRef "[" Int "]" 26 | [ function, hook(LIST.get), symbol(ListRef:get) ] 27 | syntax ListRef ::= ListRef "[" index: Int "<-" value: RefVal "]" 28 | [function, hook(LIST.update), symbol(ListRef:set)] 29 | syntax ListRef ::= makeListRef(length: Int, value: RefVal) 30 | [function, hook(LIST.make)] 31 | syntax ListRef ::= updateList(dest: ListRef, index: Int, src: ListRef) 32 | [function, hook(LIST.updateAll)] 33 | syntax ListRef ::= fillList(ListRef, index: Int, length: Int, value: RefVal) 34 | [function, hook(LIST.fill)] 35 | syntax ListRef ::= range(ListRef, fromFront: Int, fromBack: Int) 36 | [function, hook(LIST.range), symbol(ListRef:range)] 37 | syntax Bool ::= RefVal "in" ListRef 38 | [function, total, hook(LIST.in), symbol(_inListRef_)] 39 | syntax Int ::= size(ListRef) 40 | [function, total, hook(LIST.size), symbol(sizeListRef), smtlib(smt_seq_len)] 41 | endmodule 42 | 43 | module LIST-REF-EXTENSIONS 44 | imports LIST-REF 45 | imports BOOL 46 | imports INT 47 | 48 | syntax RefVal ::= ListRef "[" Int "]" "orDefault" RefVal 49 | [ function, total, symbol(ListRef:getOrDefault) ] 50 | // ---------------------------------------------------------------- 51 | rule ListItem(V:RefVal) _:ListRef [0] orDefault _:RefVal 52 | => V 53 | rule _:ListRef ListItem(V:RefVal) [-1] orDefault _:RefVal 54 | => V 55 | rule .ListRef [_:Int] orDefault D:RefVal => D 56 | 57 | rule ListItem(_:RefVal) L:ListRef [I:Int] orDefault D:RefVal 58 | => L[I -Int 1] orDefault D 59 | requires 0 L[I +Int 1] orDefault D 62 | requires I D 65 | requires notBool (0 -Int size(L) <=Int I andBool I L [N] orDefault ( null) 72 | 73 | syntax ListRef ::= makeListRefTotal(Int, RefVal) 74 | [function, total, symbol(ListRef:makeTotal)] 75 | // ---------------------------------------------------- 76 | rule makeListRefTotal(N, V) => makeListRef(N, V) 77 | requires N >=Int 0 78 | rule makeListRefTotal(N, _) => .ListRef 79 | requires N dropListRef(N -Int 1, L) 85 | requires N >Int 0 86 | rule dropListRef(_, L) => L 87 | [owise] 88 | 89 | endmodule 90 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/kdist/wasm-semantics/wasm-data/sparse-bytes.k: -------------------------------------------------------------------------------- 1 | module SPARSE-BYTES-SYNTAX 2 | imports BYTES 3 | imports INT 4 | 5 | syntax SBItem ::= #empty(Int) [symbol(SBItem:empty)] 6 | | #bytes(Bytes) [symbol(SBItem:bytes)] 7 | 8 | 9 | syntax SBItemChunk ::= SBChunk(SBItem) 10 | 11 | syntax SparseBytes ::= List{SBItemChunk, ""} 12 | 13 | syntax Bytes ::= unwrap(SparseBytes) 14 | [function, total, symbol(SparseBytes:unwrap)] 15 | 16 | syntax Bytes ::= unwrap(SBItem) 17 | [function, total, symbol(SBItem:unwrap)] 18 | 19 | syntax Int ::= size(SparseBytes) 20 | [function, total, symbol(SparseBytes:size)] 21 | 22 | syntax Int ::= size(SBItem) 23 | [function, total, symbol(SBItem:size)] 24 | 25 | syntax Bytes ::= zeros(Int) [function, total, symbol(zeros)] 26 | endmodule 27 | 28 | module SPARSE-BYTES 29 | imports BOOL 30 | imports SPARSE-BYTES-SYNTAX 31 | imports REPLACE-AT-COMMON 32 | imports REPLACE-AT-CONCRETE 33 | imports REPLACE-AT-SYMBOLIC 34 | 35 | // syntax Bytes ::= unwrap(SparseBytes) 36 | // [function, total, symbol(SparseBytes:unwrap)] 37 | // ----------------------------------------------------------------- 38 | rule unwrap(SBChunk(SBI) REST) => unwrap(SBI) +Bytes unwrap(REST) 39 | rule unwrap(.SparseBytes) => .Bytes 40 | 41 | syntax SparseBytes ::= fromBytes(Bytes) 42 | [function, total, symbol(SparseBytes:fromBytes)] 43 | // --------------------------------------------------------- 44 | rule fromBytes(Bs) => SBChunk(#bytes(Bs)) 45 | 46 | // syntax Bytes ::= unwrap(SBItem) 47 | // [function, total, symbol(SBItem:unwrap)] 48 | // ----------------------------------------------- 49 | rule unwrap(#bytes(Bs)) => Bs 50 | rule unwrap(#empty(N)) => zeros(N) 51 | 52 | // syntax Bytes ::= zeros(Int) [function, total, symbol(zeros)] 53 | // ------------------------------------------------------------------- 54 | rule zeros(N) => padLeftBytes(.Bytes, size(#empty(N)), 0) 55 | 56 | // syntax Int ::= size(SparseBytes) 57 | // [function, total, symbol(SparseBytes:size)] 58 | // --------------------------------------------------- 59 | rule size(SBChunk(SBI) SBS) => size(SBI) +Int size(SBS) 60 | rule size(.SparseBytes) => 0 61 | 62 | // syntax Int ::= size(SBItem) 63 | // [function, total, symbol(SBItem:size)] 64 | // ----------------------------------------------- 65 | rule size(#bytes(Bs)) => lengthBytes(Bs) 66 | rule size(#empty(N)) => maxInt(N,0) 67 | 68 | 69 | syntax SparseBytes ::= substrSparseBytes(SparseBytes, from: Int, to: Int) 70 | [function, total, symbol(SparseBytes:substr)] 71 | // ------------------------------------------------------------------------ 72 | rule substrSparseBytes(_, S, E) => .SparseBytes 73 | requires notBool( 0 <=Int S andBool S <=Int E ) 74 | 75 | rule substrSparseBytes(.SparseBytes, S, E) => .SparseBytes 76 | requires 0 <=Int S andBool S <=Int E 77 | 78 | rule substrSparseBytes(SBChunk(SBI) REST, S, E) => substrSparseBytes(REST, S -Int size(SBI), E -Int size(SBI)) 79 | requires 0 <=Int S andBool S <=Int E 80 | andBool size(SBI) <=Int S 81 | 82 | rule substrSparseBytes(SBChunk(SBI) REST, S, E) 83 | => #let SUBSTR = substrSBItem(SBI, S, E) 84 | #in SUBSTR substrSparseBytes(REST, 0, E -Int size(SBI)) 85 | requires 0 <=Int S andBool S <=Int E 86 | andBool size(SBI) >Int S 87 | 88 | syntax SparseBytes ::= substrSBItem(SBItem, from: Int, to: Int) 89 | [function, total, symbol(SBItem:substr)] 90 | // ------------------------------------------------------------- 91 | rule substrSBItem(_SBI, S, E) => .SparseBytes 92 | requires S .SparseBytes 95 | requires 0 <=Int S andBool S <=Int E 96 | andBool N <=Int S 97 | 98 | rule substrSBItem(#empty(N), S, E) => SBChunk( #empty( minInt(E, N) -Int S) ) 99 | requires 0 <=Int S andBool S <=Int E 100 | andBool S .SparseBytes 103 | requires 0 <=Int S andBool S <=Int E 104 | andBool lengthBytes(Bs) <=Int S 105 | 106 | rule substrSBItem(#bytes(Bs), S, E) 107 | => SBChunk(#bytes( substrBytes(Bs, S, minInt(E, lengthBytes(Bs))) )) 108 | requires 0 <=Int S andBool S <=Int E 109 | andBool S .SparseBytes 122 | requires S SBChunk(#bytes(Bs)) 126 | requires 0 ==Int S 127 | 128 | // append padded 129 | rule replaceAt(.SparseBytes, S, Bs) => SBChunk(#empty(S)) SBChunk(#bytes(Bs)) 130 | requires 0 SBChunk(SBI) replaceAt(REST, S -Int size(SBI), Bs) 135 | requires size(SBI) <=Int S 136 | 137 | syntax SparseBytes ::= replaceAtZ(Int, SparseBytes, Int, Bytes) 138 | [function, total, symbol(SparseBytes:replaceAtZ)] 139 | // --------------------------------------------------------------- 140 | ////////////// S < 0 141 | rule replaceAtZ(_, _, S, _) => .SparseBytes 142 | requires S 0 145 | // split zeros: 0 < S < N 146 | rule replaceAtZ(N, REST, S, Bs) 147 | => SBChunk(#empty(S)) replaceAtZ(N -Int S, REST, 0, Bs) 148 | requires 0 SBChunk(#empty(N)) replaceAt(REST, S -Int N, Bs) 154 | requires 0 SBChunk(#bytes(Bs)) SBChunk(#empty(N -Int lengthBytes(Bs))) REST 162 | requires 0 ==Int S 163 | andBool lengthBytes(Bs) SBChunk(#bytes(Bs)) REST 168 | requires 0 ==Int S 169 | andBool lengthBytes(Bs) ==Int N 170 | 171 | ///////// len(Bs) > N 172 | rule replaceAtZ(N, REST, S, Bs) 173 | => replaceAt(SBChunk(#bytes(zeros(N))) REST, S, Bs) 174 | requires 0 ==Int S 175 | andBool lengthBytes(Bs) >Int N 176 | 177 | 178 | syntax SparseBytes ::= replaceAtB(Bytes, SparseBytes, Int, Bytes) 179 | [function, total, symbol(SparseBytes:replaceAtB)] 180 | // --------------------------------------------------------------- 181 | ////////// S + len(Bs) <= len(MB) 182 | rule replaceAtB(MB, REST, S, Bs) 183 | => SBChunk(#bytes( replaceAtBytes(MB, S, Bs) )) REST 184 | requires 0 <=Int S 185 | andBool S +Int lengthBytes(Bs) <=Int lengthBytes(MB) 186 | 187 | ////////// S + len(Bs) > len(MB) 188 | rule replaceAtB(MB, REST, S, Bs) 189 | => replaceAt( 190 | joinUntil(MB, REST, S +Int lengthBytes(Bs)), 191 | S, 192 | Bs 193 | ) 194 | requires 0 <=Int S 195 | andBool lengthBytes(MB) SBChunk(#bytes(Bs)) REST 204 | requires I <=Int lengthBytes(Bs) 205 | 206 | rule joinUntil(Bs, SBChunk(SBI) REST, I) 207 | => joinUntil(Bs +Bytes unwrap(SBI), REST, I) 208 | requires I >Int lengthBytes(Bs) 209 | 210 | rule joinUntil(Bs, .SparseBytes, I) 211 | => SBChunk(#bytes( padRightBytes(Bs, I, 0) )) 212 | requires I >Int lengthBytes(Bs) 213 | endmodule 214 | 215 | module REPLACE-AT-CONCRETE [concrete] 216 | imports REPLACE-AT-COMMON 217 | 218 | rule replaceAt(SBChunk(#empty(N)) REST, S, Bs) => replaceAtZ(N, REST, S, Bs) 219 | requires S replaceAtB(B, REST, S, Bs) 221 | requires S replaceAtZ(N, REST, S, Bs) 229 | requires S replaceAtB(B, REST, S, Bs) 232 | requires S L{{I <- V}} 12 | requires 0 <=Int I andBool I setExtend(L ListItem(wrap(D)), I, V, D) 15 | requires size(L) <=Int I 16 | 17 | rule #Ceil(setExtend(_L:ListInt, I:Int, _V:Int, _D:Int)) => {true #Equals 0 <=Int I} 18 | [simplification] 19 | 20 | syntax Bool ::= isListIndex(Int, ListInt) [function, total] 21 | 22 | rule isListIndex(I:Int, L:ListInt) => 0 <=Int I andBool I str: 12 | print(h) 13 | if 'nan' in h: 14 | return h.replace('nan', 'NaN') 15 | elif 'inf' in h: 16 | return h.replace('inf', 'Infinity') 17 | elif '0x' not in h: 18 | return h 19 | else: 20 | return h.split()[0] + ' ' + '%e' % (float.fromhex(h.split()[1])) 21 | 22 | 23 | def main() -> None: 24 | filename = sys.argv[1] 25 | infile = 'tests/wasm-tests/test/core/%s' % filename 26 | outfile = open('tests/simple/%s-c.%s' % tuple(filename.split('.')), 'w') 27 | unsupported = [ 28 | 'nan:', 29 | '-nan', 30 | 'reinterpret', 31 | 'assert_return_canonical_nan', 32 | 'assert_return_arithmetic_nan', 33 | 'assert_invalid', 34 | 'assert_malformed', 35 | ] 36 | for line in open(infile).readlines(): 37 | if any(x in line for x in unsupported): 38 | outfile.write(';; ' + line) 39 | else: 40 | outfile.write(re.sub(r'(?:(?:f32|f64)\.const )([^\)]+)', lambda m: hex2float(m.group()), line)) 41 | outfile.write('\n#clearConfig\n') 42 | 43 | 44 | if __name__ == '__main__': 45 | main() 46 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/scripts/kwasm.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | from argparse import ArgumentParser 5 | from contextlib import contextmanager 6 | from enum import Enum 7 | from pathlib import Path 8 | from tempfile import NamedTemporaryFile 9 | from typing import TYPE_CHECKING 10 | 11 | from pyk.cli.utils import dir_path, file_path 12 | from pyk.kdist import kdist 13 | from pyk.ktool.kprint import KAstInput, KAstOutput, _kast 14 | from pyk.ktool.kprove import _kprove 15 | from pyk.ktool.krun import _krun 16 | from pyk.utils import run_process 17 | 18 | from .preprocessor import preprocess 19 | 20 | if TYPE_CHECKING: 21 | from collections.abc import Container, Iterable, Iterator 22 | from subprocess import CompletedProcess 23 | 24 | 25 | class ProofDefinition(Enum): 26 | KWASM_LEMMAS = 'kwasm-lemmas' 27 | WRC20 = 'wrc20' 28 | 29 | 30 | def main() -> None: 31 | parser = _argument_parser() 32 | args, rest = parser.parse_known_args() 33 | 34 | if args.command == 'run': 35 | _exec_run(program=args.program) 36 | elif args.command == 'kast': 37 | _exec_kast(program=args.program, output=args.output) 38 | elif args.command == 'prove': 39 | _exec_prove(spec_file=args.spec, proof_defn=args.defn, include_dirs=args.include_dirs, args=rest) 40 | 41 | raise AssertionError() 42 | 43 | 44 | def _exec_run(program: Path) -> None: 45 | definition_dir = kdist.get('wasm-semantics.llvm') 46 | 47 | with _preprocessed(program) as input_file: 48 | proc_res = _krun(definition_dir=definition_dir, input_file=input_file, check=False) 49 | 50 | _exit_with_output(proc_res) 51 | 52 | 53 | def _exec_kast(program: Path, output: KAstOutput | None) -> None: 54 | definition_dir = kdist.get('wasm-semantics.llvm') 55 | pgm_parser = definition_dir / 'parser_PGM' 56 | 57 | with _preprocessed(program) as preprocessed_file: 58 | input = KAstInput.PROGRAM 59 | input_file = preprocessed_file 60 | 61 | if pgm_parser.exists(): 62 | f = NamedTemporaryFile() 63 | proc_res = run_process([str(pgm_parser), str(input_file)], check=False) 64 | if proc_res.returncode != 0: 65 | _exit_with_output(proc_res) 66 | tmp_file = Path(f.name) 67 | tmp_file.write_text(proc_res.stdout) 68 | 69 | input = KAstInput.KORE 70 | input_file = tmp_file 71 | 72 | if (not pgm_parser.exists()) or output != KAstOutput.KORE: 73 | proc_res = _kast(input_file, definition_dir=definition_dir, input=input, output=output, check=False) 74 | 75 | _exit_with_output(proc_res) 76 | 77 | 78 | def _exec_prove( 79 | spec_file: Path, 80 | proof_defn: ProofDefinition, 81 | include_dirs: Iterable[Path] | None, 82 | args: Iterable[str], 83 | ) -> None: 84 | definition_dir = kdist.get(f'wasm-semantics.{proof_defn.value}') 85 | proc_res = _kprove( 86 | spec_file, 87 | kompiled_dir=definition_dir, 88 | include_dirs=include_dirs or (), 89 | args=args, 90 | check=False, 91 | ) 92 | _exit_with_output(proc_res, normal_status=(0, 1)) 93 | 94 | 95 | @contextmanager 96 | def _preprocessed(program: Path) -> Iterator[Path]: 97 | program_text = program.read_text() 98 | with NamedTemporaryFile() as f: 99 | tmp_file = Path(f.name) 100 | tmp_file.write_text(preprocess(program_text)) 101 | yield tmp_file 102 | 103 | 104 | def _exit_with_output(cp: CompletedProcess, *, normal_status: Container[int] | None = None) -> None: 105 | status = cp.returncode 106 | normal_status = normal_status or (0,) 107 | err = status not in normal_status 108 | out = cp.stderr if err else cp.stdout 109 | file = sys.stderr if err else sys.stdout 110 | print(out, end='', file=file, flush=True) 111 | sys.exit(status) 112 | 113 | 114 | def _argument_parser() -> ArgumentParser: 115 | parser = ArgumentParser(prog='kwasm') 116 | command_parser = parser.add_subparsers(dest='command', required=True) 117 | 118 | run_parser = command_parser.add_parser('run', help='run a WebAssembly program') 119 | run_parser.add_argument('program', metavar='PROGRAM', type=file_path, help='path to WebAssembly program') 120 | 121 | kast_parser = command_parser.add_parser( 122 | 'kast', help='parse a WebAssembly program and output it in a supported format' 123 | ) 124 | kast_parser.add_argument('program', metavar='PROGRAM', type=file_path, help='path to WebAssembly program') 125 | kast_parser.add_argument('--output', metavar='FORMAT', type=KAstOutput, help='format to output the term in') 126 | 127 | prove_parser = command_parser.add_parser('prove', help='run a WebAssembly K proof') 128 | prove_parser.add_argument('spec', metavar='SPEC', type=file_path, help='K specification to be proved') 129 | prove_parser.add_argument('defn', metavar='DEFN', type=ProofDefinition, help='proof definition') 130 | prove_parser.add_argument( 131 | '-I', dest='include_dirs', metavar='INCLUDE', action='append', type=dir_path, help='include path' 132 | ) 133 | 134 | return parser 135 | 136 | 137 | if __name__ == '__main__': 138 | main() 139 | -------------------------------------------------------------------------------- /pykwasm/src/pykwasm/scripts/preprocessor.py: -------------------------------------------------------------------------------- 1 | # Preprocessor that converts Wasm concrete syntax into a form parseable by K. 2 | # example usage: kwasm-preprocess f32.wast 3 | 4 | import re 5 | import sys 6 | 7 | 8 | def preprocess(s: str) -> str: 9 | def replace(m: re.Match) -> str: 10 | return hex2float(m.group()) 11 | 12 | lines = [] 13 | for line in s.split('\n'): # splitlines also splits on other characters, e.g \u2028 14 | lines.append(re.sub(r'(?:(?:f32|f64)\.const )([^\)]+)', replace, line + '\n')) 15 | 16 | return ''.join(lines) 17 | 18 | 19 | def hex2float(h: str) -> str: 20 | h = re.sub('_', '', h) 21 | if 'nan' in h: 22 | # TODO: Keep bit pattern of float, don't turn all of them into simple NaNs. 23 | return re.sub('-?nan(:.*$)?', 'NaN', h) 24 | elif 'inf' in h: 25 | return h.replace('inf', 'Infinity') 26 | elif '0x' in h: 27 | try: 28 | return h.split()[0] + ' ' + '%e' % (float.fromhex(h.split()[1])) 29 | except OverflowError: 30 | return h 31 | except ValueError: 32 | return h 33 | else: 34 | return h 35 | 36 | 37 | def main() -> None: 38 | if len(list(sys.argv)) == 1: 39 | infile = sys.stdin 40 | else: 41 | infile = open(sys.argv[1]) 42 | print(preprocess(infile.read())) 43 | infile.close() 44 | 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /pykwasm/src/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/pykwasm/src/tests/__init__.py -------------------------------------------------------------------------------- /pykwasm/src/tests/conftest.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | import pytest 6 | from pyk.cli.utils import dir_path 7 | from pyk.kdist import kdist 8 | from pyk.ktool.krun import KRun 9 | 10 | if TYPE_CHECKING: 11 | from pathlib import Path 12 | 13 | from pytest import Config, Parser 14 | 15 | 16 | def pytest_addoption(parser: Parser) -> None: 17 | parser.addoption( 18 | '--llvm-dir', 19 | dest='llvm_dir', 20 | type=dir_path, 21 | help='Existing LLVM kompiled directory.', 22 | ) 23 | 24 | 25 | @pytest.fixture(scope='session') 26 | def llvm_dir(pytestconfig: Config) -> Path | None: 27 | return pytestconfig.getoption('llvm_dir') 28 | 29 | 30 | @pytest.fixture(scope='session') 31 | def krun_llvm(llvm_dir: Path | None) -> KRun: 32 | if llvm_dir is not None: 33 | return KRun(llvm_dir) 34 | 35 | llvm_dir = kdist.which('wasm-semantics.llvm') 36 | if not llvm_dir.is_dir(): 37 | raise ValueError('LLVM definition not found. Run make from the repository root, or pass --llvm-dir') 38 | 39 | return KRun(llvm_dir) 40 | -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/pykwasm/src/tests/integration/__init__.py -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/datas.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 1) 3 | (data (i32.const 0) "WASM") 4 | (data (i32.const 3) "foo\AA\01") 5 | ) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/elems.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (table 10 funcref) 3 | (elem (i32.const 0) 0 0 $foo) 4 | (elem (i32.const 3) 1 1 $foo) 5 | (func) 6 | (func) 7 | (func $foo)) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/exports.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "foo")) 3 | (func (export "fom")) 4 | (memory (export "baz") 1 1) 5 | (global (export "faz") (mut f64) (f64.const 0)) 6 | (table (export "bar") 1 3 funcref)) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/funcs.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (func (param i32 i64) (local f64)) 3 | ) 4 | -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/globals.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (global i64 (i64.const 0)) 3 | (global (mut i32) (i32.const 1))) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/imports.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (func (param i32) (result i64))) 3 | (import "env" "foo" (func)) 4 | (import "env" "baz" (global (mut f64))) 5 | (import "env" "faz" (memory 1 3)) 6 | (import "env" "bar" (table 1 3 funcref))) 7 | -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/instrs.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 0) 3 | (table 100 funcref) 4 | (elem func $f) 5 | (global (mut i32) (i32.const 0)) 6 | (func (param i32 i64) (local f64)) 7 | (func $f) 8 | (global funcref (ref.func $f)) 9 | (func (local i32) 10 | ;; `unreachable` and `drop` are inserted as needed to 11 | ;; ensure correct typing. 12 | unreachable 13 | 14 | ;; Numeric Instrs 15 | ;; -------------- 16 | ;; Commented out instructions are not currently supported by py-wasm. 17 | i32.const 0 drop 18 | f32.const 0 drop 19 | i32.extend8_s drop 20 | i32.extend16_s drop 21 | i64.extend8_s drop 22 | i64.extend16_s drop 23 | i64.extend32_s drop 24 | i32.wrap_i64 drop 25 | i64.extend_i32_s drop 26 | i64.extend_i32_u drop 27 | i32.trunc_f64_s drop 28 | i64.trunc_f32_u drop 29 | ;; i32.trunc_sat_f64_s drop 30 | ;; i32.trunc_sat_f64_u drop 31 | f32.demote_f64 drop 32 | f64.promote_f32 drop 33 | f64.convert_i32_s drop 34 | f64.convert_i32_u drop 35 | ;; i32.reinterpret_f32 drop 36 | ;; f64.reinterpret_i64 drop 37 | ;; -- 38 | unreachable 39 | 40 | ;; IUnOp 41 | ;; ----- 42 | i32.clz 43 | i32.ctz 44 | i32.popcnt 45 | ;; -- 46 | unreachable 47 | 48 | ;; IBinOp 49 | ;; ------ 50 | i64.add 51 | i64.sub 52 | i64.mul 53 | i64.div_s 54 | i64.div_u 55 | i64.rem_s 56 | i64.rem_u 57 | i64.and 58 | i64.or 59 | i64.xor 60 | i64.shl 61 | i64.shr_s 62 | i64.shr_u 63 | i64.rotl 64 | i64.rotr 65 | ;; -- 66 | unreachable 67 | 68 | ;; FUnOp 69 | ;; ----- 70 | f32.abs 71 | f32.neg 72 | f32.sqrt 73 | f32.ceil 74 | f32.floor 75 | f32.trunc 76 | f32.nearest 77 | ;; -- 78 | unreachable 79 | 80 | ;; FBinOp 81 | ;; ------ 82 | f64.add 83 | f64.sub 84 | f64.mul 85 | f64.div 86 | f64.min 87 | f64.max 88 | f64.copysign 89 | ;; -- 90 | unreachable 91 | 92 | ;; ITestop 93 | ;; ------- 94 | i32.eqz 95 | ;; -- 96 | unreachable 97 | 98 | ;; IRelOp 99 | ;; ------ 100 | i32.eq 101 | i32.ne 102 | i32.lt_s 103 | i32.lt_u 104 | i32.gt_s 105 | i32.gt_u 106 | i32.le_s 107 | i32.le_u 108 | i32.ge_s 109 | i32.ge_u 110 | ;; -- 111 | unreachable 112 | 113 | ;; FRelOp 114 | ;; ------ 115 | f64.eq drop 116 | f64.ne drop 117 | f64.lt drop 118 | f64.gt drop 119 | f64.le drop 120 | f64.ge drop 121 | ;; -- 122 | unreachable 123 | 124 | ;; Stack Instrs 125 | ;; ------------ 126 | drop 127 | select 128 | ;; -- 129 | unreachable 130 | 131 | ;; Variable Instrs 132 | ;; --------------- 133 | local.get 0 134 | local.set 0 135 | local.tee 0 136 | global.get 0 137 | global.set 0 138 | ;; -- 139 | unreachable 140 | 141 | ;; Memory Instrs 142 | ;; ------------- 143 | i32.load offset=10 drop 144 | f32.load offset=10 drop 145 | i32.store offset=10 drop 146 | f32.store offset=10 drop 147 | i32.load8_s offset=10 drop 148 | i32.load8_u offset=10 drop 149 | i32.load16_s offset=1 drop 150 | i32.load16_u offset=1 drop 151 | i64.load32_s offset=1 drop 152 | i64.load32_u offset=1 drop 153 | i32.store8 offset=10 drop 154 | i32.store16 offset=10 drop 155 | i64.store32 offset=10 drop 156 | memory.size 157 | memory.grow 158 | ;; -- 159 | unreachable 160 | 161 | ;; Control Instrs 162 | ;; -------------- 163 | nop 164 | unreachable 165 | block (result i32) unreachable end 166 | block (result i32) unreachable nop end 167 | block end 168 | if (result f32) unreachable else unreachable end 169 | loop unreachable end 170 | br 0 171 | br_if 0 172 | br_table 0 0 0 173 | return 174 | call 0 175 | call_indirect (type 0) 176 | ;; -- 177 | 178 | ;; Reference Instrs 179 | ref.is_null drop 180 | ref.null extern drop 181 | ref.null func drop 182 | ref.func $f drop 183 | ;; -- 184 | 185 | ;; Table Instrs 186 | table.get 0 drop 187 | table.set 0 drop 188 | table.init 0 0 drop 189 | elem.drop 0 drop 190 | table.copy 0 0 drop 191 | table.grow 0 drop 192 | table.size 0 drop 193 | table.fill 0 drop 194 | ;; -- 195 | 196 | unreachable 197 | ) 198 | 199 | ) 200 | -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/memories.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 1)) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/spec_elem_0.wat: -------------------------------------------------------------------------------- 1 | ;; Syntax 2 | (module 3 | (table $t 10 funcref) 4 | (func $f) 5 | (func $g) 6 | 7 | ;; Passive 8 | (elem funcref) 9 | (elem funcref (ref.func $f) (item ref.func $f) (item (ref.null func)) (ref.func $g)) 10 | (elem func) 11 | (elem func $f $f $g $g) 12 | 13 | (elem $p1 funcref) 14 | (elem $p2 funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) 15 | (elem $p3 func) 16 | (elem $p4 func $f $f $g $g) 17 | 18 | ;; Active 19 | (elem (table $t) (i32.const 0) funcref) 20 | (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) 21 | (elem (table $t) (i32.const 0) func) 22 | (elem (table $t) (i32.const 0) func $f $g) 23 | (elem (table $t) (offset (i32.const 0)) funcref) 24 | (elem (table $t) (offset (i32.const 0)) func $f $g) 25 | (elem (table 0) (i32.const 0) func) 26 | (elem (table 0x0) (i32.const 0) func $f $f) 27 | (elem (table 0x000) (offset (i32.const 0)) func) 28 | (elem (table 0) (offset (i32.const 0)) func $f $f) 29 | (elem (table $t) (i32.const 0) func) 30 | (elem (table $t) (i32.const 0) func $f $f) 31 | (elem (table $t) (offset (i32.const 0)) func) 32 | (elem (table $t) (offset (i32.const 0)) func $f $f) 33 | (elem (offset (i32.const 0))) 34 | (elem (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) 35 | (elem (offset (i32.const 0)) func $f $f) 36 | (elem (offset (i32.const 0)) $f $f) 37 | (elem (i32.const 0)) 38 | (elem (i32.const 0) funcref (ref.func $f) (ref.null func)) 39 | (elem (i32.const 0) func $f $f) 40 | (elem (i32.const 0) $f $f) 41 | 42 | (elem $a1 (table $t) (i32.const 0) funcref) 43 | (elem $a2 (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) 44 | (elem $a3 (table $t) (i32.const 0) func) 45 | (elem $a4 (table $t) (i32.const 0) func $f $g) 46 | (elem $a9 (table $t) (offset (i32.const 0)) funcref) 47 | (elem $a10 (table $t) (offset (i32.const 0)) func $f $g) 48 | (elem $a11 (table 0) (i32.const 0) func) 49 | (elem $a12 (table 0x0) (i32.const 0) func $f $f) 50 | (elem $a13 (table 0x000) (offset (i32.const 0)) func) 51 | (elem $a14 (table 0) (offset (i32.const 0)) func $f $f) 52 | (elem $a15 (table $t) (i32.const 0) func) 53 | (elem $a16 (table $t) (i32.const 0) func $f $f) 54 | (elem $a17 (table $t) (offset (i32.const 0)) func) 55 | (elem $a18 (table $t) (offset (i32.const 0)) func $f $f) 56 | (elem $a19 (offset (i32.const 0))) 57 | (elem $a20 (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) 58 | (elem $a21 (offset (i32.const 0)) func $f $f) 59 | (elem $a22 (offset (i32.const 0)) $f $f) 60 | (elem $a23 (i32.const 0)) 61 | (elem $a24 (i32.const 0) funcref (ref.func $f) (ref.null func)) 62 | (elem $a25 (i32.const 0) func $f $f) 63 | (elem $a26 (i32.const 0) $f $f) 64 | 65 | ;; Declarative 66 | (elem declare funcref) 67 | (elem declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) 68 | (elem declare func) 69 | (elem declare func $f $f $g $g) 70 | 71 | (elem $d1 declare funcref) 72 | (elem $d2 declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) 73 | (elem $d3 declare func) 74 | (elem $d4 declare func $f $f $g $g) 75 | ) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/spec_elem_1.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type $out-i32 (func (result i32))) 3 | (table 10 funcref) 4 | (elem (i32.const 7) $const-i32-a) 5 | (elem (i32.const 9) $const-i32-b) 6 | (func $const-i32-a (type $out-i32) (i32.const 65)) 7 | (func $const-i32-b (type $out-i32) (i32.const 66)) 8 | (func (export "call-7") (type $out-i32) 9 | (call_indirect (type $out-i32) (i32.const 7)) 10 | ) 11 | (func (export "call-9") (type $out-i32) 12 | (call_indirect (type $out-i32) (i32.const 9)) 13 | ) 14 | ) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/spec_elem_2.wat: -------------------------------------------------------------------------------- 1 | (module $module1 2 | (type $out-i32 (func (result i32))) 3 | (table (export "shared-table") 10 funcref) 4 | (elem (i32.const 8) $const-i32-a) 5 | (elem (i32.const 9) $const-i32-b) 6 | (func $const-i32-a (type $out-i32) (i32.const 65)) 7 | (func $const-i32-b (type $out-i32) (i32.const 66)) 8 | (func (export "call-7") (type $out-i32) 9 | (call_indirect (type $out-i32) (i32.const 7)) 10 | ) 11 | (func (export "call-8") (type $out-i32) 12 | (call_indirect (type $out-i32) (i32.const 8)) 13 | ) 14 | (func (export "call-9") (type $out-i32) 15 | (call_indirect (type $out-i32) (i32.const 9)) 16 | ) 17 | ) -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/start.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (func $first) 3 | (start $first)) 4 | -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/tables.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (table (import "spectest" "table") 0 funcref) 3 | (table 0 funcref) 4 | (table 1 funcref) 5 | (table 1 100 funcref) 6 | (table 0 externref) 7 | (table 1 externref) 8 | (table 1 100 externref) 9 | ) 10 | -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/binary/types.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (func )) 3 | (type (func (param i32 i64 f32 f64) (result i32))) 4 | (type $foo (func (param i32 i64 f32 f64) (result i32))) 5 | ) 6 | -------------------------------------------------------------------------------- /pykwasm/src/tests/integration/test_binary_parser.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | from io import BytesIO 5 | from pathlib import Path 6 | from subprocess import run 7 | from typing import TYPE_CHECKING 8 | 9 | import pytest 10 | from pyk.kast.inner import KSequence, KSort, Subst 11 | from pyk.kast.manip import split_config_from 12 | 13 | from pykwasm.wasm2kast import wasm2kast 14 | 15 | if TYPE_CHECKING: 16 | from pyk.kast import KInner 17 | from pyk.ktool.krun import KRun 18 | 19 | 20 | BINARY_DIR = Path(__file__).parent / 'binary' 21 | BINARY_WAT_FILES = BINARY_DIR.glob('*.wat') 22 | 23 | sys.setrecursionlimit(1500000000) 24 | 25 | 26 | @pytest.mark.parametrize('wat_path', BINARY_WAT_FILES, ids=str) 27 | def test_wasm2kast(krun_llvm: KRun, wat_path: Path) -> None: 28 | # Given 29 | wat2wasm_cmd = ['wat2wasm', str(wat_path), '--output=/dev/stdout'] 30 | proc_res = run(wat2wasm_cmd, check=True, capture_output=True) 31 | wasm_file = BytesIO(proc_res.stdout) 32 | 33 | assert not proc_res.returncode 34 | 35 | # When 36 | module = wasm2kast(wasm_file) 37 | 38 | # Then 39 | run_module(krun_llvm, module) 40 | 41 | 42 | def run_module(krun: KRun, parsed_module: KInner) -> None: 43 | try: 44 | # Create an initial config 45 | config_kast = krun.definition.init_config(KSort('GeneratedTopCell')) 46 | 47 | # Embed parsed_module to 48 | symbolic_config, init_subst = split_config_from(config_kast) 49 | init_subst['K_CELL'] = KSequence(parsed_module) 50 | config_with_module = Subst(init_subst)(symbolic_config) 51 | 52 | # Convert the config to kore 53 | config_kore = krun.kast_to_kore(config_with_module, KSort('GeneratedTopCell')) 54 | 55 | # Run the config 56 | krun.run_pattern(config_kore) 57 | 58 | except Exception as e: 59 | raise Exception('Received error while running') from e 60 | -------------------------------------------------------------------------------- /pykwasm/src/tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/wasm-semantics/8f0ab878103753a4fd4229f0533cb43d8c31ff63/pykwasm/src/tests/unit/__init__.py -------------------------------------------------------------------------------- /pykwasm/src/tests/unit/test_kwasm_ast.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pykwasm.kwasm_ast import KBytes 4 | 5 | KBYTES_TEST_DATA = ( 6 | (bytes([0x0, 0x41, 0xFF]), 'b"\\x00A\\xff"'), 7 | (bytes([]), 'b""'), 8 | (b'WASM', 'b"WASM"'), 9 | (b'foo\xaa\x01barbaz', 'b"foo\\xaa\\x01barbaz"'), 10 | (b'foo\xaabar\x01baz', 'b"foo\\xaabar\\x01baz"'), 11 | (b'abcdefghijklmnopqrstuvwxyz', 'b"abcdefghijklmnopqrstuvwxyz"'), 12 | ( 13 | 0x11223344556677889900AABBCCDDEEFF.to_bytes(length=16, byteorder='big'), 14 | 'b"\\x11\\"3DUfw\\x88\\x99\\x00\\xaa\\xbb\\xcc\\xdd\\xee\\xff"', 15 | ), 16 | ) 17 | 18 | 19 | @pytest.mark.parametrize(('input', 'expected'), KBYTES_TEST_DATA) 20 | def test_kbytes(input: bytes, expected: str) -> None: 21 | # When 22 | t = KBytes(input) 23 | # How KToken stores the string may change. Check the serialized string instead of t.token 24 | t_dict = t.to_dict() 25 | 26 | # Then 27 | assert t_dict['token'] == expected 28 | assert t_dict['sort']['name'] == 'Bytes' 29 | -------------------------------------------------------------------------------- /pykwasm/src/tests/unit/test_wasm2kast.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | import pytest 6 | from pyk.kast.inner import KApply 7 | from wasm.datatypes import ExternAddress, FunctionAddress, Limits, Table, TableType 8 | 9 | from pykwasm import wasm2kast 10 | from pykwasm.kwasm_ast import KInt, externref, funcref 11 | 12 | if TYPE_CHECKING: 13 | from pyk.kast import KInner 14 | 15 | 16 | TABLE_TEST_DATA = ( 17 | (Table(TableType(Limits(0, None), FunctionAddress)), KApply('limitsMin', [KInt(0)]), funcref), 18 | (Table(TableType(Limits(0, 100), ExternAddress)), KApply('limitsMinMax', [KInt(0), KInt(100)]), externref), 19 | ) 20 | 21 | 22 | @pytest.mark.parametrize(('input', 'limits', 'typ'), TABLE_TEST_DATA) 23 | def test_table(input: Table, limits: KInner, typ: KInner) -> None: 24 | # When 25 | t = wasm2kast.table(input) 26 | 27 | # Then 28 | assert limits == t.args[0] 29 | assert typ == t.args[1] 30 | -------------------------------------------------------------------------------- /tests/conformance/look_for_supported.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Execute the script from project top directory. 4 | 5 | # This script considers all conformance tests currently listed as unparseable or unsupported, and tries parsing and executing them in turn. 6 | # If both steps are successfull, the confromance test is deleted from the lists. 7 | # If either step fails, the conformance test is added to the correct list and removed from the other. 8 | 9 | unparsefile="tests/conformance/unparseable.txt" 10 | 11 | unparseable=$(cat $unparsefile) 12 | backends="llvm" 13 | 14 | # Try all unparseable files, see if any new one parses and add them to the unsupported lists. 15 | # Keep the files sorted and without duplicates so the diff is easy to follow. 16 | for shortname in $unparseable $unsupported; do 17 | file=tests/wasm-tests/test/core/$shortname 18 | 19 | echo Trying to parse: $shortname 20 | echo =============== 21 | 22 | make $file.parse 23 | if [ $? -eq 0 ] 24 | then 25 | sed --in-place "/^$shortname\$/d" $unparsefile 26 | for backend in $backends; do 27 | unsuppfile="tests/conformance/unsupported-$backend.txt" 28 | echo $shortname >> $unsuppfile 29 | sort -u $unsuppfile -o $unsuppfile 30 | done 31 | else 32 | echo $shortname >> $unparsefile 33 | sort -u $unparsefile -o $unparsefile 34 | for backend in $backends; do 35 | unsuppfile="tests/conformance/unsupported-$backend.txt" 36 | sed --in-place "/^$shortname\$/d" $unsuppfile 37 | done 38 | echo "Unparseable: $shortname\n" 39 | fi 40 | done 41 | 42 | # Go over the unsupported files, see if any has become supported. 43 | for backend in $backends; do 44 | unsuppfile="tests/conformance/unsupported-$backend.txt" 45 | unsupported=$(cat $unsuppfile) 46 | for shortname in $unsupported; do 47 | 48 | file=tests/wasm-tests/test/core/$shortname 49 | 50 | echo Trying to run: $shortname 51 | echo ============= 52 | 53 | make $file.run-term TEST_CONCRETE_BACKEND=$backend 54 | if [ $? -eq 0 ] 55 | then 56 | # Now supported, remove. 57 | sed --in-place "/^$shortname\$/d" $unparsefile 58 | sed --in-place "/^$shortname\$/d" $unsuppfile 59 | sort -u $unsuppfile -o $unsuppfile 60 | echo "New supported ($backend): $shortname\n" 61 | else 62 | echo "Unsupported ($backend): $shortname\n" 63 | fi 64 | done 65 | done 66 | -------------------------------------------------------------------------------- /tests/conformance/unparseable.txt: -------------------------------------------------------------------------------- 1 | block.wast 2 | br_table.wast 3 | bulk.wast 4 | comments.wast 5 | conversions.wast 6 | data.wast 7 | endianness.wast 8 | float_exprs.wast 9 | float_literals.wast 10 | global.wast 11 | if.wast 12 | imports.wast 13 | loop.wast 14 | memory.wast 15 | memory_init.wast 16 | select.wast 17 | tokens.wast 18 | -------------------------------------------------------------------------------- /tests/conformance/unsupported-llvm.txt: -------------------------------------------------------------------------------- 1 | address.wast 2 | align.wast 3 | call_indirect.wast 4 | const.wast 5 | f32.wast 6 | f32_bitwise.wast 7 | f64.wast 8 | f64_bitwise.wast 9 | fac.wast 10 | float_memory.wast 11 | float_misc.wast 12 | func.wast 13 | left-to-right.wast 14 | memory_redundancy.wast 15 | memory_trap.wast 16 | traps.wast 17 | -------------------------------------------------------------------------------- /tests/failing.proofs: -------------------------------------------------------------------------------- 1 | tests/proofs/loops-spec.k 2 | tests/proofs/wrc20-spec.k 3 | -------------------------------------------------------------------------------- /tests/failing.simple: -------------------------------------------------------------------------------- 1 | tests/simple/f64_bitwise-cs.wast 2 | tests/simple/f64_cmp-cs.wast 3 | tests/simple/f64-cs.wast 4 | tests/simple/fconversions-c.wast 5 | -------------------------------------------------------------------------------- /tests/interactive/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/interactive/fac.wast: -------------------------------------------------------------------------------- 1 | // (c) 2015 Andreas Rossberg 2 | 3 | (module 4 | // Recursive factorial 5 | (func (param i32) (result i32) 6 | (local) // opt 7 | (return 8 | (if 9 | (eq.i32 (getlocal 0) (const.i32 0)) 10 | (const.i32 1) 11 | (mul.i32 (getlocal 0) (call 0 (sub.i32 (getlocal 0) (const.i32 1)))) 12 | ) 13 | ) 14 | ) 15 | 16 | // Recursive factorial with implicit return value 17 | (func (param i32) (result i32) 18 | (local) // opt 19 | (if 20 | (eq.i32 (getlocal 0) (const.i32 0)) 21 | (const.i32 1) 22 | (mul.i32 (getlocal 0) (call 0 (sub.i32 (getlocal 0) (const.i32 1)))) 23 | ) 24 | ) 25 | 26 | // Iterative factorial 27 | (func (param i32) (result i32) 28 | (local i32) 29 | (setlocal 1 (const.i32 1)) 30 | (label 31 | (loop 32 | (if 33 | (eq.i32 (getlocal 0) (const.i32 0)) 34 | (break 0) 35 | (block 36 | (setlocal 1 (mul.i32 (getlocal 0) (getlocal 1))) 37 | (setlocal 0 (sub.i32 (getlocal 0) (const.i32 1))) 38 | ) 39 | ) 40 | ) 41 | ) 42 | (return (getlocal 1)) 43 | ) 44 | 45 | (export 0 1 2) 46 | 47 | (memory 0) 48 | ) 49 | 50 | (invoke 0 (const.i32 3)) 51 | (invoke 1 (const.i32 3)) 52 | (invoke 2 (const.i32 3)) 53 | -------------------------------------------------------------------------------- /tests/interactive/fac.wast.out: -------------------------------------------------------------------------------- 1 | 6 2 | 6 3 | 6 4 | -------------------------------------------------------------------------------- /tests/interactive/memory.wast: -------------------------------------------------------------------------------- 1 | // (c) 2015 Andreas Rossberg 2 | 3 | (module 4 | // Aligned read/write 5 | (func (param) (result i32) 6 | (local i32 i32 i32) 7 | (setlocal 0 (const.i32 10)) 8 | (label 9 | (loop 10 | (if 11 | (eq.i32 (getlocal 0) (const.i32 0)) 12 | (break) 13 | ) 14 | (setlocal 2 (mul.i32 (getlocal 0) (const.i32 4))) 15 | (setnears.i32 (getlocal 2) (getlocal 0)) 16 | (setlocal 1 (getnears.i32 (getlocal 2))) 17 | (if 18 | (neq.i32 (getlocal 0) (getlocal 1)) 19 | (return (const.i32 0)) 20 | ) 21 | (setlocal 0 (sub.i32 (getlocal 0) (const.i32 1))) 22 | ) 23 | ) 24 | (return (const.i32 1)) 25 | ) 26 | 27 | // Unaligned read/write 28 | (func (param) (result i32) 29 | (local i32 i32 i32) 30 | (setlocal 0 (const.i32 10)) 31 | (label 32 | (loop 33 | (if 34 | (eq.i32 (getlocal 0) (const.i32 0)) 35 | (break) 36 | ) 37 | (setlocal 2 (getlocal 0)) 38 | (setnearunaligneds.i32 (getlocal 0) (getlocal 2)) 39 | (setlocal 1 (getnearunaligneds.i32 (getlocal 0))) 40 | (if 41 | (neq.i32 (getlocal 2) (getlocal 1)) 42 | (return (const.i32 0)) 43 | ) 44 | (setlocal 0 (sub.i32 (getlocal 0) (const.i32 1))) 45 | ) 46 | ) 47 | (return (const.i32 1)) 48 | ) 49 | 50 | // Memory cast 51 | (func (param) (result f64) 52 | (local) 53 | (setnears.i64 (const.i32 8) (const.i64 -12345)) 54 | (if 55 | (eq.f64 (getnear.f64 (const.i32 8)) (cast.i64.f64 (const.i64 -12345))) 56 | (return (const.f64 0)) 57 | ) 58 | (setfarunaligneds.i16 (const.i64 3) (const.i32 -23423)) 59 | (return (getnear.f64 (const.i32 0))) 60 | ) 61 | 62 | (export 0 1 2) 63 | 64 | (memory 64) 65 | ) 66 | 67 | (invoke 0) 68 | (invoke 1) 69 | //(invoke 2) 70 | -------------------------------------------------------------------------------- /tests/interactive/memory.wast.out: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | -------------------------------------------------------------------------------- /tests/interactive/ret.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (param) (result i32 i32) 3 | (local) 4 | (return 5 | (const.i32 1) 6 | (const.i32 2) 7 | ) 8 | ) 9 | 10 | (func (param) (result i32) 11 | (local i32 i32) 12 | (destruct 0 1 (call 0)) 13 | (return (add.i32 (getlocal 0) (getlocal 1))) 14 | ) 15 | 16 | (export 0 1) 17 | 18 | (memory 0) 19 | ) 20 | 21 | (invoke 1) 22 | -------------------------------------------------------------------------------- /tests/interactive/ret.wast.out: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /tests/interactive/sum.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (param i32) (result i32) 3 | (local i32) 4 | (setlocal 1 (const.i32 0)) 5 | (label 6 | (loop 7 | (if 8 | (eq.i32 (getlocal 0) (const.i32 0)) 9 | (break 0) 10 | (block 11 | (setlocal 1 (add.i32 (getlocal 0) (getlocal 1))) 12 | (setlocal 0 (sub.i32 (getlocal 0) (const.i32 1))) 13 | ) 14 | ) 15 | ) 16 | ) 17 | (return (getlocal 1)) 18 | ) 19 | 20 | (export 0) 21 | 22 | (memory 0) 23 | ) 24 | 25 | (invoke 0 (const.i32 10)) 26 | -------------------------------------------------------------------------------- /tests/interactive/sum.wast.out: -------------------------------------------------------------------------------- 1 | 55 2 | -------------------------------------------------------------------------------- /tests/proofs/functions-spec.k: -------------------------------------------------------------------------------- 1 | requires "kwasm-lemmas.md" 2 | 3 | module FUNCTIONS-SPEC 4 | imports KWASM-LEMMAS 5 | 6 | claim run ( #wrap(2, #getRange(BM, ADDR, 4)) ) => done ( #getRange(BM, ADDR, 2) ) ... requires 0 <=Int ADDR 7 | 8 | claim run ( #setRange(BM, ADDR, #wrap(2, #getRange(BM, ADDR, 4)), 2) ) => done ( BM ) ... requires 0 <=Int ADDR 9 | 10 | claim run ( #getRange(_BM, _ADDR, 0) ) => done ( 0 ) ... 11 | claim run ( #getRange(_BM, ADDR, _WIDTH) ) => done ( 0 ) ... requires ADDR run ( #getRange(BM, ADDR, 1) modInt 256 ) => done ( #getRange(BM, ADDR , 1) ) ... 13 | claim run ( #getRange(BM, ADDR, 3) modInt 256 ) => done ( #getRange(BM, ADDR , 1) ) ... 14 | claim run ( #getRange(BM, ADDR, 3) modInt (2 ^Int (8 *Int 3)) ) => done ( #getRange(BM, ADDR , 3) ) ... 15 | claim run ( #getRange(BM, ADDR, 7) modInt (2 ^Int (8 *Int 3)) ) => done ( #getRange(BM, ADDR , 3) ) ... 16 | claim run ( #getRange(BM, ADDR, 2) >>Int 8 ) => done ( #getRange(BM, ADDR +Int 1, 1) ) ... requires 0 <=Int ADDR 17 | 18 | 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 ) < 22 | 23 | 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 ) < 27 | 28 | 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) ) 30 | ... 31 | 32 | requires ADDR >=Int 0 33 | 34 | claim run ( #setRange ( BM , ADDR modInt 4294967296 , #getRange ( BM , ADDR modInt 4294967296 , #numBytes ( ITYPE ) ) , #numBytes ( ITYPE ) ) ) 35 | => done ( BM ) 36 | ... 37 | 38 | 39 | 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) < 43 | 44 | claim run ( #getRange ( #setRange ( BM , ADDR +Int 7 , _VAL , 1 ) , ADDR +Int 3 , 1 ) ) => done ( #getRange ( BM , ADDR +Int 3 , 1 ) ) ... 45 | 46 | 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 ) ) 48 | => done ( #getRange ( BM , ADDR +Int 4 , 1 ) ) 49 | ... 50 | 51 | requires 0 <=Int ADDR 52 | 53 | claim run ( substrSparseBytes(_SB, S, _E) ) => done ( .SparseBytes ) ... requires S run ( substrSparseBytes(_SB, _S, E) ) => done ( .SparseBytes ) ... requires E run ( substrSparseBytes(_SB, S, E) ) => done ( .SparseBytes ) ... requires E run ( #getRange(_SB, S, _W) ) => done ( 0 ) ... requires S run ( #getRange(_SB, _S, W) ) => done ( 0 ) ... requires W run ( unwrap(fromBytes(Bs))) => done ( Bs ) ... 61 | 62 | claim run ( #getBytesRange( 63 | SBChunk(#bytes(b"abcd")) 64 | SBChunk(#bytes(b"efgh")), 65 | 2, 66 | 4 67 | ) 68 | ) 69 | => done ( b"cdef" ) 70 | ... 71 | 72 | 73 | claim run ( #getBytesRange( 74 | SBChunk(#bytes(B1)) 75 | SBChunk(#empty(N1)) 76 | SBChunk(#bytes(B2)), 77 | lengthBytes(B1) +Int N1, 78 | WIDTH 79 | ) 80 | ) 81 | => done ( padRightBytes(B2, WIDTH, 0) ) 82 | ... 83 | 84 | requires N1 ==K 123000000 85 | andBool WIDTH ==K 120 86 | andBool B1 ==K b"00000000000000000000000000000000asdfghjklqwertyuio" 87 | andBool B2 ==K b"asdfghjklqwertyuio" 88 | 89 | claim run ( #getBytesRange( 90 | SBChunk(#bytes(B1)) 91 | SBChunk(#empty(N1)) 92 | SBChunk(#bytes(B2)), 93 | lengthBytes(B1) +Int N1 -Int Z, 94 | WIDTH 95 | ) 96 | ) 97 | => done ( padRightBytes(zeros(Z) +Bytes B2, WIDTH, 0) ) 98 | ... 99 | 100 | requires N1 ==K 123000000 101 | andBool Z ==K 30 102 | andBool WIDTH ==K 120 103 | andBool B1 ==K b"00000000000000000000000000000000asdfghjklqwertyuio" 104 | andBool B2 ==K b"asdfghjklqwertyuio" 105 | 106 | claim run ( #getBytesRange( 107 | SBChunk(#bytes(b"a")) 108 | SBChunk(#empty(1)) 109 | SBChunk(#bytes(b"b")) 110 | SBChunk(#empty(1)) 111 | SBChunk(#bytes(b"c")) 112 | SBChunk(#empty(1)) 113 | SBChunk(#bytes(b"d")) 114 | SBChunk(#empty(1)) 115 | SBChunk(#bytes(b"e")), 116 | 0, 117 | 100 118 | ) 119 | ) 120 | => done ( padRightBytes(b"a\x00b\x00c\x00d\x00e", 100, 0) ) 121 | ... 122 | 123 | 124 | // Should not allocate huge bytes 125 | claim run ( #getBytesRange( 126 | SBChunk(#empty(Z)) 127 | SBChunk(#bytes(b"x")), 128 | Z -Int 1, 129 | 2 130 | ) 131 | ) 132 | => done ( b"\x00x" ) 133 | ... 134 | 135 | requires Z ==K 1000000000000 // ~ 1 TB 136 | 137 | endmodule 138 | -------------------------------------------------------------------------------- /tests/proofs/locals-spec.k: -------------------------------------------------------------------------------- 1 | requires "kwasm-lemmas.md" 2 | 3 | module LOCALS-SPEC 4 | imports KWASM-LEMMAS 5 | 6 | claim #local.get(X) ~> #local.set(X) => .K ... 7 | 8 | X |-> _:IVal 9 | 10 | 11 | claim #local.get(X) ~> #local.set(X) => .K ... 12 | 13 | X |-> _:FVal 14 | 15 | 16 | claim #local.get(X) ~> #local.set(X) => .K ... 17 | 18 | X |-> _:RefVal 19 | 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /tests/proofs/loops-spec.k: -------------------------------------------------------------------------------- 1 | requires "kwasm-lemmas.md" 2 | 3 | module LOOPS-SPEC 4 | imports KWASM-LEMMAS 5 | 6 | // Lemma 7 | claim #br(0) 8 | ~> label // Loop label. 9 | [ .ValTypes ] 10 | { #loop([ .ValTypes ], 11 | #local.get(0) 12 | #local.get(1) 13 | ITYPE.add 14 | #local.set(1) 15 | #local.get(0) 16 | ITYPE.const 1 17 | ITYPE.sub 18 | #local.tee(0) 19 | ITYPE.eqz 20 | #br_if(1) 21 | #br(0), 22 | _ 23 | ) 24 | } 25 | .ValStack 26 | ~> label [ .ValTypes ] {.Instrs } STACK // Block label. 27 | => .K 28 | ... 29 | 30 | _ => STACK 31 | 32 | 0 |-> < ITYPE > (I => 0) 33 | 1 |-> < ITYPE > (X => X +Int ((I *Int (I +Int 1)) /Int 2)) 34 | 35 | requires #inUnsignedRange(ITYPE, I) 36 | andBool I >Int 0 37 | andBool #inUnsignedRange(ITYPE, X +Int I) 38 | andBool #inUnsignedRange(ITYPE, X +Int ((I *Int (I +Int 1)) /Int 2)) 39 | 40 | // Main claim. 41 | claim 42 | #block([ .ValTypes ], 43 | #loop([ .ValTypes], 44 | #local.get(0) 45 | #local.get(1) 46 | ITYPE.add 47 | #local.set(1) 48 | #local.get(0) 49 | ITYPE.const 1 50 | ITYPE.sub 51 | #local.tee(0) 52 | ITYPE.eqz 53 | #br_if(1) 54 | #br(0), 55 | _ 56 | ), 57 | _ 58 | ) 59 | => .K 60 | ... 61 | 62 | 63 | 0 |-> < ITYPE > (N => 0) 64 | 1 |-> < ITYPE > (0 => (N *Int (N +Int 1)) /Int 2) 65 | 66 | requires #inUnsignedRange(ITYPE, N) 67 | andBool N >Int 0 68 | andBool #inUnsignedRange(ITYPE, ((N *Int (N +Int 1)) /Int 2)) 69 | 70 | endmodule 71 | -------------------------------------------------------------------------------- /tests/proofs/memory-spec.k: -------------------------------------------------------------------------------- 1 | requires "kwasm-lemmas.md" 2 | 3 | module MEMORY-SPEC 4 | imports KWASM-LEMMAS 5 | 6 | claim i32.const ADDR ~> i32.const ADDR ~> #load(i64, load32_u, 0) ~> #store(i64, store16, 0) => .K ... 7 | CUR 8 | 9 | CUR 10 | 0 |-> MEMADDR 11 | ... 12 | 13 | 14 | MEMADDR 15 | SIZE 16 | _BM 17 | ... 18 | 19 | requires 20 | ADDR +Int #numBytes(i64) <=Int SIZE *Int #pageSize() 21 | andBool #inUnsignedRange(i32, ADDR) 22 | 23 | claim i32.const ADDR ~> i32.const ADDR ~> #load(ITYPE:IValType, load, 0) ~> #store(ITYPE, store, 0) => .K ... 24 | CUR 25 | 26 | CUR 27 | 0 |-> MEMADDR 28 | ... 29 | 30 | 31 | MEMADDR 32 | SIZE 33 | _BM 34 | ... 35 | 36 | requires 37 | #get(#chop( ADDR)) +Int #numBytes(ITYPE) <=Int SIZE *Int #pageSize() 38 | endmodule 39 | -------------------------------------------------------------------------------- /tests/proofs/simple-arithmetic-spec.k: -------------------------------------------------------------------------------- 1 | requires "kwasm-lemmas.md" 2 | 3 | module SIMPLE-ARITHMETIC-SPEC 4 | imports KWASM-LEMMAS 5 | 6 | claim ITYPE:IValType . const X:Int => .K ... 7 | S:ValStack => < ITYPE > X : S 8 | requires #inUnsignedRange(ITYPE, X) 9 | 10 | claim ITYPE:IValType . const X:Int => .K ... 11 | S:ValStack => < ITYPE > (X +Int #pow(ITYPE)) : S 12 | requires (#minSigned(ITYPE) <=Int X) andBool (X ITYPE:IValType . const X:Int ~> ITYPE . const Y:Int ~> ITYPE . add => .K ... 15 | S:ValStack => < ITYPE > (X +Int Y) : S 16 | requires 0 <=Int X andBool 0 <=Int Y 17 | andBool (X +Int Y) i32.const #unsigned(i32, #signed(i32, #pow(i32) -Int 1)) 21 | => .K ... 22 | 23 | S => < i32 > #pow(i32) -Int 1 : S 24 | 25 | 26 | // #unsigned( i64 , #signed( i64 , 2^64 - 1 ) ) == 2^64 - 1 27 | claim i64.const #unsigned(i64, #signed(i64, #pow(i64) -Int 1)) 28 | => .K ... 29 | 30 | S => < i64 > #pow(i64) -Int 1 : S 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /tests/proofs/wrc20-spec.k: -------------------------------------------------------------------------------- 1 | requires "wrc20.md" 2 | 3 | // This is the "fast transfer" version of the WRC20 spec by pauld. 4 | 5 | module WRC20-SPEC 6 | imports WRC20-LEMMAS 7 | 8 | // Reverse bytes spec. 9 | 10 | claim sequenceDefns(#t2aDefns<#freshCtx()>(#wrc20ReverseBytes)) // TODO: Have this pre-loaded in the store. 11 | ~> i32.const ADDR 12 | ~> i32.const ADDR 13 | ~> #load(i64, load, 0) 14 | ~> (invoke NEXTADDR) // TODO: Use `call`. 15 | ~> #store(i64, store, 0) 16 | => .K 17 | ... 18 | 19 | CUR 20 | 21 | CUR 22 | #wrc20ReverseBytesTypeIdx |-> #wrc20ReverseBytesType 23 | 0 |-> MEMADDR 24 | _ => ?_ 25 | NEXTFUNCIDX => NEXTFUNCIDX +Int 1 26 | ... 27 | 28 | .Bag => ?_ 29 | NEXTADDR => NEXTADDR +Int 1 30 | 31 | MEMADDR 32 | SIZE 33 | BM => ?BM' 34 | ... 35 | 36 | // TODO: Make function out of this tricky side condition. 37 | requires ADDR +Int #numBytes(i64) <=Int SIZE *Int #pageSize() 38 | andBool #inUnsignedRange(i32, ADDR) 39 | ensures #getRange(BM, ADDR +Int 0, 1) ==Int #getRange(?BM', ADDR +Int 7, 1) 40 | andBool #getRange(BM, ADDR +Int 1, 1) ==Int #getRange(?BM', ADDR +Int 6, 1) 41 | andBool #getRange(BM, ADDR +Int 2, 1) ==Int #getRange(?BM', ADDR +Int 5, 1) 42 | andBool #getRange(BM, ADDR +Int 3, 1) ==Int #getRange(?BM', ADDR +Int 4, 1) 43 | andBool #getRange(BM, ADDR +Int 4, 1) ==Int #getRange(?BM', ADDR +Int 3, 1) 44 | andBool #getRange(BM, ADDR +Int 5, 1) ==Int #getRange(?BM', ADDR +Int 2, 1) 45 | andBool #getRange(BM, ADDR +Int 6, 1) ==Int #getRange(?BM', ADDR +Int 1, 1) 46 | andBool #getRange(BM, ADDR +Int 7, 1) ==Int #getRange(?BM', ADDR +Int 0, 1) 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /tests/simple/arithmetic.wast: -------------------------------------------------------------------------------- 1 | (i32.const 5) 2 | (i32.const 7) 3 | (i32.add) 4 | #assertTopStack < i32 > 12 "add" 5 | 6 | (i32.const 5) 7 | (i32.const 7) 8 | (i32.sub) 9 | #assertTopStack < i32 > -2 "sub" 10 | 11 | (i32.const 15) 12 | (i32.const 3) 13 | (i32.mul) 14 | #assertTopStack < i32 > 45 "mul" 15 | 16 | (i32.const 15) 17 | (i32.const 3) 18 | (i32.div_u) 19 | #assertTopStack < i32 > 5 "div_u1" 20 | 21 | (i32.const 15) 22 | (i32.const 2) 23 | (i32.div_u) 24 | #assertTopStack < i32 > 7 "div_u2" 25 | 26 | (i32.const 15) 27 | (i32.const 0) 28 | (i32.div_u) 29 | #assertTrap "div_u3" 30 | 31 | (i32.const 15) 32 | (i32.const 3) 33 | (i32.rem_u) 34 | #assertTopStack < i32 > 0 "rem_u1" 35 | 36 | (i32.const 15) 37 | (i32.const 2) 38 | (i32.rem_u) 39 | #assertTopStack < i32 > 1 "rem_u2" 40 | 41 | (i32.const 15) 42 | (i32.const 0) 43 | (i32.rem_u) 44 | #assertTrap "rem_u3" 45 | 46 | (i32.const 10) 47 | (i32.const 3) 48 | (i32.div_s) 49 | #assertTopStack < i32 > 3 "i32.div_s 1" 50 | 51 | (i32.const 10) 52 | (i32.const 4) 53 | (i32.div_s) 54 | #assertTopStack < i32 > 2 "i32.div_s 2" 55 | 56 | (i32.const 10) 57 | (i32.const 0) 58 | (i32.div_s) 59 | #assertTrap "i32.div_s 3" 60 | 61 | (i32.const #pow1(i32)) 62 | (i32.sub (i32.const #pow(i32)) (i32.const 1)) 63 | (i32.div_s) 64 | #assertTrap "i32.div_s 4" 65 | 66 | (i32.const 10) 67 | (i32.const 5) 68 | (i32.div_s) 69 | #assertTopStack < i32 > 2 "div_s" 70 | 71 | (i32.const 91) 72 | (i32.const 13) 73 | (i32.rem_s) 74 | #assertTopStack 0 "rem_s" 75 | 76 | (i32.const -91) 77 | (i32.const -13) 78 | (i32.rem_s) 79 | #assertTopStack 0 "rem_s" 80 | 81 | (i32.const -1) 82 | (i32.const -3) 83 | (i32.rem_s) 84 | #assertTopStack -1 "rem_s" 85 | 86 | (i32.const 10) 87 | (i32.const 0) 88 | (i32.rem_s) 89 | #assertTrap "rem_s" 90 | 91 | (i32.const #pow1(i32)) 92 | (i32.sub (i32.const #pow(i32)) (i32.const 1)) 93 | (i32.rem_s) 94 | #assertTopStack 0 "rem_s edge case" 95 | 96 | ;; The following tests were generated using the reference OCaml WASM interpreter. 97 | 98 | (i32.const 10) 99 | (i32.const 3) 100 | (i32.rem_s) 101 | #assertTopStack < i32 > 1 "i32.rem_s 1" 102 | 103 | (i32.const 10) 104 | (i32.const 4) 105 | (i32.rem_s) 106 | #assertTopStack < i32 > 2 "i32.rem_s 2" 107 | 108 | (i32.const 10) 109 | (i32.const 5) 110 | (i32.rem_s) 111 | #assertTopStack < i32 > 0 "i32.rem_s 3" 112 | 113 | (i32.const -10) 114 | (i32.const 3) 115 | (i32.div_s) 116 | #assertTopStack < i32 > -3 "i32.div_s 3" 117 | 118 | (i32.const -10) 119 | (i32.const 4) 120 | (i32.div_s) 121 | #assertTopStack < i32 > -2 "i32.div_s 4" 122 | 123 | (i32.const -10) 124 | (i32.const 5) 125 | (i32.div_s) 126 | #assertTopStack < i32 > -2 "i32.div_s 5" 127 | 128 | (i32.const -10) 129 | (i32.const 3) 130 | (i32.rem_s) 131 | #assertTopStack < i32 > -1 "i32.rem_s 4" 132 | 133 | (i32.const -10) 134 | (i32.const 4) 135 | (i32.rem_s) 136 | #assertTopStack < i32 > -2 "i32.rem_s 5" 137 | 138 | (i32.const -10) 139 | (i32.const 5) 140 | (i32.rem_s) 141 | #assertTopStack < i32 > 0 "i32.rem_s 6" 142 | 143 | (i32.const -10) 144 | (i32.const -3) 145 | (i32.div_s) 146 | #assertTopStack < i32 > 3 "i32.div_s 6" 147 | 148 | (i32.const -10) 149 | (i32.const -4) 150 | (i32.div_s) 151 | #assertTopStack < i32 > 2 "i32.div_s 7" 152 | 153 | (i32.const -10) 154 | (i32.const -5) 155 | (i32.div_s) 156 | #assertTopStack < i32 > 2 "i32.div_s 8" 157 | 158 | (i32.const -10) 159 | (i32.const -3) 160 | (i32.rem_s) 161 | #assertTopStack < i32 > -1 "i32.rem_s 7" 162 | 163 | (i32.const -10) 164 | (i32.const -4) 165 | (i32.rem_s) 166 | #assertTopStack < i32 > -2 "i32.rem_s 8" 167 | 168 | (i32.const -10) 169 | (i32.const -5) 170 | (i32.rem_s) 171 | #assertTopStack < i32 > 0 "i32.rem_s 9" 172 | 173 | (i32.add (i32.const 3) (i32.const 4)) 174 | #assertTopStack < i32 > 7 "simple add folded" 175 | 176 | (i32.sub (i32.const 3) (i32.const 4)) 177 | #assertTopStack < i32 > -1 "simple sub, order dependent folded" 178 | 179 | (i32.sub (i32.mul (i32.const 5) (i32.const 7)) (i32.const 4)) 180 | #assertTopStack < i32 > 31 "mul nested in sub folded" 181 | 182 | #clearConfig 183 | -------------------------------------------------------------------------------- /tests/simple/bitwise.wast: -------------------------------------------------------------------------------- 1 | (i32.const 20) 2 | (i32.const 18) 3 | (i32.and) 4 | #assertTopStack < i32 > 16 "and" 5 | 6 | (i32.const 20) 7 | (i32.const 18) 8 | (i32.or) 9 | #assertTopStack < i32 > 22 "or" 10 | 11 | (i32.const 20) 12 | (i32.const 18) 13 | (i32.xor) 14 | #assertTopStack < i32 > 6 "xor" 15 | 16 | (i32.const 2) 17 | (i32.const 1) 18 | (i32.shl) 19 | #assertTopStack < i32 > 4 "shl 1" 20 | 21 | (i32.const 2) 22 | (i32.add (i32.const #pow1(i32)) (i32.const 1)) 23 | (i32.shl) 24 | #assertTopStack < i32 > 4 "shl 2" 25 | 26 | (i32.const #pow1(i32)) 27 | (i32.const 2) 28 | (i32.shr_u) 29 | #assertTopStack < i32 > 536870912 "shr_u 1" ;; 2 ^Int 29 30 | 31 | (i32.const 2) 32 | (i32.const 2) 33 | (i32.shr_u) 34 | #assertTopStack < i32 > 0 "shr_u 2" 35 | 36 | (i32.sub (i32.const #pow(i32)) (i32.const 2)) 37 | (i32.const 1) 38 | (i32.shr_s) 39 | #assertTopStack < i32 > 4294967295 "shr_s 1" ;; #pow(i32) -Int 1 40 | 41 | (i32.const 2) 42 | (i32.const 2) 43 | (i32.shr_s) 44 | #assertTopStack < i32 > 0 "shr_s 2" 45 | 46 | (i32.add (i32.const #pow1(i32)) (i32.const 2)) 47 | (i32.const 3) 48 | (i32.rotl) 49 | #assertTopStack < i32 > 20 "rotl" 50 | 51 | (i32.add (i32.const #pow1(i32)) (i32.const 16)) 52 | (i32.const 3) 53 | (i32.rotr) 54 | #assertTopStack < i32 > 268435458 "rotr" ;; 2 ^Int 28 +Int 2 55 | 56 | ;; clz 57 | 58 | (i32.const #pow1(i32)) 59 | (i32.clz) 60 | #assertTopStack < i32 > 0 "clz #pow1(i32)" 61 | (i64.const #pow1(i64)) 62 | (i64.clz) 63 | #assertTopStack < i64 > 0 "clz #pow1(i62)" 64 | 65 | (i32.const 0) 66 | (i32.clz) 67 | #assertTopStack < i32 > 32 "clz 0" 68 | (i64.const 0) 69 | (i64.clz) 70 | #assertTopStack < i64 > 64 "clz 0" 71 | 72 | (i32.const 1) 73 | (i32.clz) 74 | #assertTopStack < i32 > 31 "clz 1" 75 | (i64.const 1) 76 | (i64.clz) 77 | #assertTopStack < i64 > 63 "clz 1" 78 | 79 | (i32.sub (i32.const #pow(i32)) (i32.const 1)) 80 | (i32.clz) 81 | #assertTopStack < i32 > 0 "clz 2^32 - 1" 82 | 83 | (i64.sub (i64.const #pow(i64)) (i64.const 1)) 84 | (i64.clz) 85 | #assertTopStack < i64 > 0 "clz 2^64 - 1" 86 | 87 | (i32.sub (i32.const #pow1(i32)) (i32.const 1)) 88 | (i32.clz) 89 | #assertTopStack < i32 > 1 "clz 2^31 - 1" 90 | 91 | (i64.sub (i64.const #pow1(i64)) (i64.const 1)) 92 | (i64.clz) 93 | #assertTopStack < i64 > 1 "clz 2^63 - 1" 94 | 95 | ;; ctz 96 | (i32.const #pow1(i32)) 97 | (i32.ctz) 98 | #assertTopStack < i32 > 31 "ctz #pow1(i32)" 99 | (i64.const #pow1(i64)) 100 | (i64.ctz) 101 | #assertTopStack < i64 > 63 "ctz #pow1(i32)" 102 | 103 | (i32.const 0) 104 | (i32.ctz) 105 | #assertTopStack < i32 > 32 "ctz 0" 106 | (i64.const 0) 107 | (i64.ctz) 108 | #assertTopStack < i64 > 64 "ctz 0" 109 | 110 | (i32.const 1) 111 | (i32.ctz) 112 | #assertTopStack < i32 > 0 "ctz 1" 113 | (i64.const 1) 114 | (i64.ctz) 115 | #assertTopStack < i64 > 0 "ctz 1" 116 | 117 | (i32.sub (i32.const #pow(i32)) (i32.const 1)) 118 | (i32.ctz) 119 | #assertTopStack < i32 > 0 "ctz 2^32 - 1" 120 | (i64.sub (i64.const #pow(i64)) (i64.const 1)) 121 | (i64.ctz) 122 | #assertTopStack < i64 > 0 "ctz 2^64 - 1" 123 | 124 | ;; popcnt 125 | 126 | (i32.const #pow1(i32)) 127 | (i32.popcnt) 128 | #assertTopStack < i32 > 1 "popcnt #pow1(i32)" 129 | (i64.const #pow1(i64)) 130 | (i64.popcnt) 131 | #assertTopStack < i64 > 1 "popcnt #pow1(i32)" 132 | 133 | (i32.const 0) 134 | (i32.popcnt) 135 | #assertTopStack < i32 > 0 "popcnt 0" 136 | (i64.const 0) 137 | (i64.popcnt) 138 | #assertTopStack < i64 > 0 "popcnt 0" 139 | 140 | (i32.const 1) 141 | (i32.popcnt) 142 | #assertTopStack < i32 > 1 "popcnt 1" 143 | (i64.const 1) 144 | (i64.popcnt) 145 | #assertTopStack < i64 > 1 "popcnt 1" 146 | 147 | (i32.sub (i32.const #pow(i32)) (i32.const 1)) 148 | (i32.popcnt) 149 | #assertTopStack < i32 > 32 "popcnt 2^32 - 1" 150 | (i64.sub (i64.const #pow(i64)) (i64.const 1)) 151 | (i64.popcnt) 152 | #assertTopStack < i64 > 64 "popcnt 2^64 - 1" 153 | 154 | #clearConfig 155 | -------------------------------------------------------------------------------- /tests/simple/branching.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "as-if-cond") (param i32) (result i32) 3 | (block (result i32) 4 | (if (result i32) 5 | (br_if 0 (i32.const 1) (local.get 0)) 6 | (then (i32.const 2)) 7 | (else (i32.const 3)) 8 | ) 9 | ) 10 | ) 11 | 12 | (func (export "to-top-level0") (br 0)) 13 | (func (export "to-top-level1") (block (br 0))) 14 | ) 15 | 16 | (assert_return (invoke "as-if-cond" (i32.const 1)) (i32.const 1)) 17 | (assert_return (invoke "to-top-level0")) 18 | (assert_return (invoke "to-top-level1")) 19 | 20 | #clearConfig -------------------------------------------------------------------------------- /tests/simple/comments.wast: -------------------------------------------------------------------------------- 1 | (i32.const 7) 2 | ;; this should be ignored 3 | (i32.const 8) ;; this should be ignored as well 4 | (i32.add) 5 | 6 | (; 7 | all this text 8 | should be ignored 9 | ;) 10 | 11 | #assertTopStack < i32 > 15 "dummy test 1" 12 | 13 | (i32.const -3) 14 | (i32.const 6) (; comment at end of line ;) 15 | (i32.add) 16 | #assertTopStack < i32 > 3 "dummy test 2" 17 | 18 | (i32.const -3) 19 | (i32.(;comment in the middle;)const 6) 20 | (i32.add) 21 | #assertTopStack < i32 > 3 "dummy test 2" 22 | 23 | #clearConfig 24 | -------------------------------------------------------------------------------- /tests/simple/comparison.wast: -------------------------------------------------------------------------------- 1 | (i32.const 0) 2 | (i32.eqz) 3 | #assertTopStack < i32 > 1 "eqz1" 4 | 5 | (i32.const 3) 6 | (i32.eqz) 7 | #assertTopStack < i32 > 0 "eqz2" 8 | 9 | (i32.eqz (i32.const 3)) 10 | #assertTopStack < i32 > 0 "eqz folded" 11 | 12 | (i32.const 3) 13 | (i32.const 3) 14 | (i32.eq) 15 | #assertTopStack < i32 > 1 "eq1" 16 | 17 | (i32.const 3) 18 | (i32.const 4) 19 | (i32.eq) 20 | #assertTopStack < i32 > 0 "eq2" 21 | 22 | (i32.const 3) 23 | (i32.const 3) 24 | (i32.ne) 25 | #assertTopStack < i32 > 0 "ne1" 26 | 27 | (i32.const 3) 28 | (i32.const 4) 29 | (i32.ne) 30 | #assertTopStack < i32 > 1 "ne2" 31 | 32 | (i32.const 2) 33 | (i32.const 32) 34 | (i32.lt_u) 35 | #assertTopStack < i32 > 1 "lt_u" 36 | 37 | (i32.lt_u (i32.const 32) (i32.const 2)) 38 | #assertTopStack < i32 > 0 "lt_u" 39 | 40 | (i32.const 2) 41 | (i32.const 32) 42 | (i32.gt_u) 43 | #assertTopStack < i32 > 0 "gt_u" 44 | 45 | (i32.add (i32.const #pow1(i32)) (i32.const 7)) 46 | (i32.add (i32.const #pow1(i32)) (i32.const 15)) 47 | (i32.lt_s) 48 | #assertTopStack < i32 > 1 "lt_s 1" 49 | 50 | (i32.const -32) 51 | (i32.const 32) 52 | (i32.lt_s) 53 | #assertTopStack < i32 > 1 "lt_s 2" 54 | 55 | (i32.add (i32.const #pow1(i32)) (i32.const 7)) 56 | (i32.add (i32.const #pow1(i32)) (i32.const 15)) 57 | (i32.gt_s) 58 | #assertTopStack < i32 > 0 "gt_s 1" 59 | 60 | (i32.const -32) 61 | (i32.const 32) 62 | (i32.gt_s) 63 | #assertTopStack < i32 > 0 "gt_s 2" 64 | 65 | (i32.const 2) 66 | (i32.const 32) 67 | (i32.le_u) 68 | #assertTopStack < i32 > 1 "le_u 1" 69 | 70 | (i32.const 32) 71 | (i32.const 32) 72 | (i32.le_u) 73 | #assertTopStack < i32 > 1 "le_u 2" 74 | 75 | (i32.const 2) 76 | (i32.const 32) 77 | (i32.ge_u) 78 | #assertTopStack < i32 > 0 "ge_u 1" 79 | 80 | (i32.const 32) 81 | (i32.const 32) 82 | (i32.ge_u) 83 | #assertTopStack < i32 > 1 "ge_u 2" 84 | 85 | (i32.add (i32.const #pow1(i32)) (i32.const 7)) 86 | (i32.add (i32.const #pow1(i32)) (i32.const 15)) 87 | (i32.le_s) 88 | #assertTopStack < i32 > 1 "le_s 1" 89 | 90 | (i32.const 32) 91 | (i32.const 32) 92 | (i32.le_s) 93 | #assertTopStack < i32 > 1 "le_s 2" 94 | 95 | (i32.const -32) 96 | (i32.const 32) 97 | (i32.le_s) 98 | #assertTopStack < i32 > 1 "le_s 3" 99 | 100 | (i32.add (i32.const #pow1(i32)) (i32.const 7)) 101 | (i32.add (i32.const #pow1(i32)) (i32.const 15)) 102 | (i32.ge_s) 103 | #assertTopStack < i32 > 0 "ge_s 1" 104 | 105 | (i32.const 32) 106 | (i32.const 32) 107 | (i32.ge_s) 108 | #assertTopStack < i32 > 1 "ge_s 2" 109 | 110 | (i32.const -32) 111 | (i32.const 32) 112 | (i32.ge_s) 113 | #assertTopStack < i32 > 0 "ge_s 3" 114 | 115 | #clearConfig 116 | -------------------------------------------------------------------------------- /tests/simple/constants.wast: -------------------------------------------------------------------------------- 1 | ;; Integers 2 | ;; -------- 3 | 4 | (i32.const 3) 5 | #assertTopStack < i32 > 3 "i32 1" 6 | 7 | (i32.const 5) 8 | #assertTopStack < i32 > 5 "i32 parens" 9 | 10 | (i64.const 71) 11 | #assertTopStack < i64 > 71 "i64" 12 | 13 | (i32.const #unsigned(i32, -5)) 14 | #assertTopStack < i32 > 4294967291 "i32 manual unsigned" ;; #pow(i32) -Int 5 15 | 16 | (i32.sub (i32.const #pow(i32)) (i32.const 5)) 17 | #assertTopStack < i32 > -5 "i32 manual unsigned" 18 | 19 | (i32.const -5) 20 | #assertTopStack < i32 > #unsigned(i32, -5) "i32 signed constant" 21 | 22 | (i32.const #unsigned(i32, -5)) 23 | #assertTopStack < i32 > -5 "i32 signed assert" 24 | 25 | (i32.add (i32.const #pow(i32)) (i32.const 1)) 26 | #assertTopStack < i32 > 1 "i32 overflow" 27 | 28 | (i32.const -1) 29 | #assertTopStackExactly < i32 > 4294967295 "i32 overflow" 30 | 31 | (i64.const -1) 32 | #assertTopStackExactly < i64 > 18446744073709551615 "i62 overflow" ;; #pow(i64) -Int 1 33 | 34 | ;; Floating point 35 | ;; -------------- 36 | 37 | (f32.const 3.245) 38 | #assertTopStack < f32 > 3.245 "f32" 39 | 40 | (f64.const 3.234523) 41 | #assertTopStack < f64 > 3.234523 "f32 parens" 42 | 43 | (f64.const 1.21460644e+52) 44 | #assertTopStack < f64 > 1.21460644e+52 "f64 scientific 1" 45 | 46 | (f64.const 1.6085927714e-321) 47 | #assertTopStack < f64 > 1.6085927714e-321 "f64 scientific 2" 48 | 49 | (f64.const 1.63176601e-302) 50 | #assertTopStack < f64 > 1.63176601e-302 "f64 scientific 3" 51 | 52 | ;; Below examples do not work with current float parser 53 | ;; (f64.const 0x1.da21c460a6f44p+52) 54 | ;; (f64.const 0x1.60859d2e7714ap-321) 55 | ;; (f64.const 0x1.e63f1b7b660e1p-302) 56 | 57 | ;; Helper conversions 58 | ;; ------------------ 59 | 60 | (i32.const #unsigned(i32, #signed(i32, 0))) 61 | #assertTopStack < i32 > 0 "#unsigned . #signed 1" 62 | 63 | (i32.const #unsigned(i32, #signed(i32, #pow1(i32)))) 64 | #assertTopStack < i32 > #pow1(i32) "#unsigned . #signed 2" 65 | 66 | (i64.const #unsigned(i64, #signed(i64, 0))) 67 | #assertTopStack < i64 > 0 "#unsigned . #signed 4" 68 | 69 | (i64.const #unsigned(i64, #signed(i64, #pow1(i64)))) 70 | #assertTopStack < i64 > #pow1(i64) "#unsigned . #signed 5" 71 | 72 | #clearConfig 73 | -------------------------------------------------------------------------------- /tests/simple/control-flow.wast: -------------------------------------------------------------------------------- 1 | ;; Unreachable 2 | ( unreachable ) 3 | #assertTrap "unreachable" 4 | 5 | ;; Blocks 6 | 7 | block (result i32 i32 i32) 8 | (i32.const 1) 9 | (i32.const 2) 10 | (i32.const 3) 11 | end 12 | #assertStack < i32 > 3 : < i32 > 2 : < i32 > 1 : .ValStack "block 1" 13 | 14 | block (result i32 i32) 15 | (i32.const 1) 16 | (i32.const 2) 17 | (i32.const 3) 18 | (drop) 19 | end 20 | #assertStack < i32 > 2 : < i32 > 1 : .ValStack "block 2" 21 | 22 | block (result i32 i32) 23 | (i32.const 1) 24 | (i32.const 2) 25 | (i32.const 3) 26 | end 27 | #assertStack < i32 > 3 : < i32 > 2 : .ValStack "block 3 (invalid)" 28 | 29 | ;; (block (result i32) 30 | ;; (i32.const 1) 31 | ;; ) 32 | ;; #assertTopStack < i32 > 1 "block with named result 1" 33 | 34 | ;; (block result i64 i32 35 | ;; (i32.const 2) 36 | ;; (i32.const 1) 37 | ;; (i64.const 5) 38 | ;; ) 39 | ;; #assertStack < i64 > 5 : < i32 > 1 : .ValStack "block with named result 2" 40 | 41 | ;; Breaks 42 | 43 | (i32.const 1) 44 | (i32.const 2) 45 | block 46 | (i32.const 3) 47 | (br 0) 48 | (i32.const 4) 49 | (br 0) 50 | end 51 | #assertStack < i32 > 2 : < i32 > 1 : .ValStack "br 1" 52 | 53 | (i32.const 1) 54 | (i32.const 2) 55 | block 56 | (i32.const 3) 57 | block (result i32 i32) 58 | (i32.const 4) 59 | (i32.const 5) 60 | (br 1) 61 | end 62 | (i32.const 6) 63 | (br 0) 64 | end 65 | #assertStack < i32 > 2 : < i32 > 1 : .ValStack "br 2" 66 | 67 | (i32.const 1) 68 | (i32.const 2) 69 | block (result i32 i32) 70 | (i32.const 3) 71 | block (result i32 i32) 72 | (i32.const 4) 73 | (i32.const 5) 74 | (br 1) 75 | end 76 | (i32.const 6) 77 | (br 0) 78 | end 79 | #assertStack < i32 > 5 : < i32 > 4 : < i32 > 2 : < i32 > 1 : .ValStack "br 3" 80 | 81 | (i32.const 1) 82 | (i32.const 2) 83 | block (result i32 i32) 84 | (i32.const 3) 85 | block 86 | (i32.const 4) 87 | (i32.const 5) 88 | (br 1) 89 | end 90 | (i32.const 6) 91 | (br 0) 92 | end 93 | #assertStack < i32 > 5 : < i32 > 4 : < i32 > 2 : < i32 > 1 : .ValStack "br 4" 94 | 95 | (i32.const 1) 96 | (i32.const 2) 97 | block (result i32) 98 | (i32.const 3) 99 | (i32.const 0) 100 | (br_if 0) 101 | (i32.const 4) 102 | (br 0) 103 | end 104 | #assertStack < i32 > 4 : < i32 > 2 : < i32 > 1 : .ValStack "br_if 1 false" 105 | 106 | (i32.const 1) 107 | (i32.const 2) 108 | block (result i32) 109 | (i32.const 3) 110 | (i32.const 1) 111 | (br_if 0) 112 | (i32.const 4) 113 | (br 0) 114 | end 115 | #assertStack < i32 > 3 : < i32 > 2 : < i32 > 1 : .ValStack "br_if 1 true" 116 | 117 | (i32.const 1) 118 | (i32.const 2) 119 | block 120 | (i32.const 3) 121 | (i32.const 1) 122 | (br_if 0) 123 | (i32.const 4) 124 | (br 0) 125 | end 126 | #assertStack < i32 > 2 : < i32 > 1 : .ValStack "br_if 2 true" 127 | 128 | ;; Conditional 129 | 130 | (i32.const 1) 131 | if (result i32) i32.const 1 else i32.const -1 end 132 | #assertTopStack < i32 > 1 "if true" 133 | 134 | (i32.const 0) 135 | if (result i32) i32.const 1 else i32.const -1 end 136 | #assertTopStack < i32 > -1 "if false" 137 | 138 | ;; (i32.const -1) 139 | ;; (if (i32.const 0) (then)) 140 | ;; #assertTopStack < i32 > -1 "if folded false empty" 141 | 142 | ;; (i32.const -1) 143 | ;; (if (result i32) (i32.const 1) (then (i32.const 1)) (else (i32.const 2))) 144 | ;; #assertStack < i32 > 1 : < i32 > -1 : .ValStack "if folded true" 145 | 146 | ;; (i32.const -1) 147 | ;; (if (result i32) (i32.const 0) (then (i32.const 1)) (else (i32.const 2))) 148 | ;; #assertStack < i32 > 2 : < i32 > -1 : .ValStack "if folded false" 149 | 150 | ;; (if (result i32) (i32.const 1) (then (unreachable)) (else (i32.const 1))) 151 | ;; #assertTrap "if lazy first branch true" 152 | 153 | ;; (if (result i32) (i32.const 0) (then (unreachable)) (else (i32.const 1))) 154 | ;; #assertTopStack < i32 > 1 "if lazy first branch false" 155 | 156 | ;; (if (result i32) (i32.const 1) (then (i32.const -1)) (else (unreachable))) 157 | ;; #assertTopStack < i32 > -1 "if lazy second branch true" 158 | 159 | ;; (if (result i32) (i32.const 0) (then (i32.const -1)) (else (unreachable))) 160 | ;; #assertTrap "if lazy second branch false" 161 | 162 | ;; (if (result i32) (unreachable) (then (i32.const -1)) (else (unreachable))) 163 | ;; #assertTrap "if strict condition" 164 | 165 | ;; Looping 166 | 167 | init_locals < i32 > 10 : < i32 > 0 : .ValStack 168 | loop 169 | (local.get 0) 170 | (local.get 1) 171 | (i32.add) 172 | (local.set 1) 173 | (local.get 0) 174 | (i32.const 1) 175 | (i32.sub) 176 | (local.tee 0) 177 | (br_if 0) 178 | end 179 | #assertLocal 0 < i32 > 0 "sum 1 -> 10 loop" 180 | #assertLocal 1 < i32 > 55 "sum 1 -> 10 loop" 181 | 182 | init_locals < i32 > 10 : < i32 > 0 : .ValStack 183 | block 184 | loop 185 | (local.get 0) 186 | (local.get 1) 187 | (i32.add) 188 | (local.set 1) 189 | (local.get 0) 190 | (i32.const 1) 191 | (i32.sub) 192 | (local.tee 0) 193 | (i32.eqz) 194 | (br_if 1) 195 | (br 0) 196 | end 197 | end 198 | #assertLocal 0 < i32 > 0 "sum 1 -> 10 loop concrete syntax" 199 | #assertLocal 1 < i32 > 55 "sum 1 -> 10 loop concrete syntax" 200 | 201 | ;; Stack Underflow 202 | ;; TODO: We need to give semantics to stack underflow (though it could not happen with a validated program). 203 | ;; We need `trap` semantics first. 204 | ;; (i32.const 0) 205 | ;; block [ i32 i32 ] 206 | ;; (i32.const 7) 207 | ;; end 208 | 209 | #clearConfig 210 | -------------------------------------------------------------------------------- /tests/simple/conversion.wast: -------------------------------------------------------------------------------- 1 | ;; Wrap. 2 | 3 | (i64.const 4294967296) ;; 2^32 4 | (i32.wrap_i64) 5 | #assertTopStack < i32 > 0 "wrap 2^32" 6 | 7 | (i64.const 4294967295) ;; 2^32 - 1 8 | (i32.wrap_i64) 9 | #assertTopStack < i32 > 4294967295 "wrap 2^32 - 1" 10 | 11 | (i32.wrap_i64 (i64.const 4294967298)) 12 | #assertTopStack < i32 > 2 "folded wrap 2^32 + 2" 13 | 14 | ;; Extend. 15 | 16 | (i32.const 4294967295) ;; 2^32 - 1 17 | (i64.extend_i32_u) 18 | #assertTopStack < i64 > 4294967295 "extend unsig" 19 | 20 | (i32.const -1) ;; 2^32 - 1 21 | (i64.extend_i32_s) 22 | #assertTopStack < i64 > -1 "extend sig" 23 | 24 | (i64.extend_i32_s (i32.const 15)) 25 | #assertTopStack < i64 > 15 "folded extend sig" 26 | 27 | (module 28 | (func (export "i64.extend_i32_s") (param $x i32) (result i64) (i64.extend_i32_s (local.get $x))) 29 | (func (export "i64.extend_i32_u") (param $x i32) (result i64) (i64.extend_i32_u (local.get $x))) 30 | (func (export "i32.wrap_i64") (param $x i64) (result i32) (i32.wrap_i64 (local.get $x))) 31 | ) 32 | 33 | (assert_return (invoke "i64.extend_i32_s" (i32.const 0)) (i64.const 0)) 34 | (assert_return (invoke "i64.extend_i32_s" (i32.const 10000)) (i64.const 10000)) 35 | (assert_return (invoke "i64.extend_i32_s" (i32.const -10000)) (i64.const -10000)) 36 | (assert_return (invoke "i64.extend_i32_s" (i32.const -1)) (i64.const -1)) 37 | (assert_return (invoke "i64.extend_i32_s" (i32.const 0x7fffffff)) (i64.const 0x000000007fffffff)) 38 | (assert_return (invoke "i64.extend_i32_s" (i32.const 0x80000000)) (i64.const 0xffffffff80000000)) 39 | 40 | (assert_return (invoke "i64.extend_i32_u" (i32.const 0)) (i64.const 0)) 41 | (assert_return (invoke "i64.extend_i32_u" (i32.const 10000)) (i64.const 10000)) 42 | (assert_return (invoke "i64.extend_i32_u" (i32.const -10000)) (i64.const 0x00000000ffffd8f0)) 43 | (assert_return (invoke "i64.extend_i32_u" (i32.const -1)) (i64.const 0xffffffff)) 44 | (assert_return (invoke "i64.extend_i32_u" (i32.const 0x7fffffff)) (i64.const 0x000000007fffffff)) 45 | (assert_return (invoke "i64.extend_i32_u" (i32.const 0x80000000)) (i64.const 0x0000000080000000)) 46 | 47 | #clearConfig 48 | -------------------------------------------------------------------------------- /tests/simple/data.wast: -------------------------------------------------------------------------------- 1 | ;; Instantiating with data 2 | 3 | (module 4 | (memory $an-ident (data "WASM" "2\2E0")) 5 | ) 6 | 7 | (memory.size) 8 | 9 | #assertTopStack < i32 > 1 "size of stack" 10 | #assertMemoryData (0, 87) "text to ascii W" 11 | #assertMemoryData (1, 65) "text to ascii A" 12 | #assertMemoryData (2, 83) "text to ascii S" 13 | #assertMemoryData (3, 77) "text to ascii M" 14 | #assertMemoryData (4, 50) "text to ascii 2" 15 | #assertMemoryData (5, 46) "text to ascii ." 16 | #assertMemoryData (6, 48) "text to ascii 0" 17 | #assertMemory $an-ident 1 1 "memorys string length" 18 | 19 | #clearConfig 20 | 21 | (module 22 | (memory 1 1) 23 | (data (offset (i32.const 100)) "W" "AS" "M") 24 | ) 25 | #assertMemoryData (100, 87) "text to ascii W" 26 | #assertMemoryData (101, 65) "text to ascii A" 27 | #assertMemoryData (102, 83) "text to ascii S" 28 | #assertMemoryData (103, 77) "text to ascii M" 29 | #assertMemory 0 1 1 "memorys string length" 30 | 31 | #clearConfig 32 | 33 | (module 34 | (memory (data)) 35 | ) 36 | #clearConfig 37 | 38 | (module 39 | (memory (data "W")) 40 | ) 41 | #assertMemoryData (0, 87) "text to ascii W" 42 | #assertMemory 0 1 1 "memorys string length" 43 | 44 | #clearConfig 45 | 46 | (module 47 | (memory (data "\"\t\n\n\t\'\"\r\u{090A}")) 48 | ) 49 | #assertMemoryData (0, 34) "text to ascii special" 50 | #assertMemoryData (1, 9) "text to ascii special" 51 | #assertMemoryData (2, 10) "text to ascii special" 52 | #assertMemoryData (3, 10) "text to ascii special" 53 | #assertMemoryData (4, 9) "text to ascii special" 54 | #assertMemoryData (5, 39) "text to ascii special" 55 | #assertMemoryData (6, 34) "text to ascii special" 56 | 57 | (module 58 | (memory $m 1 1) 59 | (data (offset (i32.const 0)) "\00") 60 | (data (offset (nop) (i32.const 1)) "\01") 61 | (data (offset (i32.const 2) (nop)) "\02") 62 | (data $m (offset (i32.const 3)) "\03") 63 | (data $m (offset (nop) (i32.const 4)) "\04") 64 | (data $m (offset (i32.const 5) (nop)) "\05") 65 | 66 | (data (offset (i32.const 6 (nop))) "\06") 67 | (data $m (offset (i32.const 7 (nop))) "\07") 68 | 69 | (global $g i32 (i32.const 8)) 70 | (global $h i32 (i32.const 9)) 71 | 72 | (data (offset (global.get $g)) "\08") 73 | (data $m (offset (global.get $h)) "\09") 74 | 75 | (func $main (local i32) 76 | (local.set 0 (i32.const 9)) 77 | loop 78 | (i32.load8_u (local.get 0)) 79 | (local.get 0) 80 | (if (i32.ne) (then (unreachable))) 81 | (i32.sub (local.get 0) (i32.const 1)) 82 | (local.tee 0) 83 | (i32.eqz) 84 | (br_if 1) 85 | (br 0) 86 | end 87 | ) 88 | 89 | (start $main) 90 | ) 91 | #clearConfig 92 | -------------------------------------------------------------------------------- /tests/simple/desugaring.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "foo") (result i32) (i32.const 0)) 3 | (func (export "bar") (result i32) (i32.const 1)) 4 | ) 5 | 6 | (register "a") 7 | 8 | ;; Test that imports get ordered correctly. 9 | ;; Function "bar" should get index 0, since it is imported first. 10 | (module 11 | (func (import "a" "bar") (result i32)) 12 | (import "a" "foo" (func (result i32))) 13 | (export "bar" (func 0) ) 14 | ) 15 | 16 | (assert_return (invoke "bar") (i32.const 1)) 17 | 18 | ;; Test that data initializations get ordered correctly. 19 | ;; The results of the inlined `data` should overwrite the results of the non-inlined data. 20 | (module 21 | (data (offset (i32.const 0)) "b") 22 | (memory (data "a")) 23 | (func (export "baz") (result i32) 24 | (i32.load (i32.const 0)) 25 | ) 26 | ) 27 | 28 | (assert_return (invoke "baz") (i32.const 97)) 29 | 30 | ;; Same as above but for `elem` 31 | (module 32 | (elem (offset (i32.const 0)) 0) 33 | (table funcref (elem 1)) 34 | (func (result i32) (i32.const 0)) 35 | (func (result i32) (i32.const 1)) 36 | (func (export "biz") (result i32) 37 | (call_indirect (result i32) (i32.const 0)) 38 | ) 39 | ) 40 | 41 | (assert_return (invoke "biz") (i32.const 1)) 42 | 43 | ;; Regression test: A module with hex integers inside a function after a `table` with inline `elem`. 44 | (module 45 | (table funcref (elem)) 46 | (func (export "break-inner") (result i32) 47 | (local i32) 48 | (local.set 0 (i32.const 0)) 49 | (local.set 0 (i32.add (local.get 0) (block (result i32) (block (result i32) (br 1 (i32.const 0x1)))))) 50 | (local.set 0 (i32.add (local.get 0) (block (result i32) (block (br 0)) (i32.const 0x2)))) 51 | (local.set 0 52 | (i32.add (local.get 0) (block (result i32) (i32.ctz (br 0 (i32.const 0x4))))) 53 | ) 54 | (local.set 0 55 | (i32.add (local.get 0) (block (result i32) (i32.ctz (block (result i32) (br 1 (i32.const 0x8)))))) 56 | ) 57 | (local.get 0) 58 | ) 59 | ) 60 | 61 | #clearConfig 62 | -------------------------------------------------------------------------------- /tests/simple/f64_cmp-cs.wast: -------------------------------------------------------------------------------- 1 | ;; Test all the f64 comparison operators on major boundary values and all 2 | ;; special values. 3 | 4 | (module 5 | (func (export "eq") (param $x f64) (param $y f64) (result i32) (f64.eq (local.get $x) (local.get $y))) 6 | (func (export "ne") (param $x f64) (param $y f64) (result i32) (f64.ne (local.get $x) (local.get $y))) 7 | (func (export "lt") (param $x f64) (param $y f64) (result i32) (f64.lt (local.get $x) (local.get $y))) 8 | (func (export "le") (param $x f64) (param $y f64) (result i32) (f64.le (local.get $x) (local.get $y))) 9 | (func (export "gt") (param $x f64) (param $y f64) (result i32) (f64.gt (local.get $x) (local.get $y))) 10 | (func (export "ge") (param $x f64) (param $y f64) (result i32) (f64.ge (local.get $x) (local.get $y))) 11 | ) 12 | 13 | (assert_return (invoke "eq" (f64.const -0.0) (f64.const -0.0)) (i32.const 1)) 14 | (assert_return (invoke "eq" (f64.const -0.0) (f64.const 0.0)) (i32.const 1)) 15 | (assert_return (invoke "eq" (f64.const 0.0) (f64.const -0.0)) (i32.const 1)) 16 | (assert_return (invoke "eq" (f64.const 0.0) (f64.const 0.0)) (i32.const 1)) 17 | (assert_return (invoke "eq" (f64.const -0.0) (f64.const -4.94065645841e-324)) (i32.const 0)) 18 | (assert_return (invoke "eq" (f64.const -0.0) (f64.const 4.94065645841e-324)) (i32.const 0)) 19 | (assert_return (invoke "eq" (f64.const 0.0) (f64.const -4.94065645841e-324)) (i32.const 0)) 20 | (assert_return (invoke "eq" (f64.const 0.0) (f64.const 4.94065645841e-324)) (i32.const 0)) 21 | (assert_return (invoke "eq" (f64.const -4.94065645841e-324) (f64.const -4.94065645841e-324)) (i32.const 1)) 22 | (assert_return (invoke "eq" (f64.const -4.94065645841e-324) (f64.const 4.94065645841e-324)) (i32.const 0)) 23 | (assert_return (invoke "eq" (f64.const 4.94065645841e-324) (f64.const -4.94065645841e-324)) (i32.const 0)) 24 | (assert_return (invoke "eq" (f64.const 4.94065645841e-324) (f64.const 4.94065645841e-324)) (i32.const 1)) 25 | (assert_return (invoke "ne" (f64.const -0.0) (f64.const 2.22507385851e-308)) (i32.const 1)) 26 | (assert_return (invoke "ne" (f64.const 0.0) (f64.const -2.22507385851e-308)) (i32.const 1)) 27 | (assert_return (invoke "ne" (f64.const 0.0) (f64.const 2.22507385851e-308)) (i32.const 1)) 28 | (assert_return (invoke "ne" (f64.const -0.0) (f64.const -0.5)) (i32.const 1)) 29 | (assert_return (invoke "ne" (f64.const -0.0) (f64.const 0.5)) (i32.const 1)) 30 | (assert_return (invoke "ne" (f64.const 0.0) (f64.const -0.5)) (i32.const 1)) 31 | (assert_return (invoke "ne" (f64.const 0.0) (f64.const 0.5)) (i32.const 1)) 32 | (assert_return (invoke "ne" (f64.const -0.0) (f64.const -1.0)) (i32.const 1)) 33 | (assert_return (invoke "ne" (f64.const -0.0) (f64.const 1.0)) (i32.const 1)) 34 | (assert_return (invoke "ne" (f64.const NaN) (f64.const -0.0)) (i32.const 1)) 35 | (assert_return (invoke "lt" (f64.const -0.0) (f64.const -0.0)) (i32.const 0)) 36 | (assert_return (invoke "lt" (f64.const -0.0) (f64.const 0.0)) (i32.const 0)) 37 | (assert_return (invoke "lt" (f64.const 0.0) (f64.const -0.0)) (i32.const 0)) 38 | (assert_return (invoke "lt" (f64.const 0.0) (f64.const 0.0)) (i32.const 0)) 39 | (assert_return (invoke "lt" (f64.const -0.0) (f64.const -4.94065645841e-324)) (i32.const 0)) 40 | (assert_return (invoke "lt" (f64.const -0.0) (f64.const 4.94065645841e-324)) (i32.const 1)) 41 | (assert_return (invoke "lt" (f64.const 0.0) (f64.const -4.94065645841e-324)) (i32.const 0)) 42 | (assert_return (invoke "lt" (f64.const 0.0) (f64.const 4.94065645841e-324)) (i32.const 1)) 43 | (assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const 6.28318530718)) (i32.const 1)) 44 | (assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const -6.28318530718)) (i32.const 0)) 45 | (assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const 6.28318530718)) (i32.const 0)) 46 | (assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const -1.79769313486e+308)) (i32.const 0)) 47 | (assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const 1.79769313486e+308)) (i32.const 1)) 48 | (assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const -1.79769313486e+308)) (i32.const 0)) 49 | (assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const 1.79769313486e+308)) (i32.const 0)) 50 | (assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const -Infinity)) (i32.const 0)) 51 | (assert_return (invoke "lt" (f64.const -1.79769313486e+308) (f64.const Infinity)) (i32.const 1)) 52 | (assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const -Infinity)) (i32.const 0)) 53 | (assert_return (invoke "lt" (f64.const 1.79769313486e+308) (f64.const Infinity)) (i32.const 1)) 54 | ;; (assert_return (invoke "le" (f64.const -0x0.0000000000001p-1022) (f64.const -nan)) (i32.const 0)) 55 | ;; (assert_return (invoke "le" (f64.const -0x0.0000000000001p-1022) (f64.const -nan:0x4000000000000)) (i32.const 0)) 56 | (assert_return (invoke "le" (f64.const -4.94065645841e-324) (f64.const NaN)) (i32.const 0)) 57 | ;; (assert_return (invoke "le" (f64.const -0x0.0000000000001p-1022) (f64.const nan:0x4000000000000)) (i32.const 0)) 58 | ;; (assert_return (invoke "le" (f64.const 0x0.0000000000001p-1022) (f64.const -nan)) (i32.const 0)) 59 | ;; (assert_return (invoke "le" (f64.const 0x0.0000000000001p-1022) (f64.const -nan:0x4000000000000)) (i32.const 0)) 60 | (assert_return (invoke "le" (f64.const 4.94065645841e-324) (f64.const NaN)) (i32.const 0)) 61 | (assert_return (invoke "gt" (f64.const -Infinity) (f64.const 1.0)) (i32.const 0)) 62 | (assert_return (invoke "gt" (f64.const Infinity) (f64.const -1.0)) (i32.const 1)) 63 | (assert_return (invoke "gt" (f64.const Infinity) (f64.const 1.0)) (i32.const 1)) 64 | (assert_return (invoke "gt" (f64.const -Infinity) (f64.const -6.28318530718)) (i32.const 0)) 65 | (assert_return (invoke "gt" (f64.const -Infinity) (f64.const 6.28318530718)) (i32.const 0)) 66 | (assert_return (invoke "gt" (f64.const Infinity) (f64.const -6.28318530718)) (i32.const 1)) 67 | (assert_return (invoke "gt" (f64.const Infinity) (f64.const 6.28318530718)) (i32.const 1)) 68 | (assert_return (invoke "ge" (f64.const -0.0) (f64.const -0.0)) (i32.const 1)) 69 | (assert_return (invoke "ge" (f64.const -0.0) (f64.const 0.0)) (i32.const 1)) 70 | (assert_return (invoke "ge" (f64.const 0.0) (f64.const -0.0)) (i32.const 1)) 71 | (assert_return (invoke "ge" (f64.const 0.0) (f64.const 0.0)) (i32.const 1)) 72 | (assert_return (invoke "ge" (f64.const -Infinity) (f64.const 0.0)) (i32.const 0)) 73 | (assert_return (invoke "ge" (f64.const Infinity) (f64.const -0.0)) (i32.const 1)) 74 | (assert_return (invoke "ge" (f64.const Infinity) (f64.const 0.0)) (i32.const 1)) 75 | 76 | #clearConfig 77 | -------------------------------------------------------------------------------- /tests/simple/functions_call.wast: -------------------------------------------------------------------------------- 1 | ;; Simple add function 2 | 3 | (module 4 | (type $a-cool-type (func (param i32) (param $b i32) ( result i32 ))) 5 | ) 6 | 7 | #assertType 0 [ i32 i32 ] -> [ i32 ] 8 | #assertNextTypeIdx 1 9 | 10 | (module 11 | (type $a-cool-type (func (param i32) (param $b i32) ( result i32 ))) 12 | (func $x (type $a-cool-type) 13 | (local.get 0) 14 | (local.get 1) 15 | (i32.add) 16 | (return) 17 | ) 18 | (export "000" (func 0)) 19 | 20 | ;; String-named add function 21 | 22 | (func $add (type $a-cool-type) (param $a i32) (param i32) ( result i32 ) 23 | (local.get $a) 24 | (local.get 1) 25 | (i32.add) 26 | (return) 27 | ) 28 | 29 | ;; Remove return statement, don't use explicit type name 30 | 31 | (func $0 (param $a i32) (param $b i32) result i32 32 | (local.get $a) 33 | (local.get $b) 34 | (i32.add) 35 | ) 36 | 37 | 38 | (table 1 funcref) 39 | (elem (i32.const 0) 2) 40 | 41 | ;; More complicated function with locals 42 | 43 | (func $1 param i64 i64 i64 result i64 local i64 44 | (i64.sub (local.get 2) (i64.add (local.get 0) (local.get 1))) 45 | (local.set 3) 46 | (local.get 3) 47 | (return) 48 | ) 49 | 50 | ( export "export-1" (func 3) ) 51 | ) 52 | 53 | (assert_return (invoke "000" (i32.const 7) (i32.const 8)) (i32.const 15)) 54 | #assertFunction 0 [ i32 i32 ] -> [ i32 ] [ ] "call function 0 exists" 55 | 56 | #assertFunction 1 [ i32 i32 ] -> [ i32 ] [ ] "function string-named add" 57 | #assertNextTypeIdx 2 58 | 59 | (assert_return (invoke "export-1" (i64.const 100) (i64.const 43) (i64.const 22)) (i64.const -121)) 60 | #assertFunction 3 [ i64 i64 i64 ] -> [ i64 ] [ i64 ] "call function 1 exists" 61 | 62 | 63 | (i32.const 7) 64 | (i32.const 8) 65 | (i32.const 0) 66 | (call_indirect (type $a-cool-type)) 67 | 68 | #assertTopStack < i32 > 15 "call function 0 no return" 69 | (drop) 70 | #assertFunction 2 [ i32 i32 ] -> [ i32 ] [ ] "call function 0 exists no return" 71 | 72 | ;; Function with complicated declaration of types 73 | (module 74 | (func $2 result i32 param i32 i64 param i64 local i32 75 | (local.get 0) 76 | (return) 77 | ) 78 | (func (export "out-of-order-type-declaration") (result i32) 79 | (i32.const 7) 80 | (i64.const 8) 81 | (i64.const 5) 82 | (call $2) 83 | ) 84 | ) 85 | (assert_return (invoke "out-of-order-type-declaration") (i32.const 7)) 86 | #assertFunction 0 [ i32 i64 i64 ] -> [ i32 ] [ i32 ] "out of order type declarations" 87 | #assertNextTypeIdx 2 88 | 89 | ;; Function with empty declarations of types 90 | 91 | (module 92 | (func $0 param i64 i64 result result i64 param local 93 | (local.get 0) 94 | (return) 95 | ) 96 | 97 | (func $1 (param i64 i64) (result i64) 98 | (local.get 0) 99 | (return) 100 | ) 101 | (func (export "cool") (result i64) 102 | i64.const 10 103 | i64.const 11 104 | call $1 105 | ) 106 | ) 107 | 108 | (assert_return (invoke "cool") (i64.const 10)) 109 | #assertFunction 1 [ i64 i64 ] -> [ i64 ] [ ] "empty type declarations" 110 | #assertNextTypeIdx 2 111 | 112 | ;; Function with just a name 113 | 114 | (module 115 | (func $3) 116 | (export "return-null" (func $3) ) 117 | ) 118 | (assert_return (invoke "return-null")) 119 | 120 | #assertFunction 0 [ ] -> [ ] [ ] "no domain/range or locals" 121 | 122 | (module 123 | (func $add (export "add") 124 | (param i32 i32) 125 | (result i32) 126 | (local.get 0) 127 | (local.get 1) 128 | (i32.add) 129 | (return) 130 | ) 131 | 132 | (func $sub (export "sub") 133 | (param i32 i32) 134 | (result i32) 135 | (local.get 0) 136 | (local.get 1) 137 | (i32.sub) 138 | (return) 139 | ) 140 | 141 | (func $mul (export "mul") 142 | (param i32 i32) 143 | (result i32) 144 | (local.get 0) 145 | (local.get 1) 146 | (i32.mul) 147 | (return) 148 | ) 149 | 150 | (func $xor (export "xor") (param i32 i32) (result i32) 151 | (local.get 0) 152 | (local.get 1) 153 | (i32.xor) 154 | ) 155 | ) 156 | 157 | (assert_return (invoke "add" (i32.const 3) (i32.const 5)) (i32.const 8)) 158 | (assert_return (invoke "mul" (i32.const 3) (i32.const 5)) (i32.const 15)) 159 | (assert_return (invoke "sub" (i32.const 12) (i32.const 5)) (i32.const 7)) 160 | (assert_return (invoke "xor" (i32.const 3) (i32.const 5)) (i32.const 6)) 161 | 162 | #assertFunction 0 [ i32 i32 ] -> [ i32 ] [ ] "add function typed correctly" 163 | #assertFunction 1 [ i32 i32 ] -> [ i32 ] [ ] "sub function typed correctly" 164 | #assertFunction 2 [ i32 i32 ] -> [ i32 ] [ ] "mul function typed correctly" 165 | #assertFunction 3 [ i32 i32 ] -> [ i32 ] [ ] "xor function typed correctly" 166 | #assertNextTypeIdx 1 167 | 168 | (module 169 | (func $f1 (param $a i32) (param i32) (result i32) (local $c i32) 170 | (local.get $a) 171 | (local.get 1) 172 | (i32.add) 173 | (local.set $c) 174 | (local.get $a) 175 | (local.get $c) 176 | (i32.mul) 177 | (return) 178 | ) 179 | 180 | (func $f2 (param i32 i32 i32 ) (result i32) (local i32 i32) 181 | (local.get 0) 182 | (local.get 2) 183 | (call $f1) 184 | (local.get 1) 185 | (call $f1) 186 | (local.get 0) 187 | (i32.mul) 188 | (return) 189 | ) 190 | 191 | (func (export "nested-method-call") (result i32) 192 | (i32.const 3) 193 | (i32.const 5) 194 | (call $f1) 195 | (i32.const 5) 196 | (i32.const 8) 197 | (call $f2) 198 | ) 199 | 200 | ) 201 | 202 | (assert_return (invoke "nested-method-call") (i32.const 14247936)) 203 | #assertFunction 0 [ i32 i32 ] -> [ i32 ] [ i32 ] "inner calling method" 204 | #assertFunction 1 [ i32 i32 i32 ] -> [ i32 ] [ i32 i32 ] "outer calling method" 205 | 206 | (module 207 | (func $func (param i32 i32) (result i32) (local.get 0)) 208 | (func (export "aaa") (result i32) 209 | (block (result i32) 210 | (call $func 211 | (block (result i32) (i32.const 1)) (i32.const 2) 212 | ) 213 | ) 214 | ) 215 | ) 216 | 217 | (assert_return (invoke "aaa") (i32.const 1)) 218 | 219 | (module 220 | (func $2 (export "cool-align-1") (export "cool-align-2") result i32 param i32 i64 param i64 local i32 221 | (local.get 0) 222 | (return) 223 | ) 224 | ) 225 | 226 | (assert_return (invoke "cool-align-1" (i32.const 7) (i64.const 8) (i64.const 3)) (i32.const 7)) 227 | (assert_return (invoke "cool-align-2" (i32.const 1) (i64.const 5) (i64.const 7)) (i32.const 1)) 228 | 229 | #assertFunction 0 [ i32 i64 i64 ] -> [ i32 ] [ i32 ] "out of order type declarations" 230 | 231 | (module 232 | (func (export "foo") (result i32) 233 | (block $a (result i32) 234 | (block $b (result i32) 235 | (call $bar) 236 | (i32.const 0) 237 | (br $b) 238 | ) 239 | (drop) 240 | (i32.const 1) 241 | ) 242 | ) 243 | 244 | (func $bar 245 | (block $b (block $a (br $a))) 246 | ) 247 | ) 248 | 249 | (assert_return (invoke "foo") (i32.const 1)) 250 | 251 | ;; Check type is correctly desugared. 252 | 253 | (module 254 | (func $1 param i64 i64 i64 result i64 local i64 255 | (i64.sub (local.get 2) (i64.add (local.get 0) (local.get 1))) 256 | (local.set 3) 257 | (local.get 3) 258 | (return) 259 | ) 260 | 261 | ( export "export-1" (func $1) ) 262 | 263 | (func $2 param i64 i64 i64 result i64 local i64 264 | (i64.sub (local.get 2) (i64.add (local.get 0) (local.get 1))) 265 | (local.set 3) 266 | (local.get 3) 267 | (return) 268 | ) 269 | ) 270 | 271 | (assert_return (invoke "export-1" (i64.const 100) (i64.const 43) (i64.const 22)) (i64.const -121)) 272 | #assertFunction 0 [ i64 i64 i64 ] -> [ i64 ] [ i64 ] "call function 1 exists" 273 | #assertType 0 [ i64 i64 i64 ] -> [ i64 ] 274 | ;; Check type was only added once. 275 | #assertNextTypeIdx 1 276 | 277 | #clearConfig 278 | -------------------------------------------------------------------------------- /tests/simple/i64.wast: -------------------------------------------------------------------------------- 1 | ;; retrieved from https://github.com/WebAssembly/spec/blob/main/test/core/i64.wast 2 | 3 | (module 4 | (func (export "extend8_s") (param $x i64) (result i64) (i64.extend8_s (local.get $x))) 5 | (func (export "extend16_s") (param $x i64) (result i64) (i64.extend16_s (local.get $x))) 6 | (func (export "extend32_s") (param $x i64) (result i64) (i64.extend32_s (local.get $x))) 7 | ) 8 | 9 | (assert_return (invoke "extend8_s" (i64.const 0)) (i64.const 0)) 10 | (assert_return (invoke "extend8_s" (i64.const 0x7f)) (i64.const 127)) 11 | (assert_return (invoke "extend8_s" (i64.const 0x80)) (i64.const -128)) 12 | (assert_return (invoke "extend8_s" (i64.const 0xff)) (i64.const -1)) 13 | (assert_return (invoke "extend8_s" (i64.const 0x01234567_89abcd_00)) (i64.const 0)) 14 | (assert_return (invoke "extend8_s" (i64.const 0xfedcba98_765432_80)) (i64.const -0x80)) 15 | (assert_return (invoke "extend8_s" (i64.const -1)) (i64.const -1)) 16 | 17 | (assert_return (invoke "extend16_s" (i64.const 0)) (i64.const 0)) 18 | (assert_return (invoke "extend16_s" (i64.const 0x7fff)) (i64.const 32767)) 19 | (assert_return (invoke "extend16_s" (i64.const 0x8000)) (i64.const -32768)) 20 | (assert_return (invoke "extend16_s" (i64.const 0xffff)) (i64.const -1)) 21 | (assert_return (invoke "extend16_s" (i64.const 0x12345678_9abc_0000)) (i64.const 0)) 22 | (assert_return (invoke "extend16_s" (i64.const 0xfedcba98_7654_8000)) (i64.const -0x8000)) 23 | (assert_return (invoke "extend16_s" (i64.const -1)) (i64.const -1)) 24 | 25 | (assert_return (invoke "extend32_s" (i64.const 0)) (i64.const 0)) 26 | (assert_return (invoke "extend32_s" (i64.const 0x7fff)) (i64.const 32767)) 27 | (assert_return (invoke "extend32_s" (i64.const 0x8000)) (i64.const 32768)) 28 | (assert_return (invoke "extend32_s" (i64.const 0xffff)) (i64.const 65535)) 29 | (assert_return (invoke "extend32_s" (i64.const 0x7fffffff)) (i64.const 0x7fffffff)) 30 | (assert_return (invoke "extend32_s" (i64.const 0x80000000)) (i64.const -0x80000000)) 31 | (assert_return (invoke "extend32_s" (i64.const 0xffffffff)) (i64.const -1)) 32 | (assert_return (invoke "extend32_s" (i64.const 0x01234567_00000000)) (i64.const 0)) 33 | (assert_return (invoke "extend32_s" (i64.const 0xfedcba98_80000000)) (i64.const -0x80000000)) 34 | (assert_return (invoke "extend32_s" (i64.const -1)) (i64.const -1)) 35 | 36 | #clearConfig -------------------------------------------------------------------------------- /tests/simple/identifiers.wast: -------------------------------------------------------------------------------- 1 | ;; tests of function identifier names 2 | 3 | (module 4 | (func $oeauth 5 | (param i32 i32) 6 | (result i32) 7 | (local.get 0) 8 | (local.get 1) 9 | (i32.add) 10 | (return) 11 | ) 12 | 13 | (func $023eno!thu324 14 | (param i32 i32) 15 | (result i32) 16 | (local.get 0) 17 | (local.get 1) 18 | (i32.add) 19 | (return) 20 | ) 21 | 22 | (func $02$3e%no!t&hu324 23 | (param i32 i32) 24 | (result i32) 25 | (local.get 0) 26 | (local.get 1) 27 | (i32.add) 28 | (return) 29 | ) 30 | 31 | (func $02$3e%no!t&hu3'24*32++2ao-eunth 32 | (param i32 i32) 33 | (result i32) 34 | (local.get 0) 35 | (local.get 1) 36 | (i32.add) 37 | (return) 38 | ) 39 | 40 | (func $02$3e%no!t&hu3'24*32++2ao-eu//nh? 41 | (param i32 i32) 42 | (result i32) 43 | (local.get 0) 44 | (local.get 1) 45 | (i32.add) 46 | (return) 47 | ) 48 | 49 | (func $aenuth_ae`st|23~423 50 | (param i32 i32) 51 | (result i32) 52 | (local.get 0) 53 | (local.get 1) 54 | (i32.add) 55 | (return) 56 | ) 57 | 58 | (func $bioi::..@@?^ 59 | (param i32 i32) 60 | (result i32) 61 | (local.get 0) 62 | (local.get 1) 63 | (i32.add) 64 | (return) 65 | ) 66 | ) 67 | 68 | #assertFunction 0 [ i32 i32 ] -> [ i32 ] [ ] "simple function name" 69 | #assertFunction 1 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 1" 70 | #assertFunction 2 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 2" 71 | #assertFunction 3 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3" 72 | #assertFunction 4 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3" 73 | #assertFunction 5 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3" 74 | #assertFunction 6 [ i32 i32 ] -> [ i32 ] [ ] "identifier function name 3" 75 | 76 | #clearConfig 77 | -------------------------------------------------------------------------------- /tests/simple/imports.wast: -------------------------------------------------------------------------------- 1 | (module $a 2 | (global (export "g") (export "glob") (mut i32) (i32.const 42)) 3 | (memory (export "m") (export "mem") (data "A")) 4 | (type $t (func )) 5 | (func (export "f") (export "func")) 6 | (func (export "gunc") (param i64) (param i32) (result i32) (local.get 1)) 7 | ) 8 | 9 | (register "m") 10 | 11 | (module 12 | (import "m" "gunc" (func (type $t))) 13 | (memory (import "m" "mem") 1) 14 | (export "x" (global $x)) 15 | (type $t (func (param i64) (param i32) (result i32))) 16 | (func (import "m" "gunc") (type $t)) 17 | (func (import "m" "f")) 18 | (global $x (import "m" "g") (mut i32)) 19 | (import "m" "g" (global (mut i32))) 20 | (func (export "foo") (result i32) (global.get 0)) 21 | (func (export "mod") (global.set 0 (i32.const 10))) 22 | ) 23 | 24 | (assert_return (invoke "foo") (i32.const 42)) 25 | (invoke "mod") 26 | (invoke $a "f") 27 | (assert_return (invoke "foo") (i32.const 10)) 28 | (assert_return (get $a "g") (i32.const 10)) 29 | (assert_return (get "x") (i32.const 10)) 30 | 31 | #clearConfig -------------------------------------------------------------------------------- /tests/simple/integers.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (func (export "add0") (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 0))) 3 | ) 4 | 5 | (assert_return (invoke "add0" (i32.const 123)) (i32.const 123)) 6 | (assert_return (invoke "add0" (i32.const +123)) (i32.const 1_2_3)) 7 | (assert_return (invoke "add0" (i32.const +123)) (i32.const 1_2_3)) 8 | (assert_return (invoke "add0" (i32.const -1_23)) (i32.const -12_3)) 9 | (assert_return (invoke "add0" (i32.const -0x11)) (i32.const -17)) 10 | (assert_return (invoke "add0" (i32.const -0x1_1)) (i32.const -1_7)) 11 | (assert_return (invoke "add0" (i32.const 0xF_FF_F)) (i32.const 65535)) 12 | (assert_return (invoke "add0" (i32.const 0xF_FF_F)) (i32.const 65_535)) 13 | (assert_return (invoke "add0" (i32.const -0xF_F111_1)) (i32.const -16716049)) 14 | (assert_return (invoke "add0" (i32.const -0xAABBCCDD)) (i32.const -0xA_A_B_B_C_C_D_D)) 15 | 16 | #clearConfig 17 | -------------------------------------------------------------------------------- /tests/simple/memory.wast: -------------------------------------------------------------------------------- 1 | ( memory 34) 2 | #assertMemory 0 34 .Int "memory initial 2" 3 | 4 | #clearConfig 5 | 6 | ( memory $a-memory 34) 7 | #assertMemory $a-memory 34 .Int "memory initial 2" 8 | 9 | #clearConfig 10 | 11 | ( memory 4 10 ) 12 | #assertMemory 0 4 10 "memory initial 3" 13 | 14 | #clearConfig 15 | 16 | ( memory $more-memory 4 10 ) 17 | #assertMemory $more-memory 4 10 "memory initial 3" 18 | 19 | #clearConfig 20 | 21 | ( memory $mem 0 10 ) 22 | (memory.size) 23 | #assertTopStack 0 "memory.size 1" 24 | #assertMemory $mem 0 10 "memory ungrown" 25 | 26 | #clearConfig 27 | 28 | ( memory $mem 0 10 ) 29 | (memory.grow (i32.const 10)) 30 | (memory.size) 31 | #assertStack 10 : < i32 > 0 : .ValStack "memory grow" 32 | (memory.grow (i32.const 1)) 33 | #assertTopStack -1 "memory grow" 34 | #assertMemory $mem 10 10 "memory grown" 35 | 36 | #clearConfig 37 | 38 | ( memory #maxMemorySize()) 39 | (memory.grow (i32.const 1)) 40 | #assertTopStack -1 "memory grow max too large" 41 | #assertMemory 0 #maxMemorySize() .Int "memory grow max too large" 42 | 43 | #clearConfig 44 | 45 | ( memory 0 ) 46 | (memory.grow (i32.const #maxMemorySize())) 47 | (memory.size) 48 | #assertStack #maxMemorySize() : < i32 > 0 : .ValStack "memory grow unbounded" 49 | (memory.grow (i32.const 1)) 50 | (memory.size) 51 | #assertStack #maxMemorySize() : < i32 > -1 : .ValStack "memory grow unbounded" 52 | #assertMemory 0 #maxMemorySize() .Int "memory grown unbounded" 53 | 54 | ;; Store and load 55 | 56 | #clearConfig 57 | 58 | (memory 1) 59 | (i32.const 1) 60 | (i64.const 1) 61 | (i64.store offset=2) 62 | #assertMemoryData (3, 1) "store is little endian" 63 | (i32.const 1) 64 | (i64.const 257) 65 | (i64.store8 offset=2) 66 | #assertMemoryData (3, 1) "store8" 67 | (i32.const 1) 68 | (i64.const 65537) 69 | (i64.store16 offset=2) 70 | #assertMemoryData (3, 1) "store16" 71 | (i32.const 1) 72 | (i64.add (i64.const #pow(i32)) (i64.const 1)) 73 | (i64.store16 offset=2) 74 | #assertMemoryData (3, 1) "store32" 75 | #assertMemory 0 1 .Int "" 76 | 77 | #clearConfig 78 | 79 | (memory $foo 0) 80 | (i32.const 0) 81 | (i32.const 0) 82 | (i32.store8) 83 | #assertTrap "store to 0 size memory" 84 | #assertMemory $foo 0 .Int "" 85 | 86 | #clearConfig 87 | 88 | (memory 1) 89 | (i32.const 65535) 90 | (i32.const 1) 91 | (i32.store8) 92 | #assertMemoryData (65535, 1) "store to memory edge" 93 | (i32.const 65535) 94 | (i32.const 1) 95 | (i32.store16) 96 | #assertTrap "store outside of size memory" 97 | #assertMemory 0 1 .Int "" 98 | 99 | #clearConfig 100 | 101 | (memory 1) 102 | (i32.const 15) 103 | (i64.sub (i64.const #pow(i32)) (i64.const 1)) 104 | (i64.store) 105 | (i32.const 15) 106 | (i32.load8_u) 107 | #assertTopStack 255 "load8 unsigned" 108 | (i32.const 15) 109 | (i32.load8_s ) 110 | #assertTopStack -1 "load8 signed" 111 | (i32.const 16) 112 | (i32.load16_u ) 113 | #assertTopStack 65535 "load16 unsigned" 114 | (i32.const 16) 115 | (i32.load16_s ) 116 | #assertTopStack -1 "load16 signed" 117 | (i32.const 15) 118 | (i64.load32_u ) 119 | #assertTopStack 4294967295 "load32 unsigned1" ;; #pow(i32) -Int 1 120 | (i32.const 15) 121 | (i64.load32_s ) 122 | #assertTopStack -1 "load32 signed1" 123 | (i32.const 17) 124 | (i64.load32_u ) 125 | #assertTopStack 65535 "load32 unsigned2" 126 | (i32.const 17) 127 | (i64.load32_u ) 128 | #assertTopStack 65535 "load32 signed2" 129 | #assertMemoryData (15, 255) "" 130 | #assertMemoryData (16, 255) "" 131 | #assertMemoryData (17, 255) "" 132 | #assertMemoryData (18, 255) "" 133 | #assertMemory 0 1 .Int "" 134 | 135 | ;; Updating 136 | 137 | #clearConfig 138 | 139 | (memory 1) 140 | (i32.const 1) 141 | (i64.sub (i64.const #pow(i64)) (i64.const 1)) 142 | (i64.store) 143 | (i32.const 5) (i32.const 0) 144 | (i32.store ) 145 | (i32.const 3) (i32.const 0) 146 | (i32.store16 ) 147 | (i32.const 1) (i32.const 0) 148 | (i32.store8 ) 149 | (i32.const 2) (i32.const 0) 150 | (i32.store8 ) 151 | #assertMemory 0 1 .Int "Zero updates erases memory" 152 | 153 | #clearConfig 154 | 155 | (memory 1) 156 | (i32.const 1) (i64.sub (i64.const #pow(i64)) (i64.const 1)) 157 | (i64.store ) 158 | (i32.const 2) (i32.const 0) 159 | (i32.store8 ) 160 | (i32.const 4) (i32.const 0) 161 | (i32.store ) 162 | #assertMemoryData (1, 255) "" 163 | #assertMemoryData (3, 255) "" 164 | #assertMemoryData (8, 255) "" 165 | #assertMemory 0 1 .Int "Zero updates don't over-erase" 166 | 167 | #clearConfig 168 | 169 | (module 170 | (memory 0) 171 | ) 172 | 173 | (module 174 | (memory (data "A")) 175 | ) 176 | 177 | #assertMemoryData (0, 65) "" 178 | 179 | (module 180 | (memory 1) 181 | (func $start (i32.store (i32.const 0) (i32.const 42))) 182 | (start $start) 183 | ) 184 | 185 | #assertMemoryData 1 (0, 65) "Start didn't modify other memory" 186 | #assertMemoryData (0, 42) "Start function modified its own memory" 187 | 188 | (module 189 | (memory 0) 190 | 191 | (func (export "load_at_zero") (result i32) (i32.load (i32.const 0))) 192 | (func (export "store_at_zero") (i32.store (i32.const 0) (i32.const 2))) 193 | ) 194 | 195 | (assert_trap (invoke "store_at_zero") "out of bounds memory access") 196 | (assert_trap (invoke "load_at_zero") "out of bounds memory access") 197 | 198 | #clearConfig 199 | -------------------------------------------------------------------------------- /tests/simple/modules.wast: -------------------------------------------------------------------------------- 1 | (module $myMod) 2 | 3 | #assertNamedModule $myMod "named empty module" 4 | 5 | (module $anotherName) 6 | 7 | (register "a module name") 8 | 9 | #assertRegistrationNamed "a module name" $anotherName "registration1" 10 | #assertNamedModule $anotherName "named registered module" 11 | 12 | (module $myMod2) 13 | 14 | (module) 15 | 16 | (module $myMod3) 17 | 18 | (register "a module name 2" $myMod2) 19 | (register "another module name" $myMod3) 20 | (register "third module name") 21 | 22 | #assertRegistrationNamed "another module name" $myMod3 "registration3" 23 | #assertRegistrationNamed "a module name 2" $myMod2 "registration4" 24 | #assertRegistrationUnnamed "third module name" "registration5" 25 | 26 | (assert_malformed 27 | (module quote "(func block end $l)") 28 | "mismatching label" 29 | ) 30 | 31 | (assert_malformed 32 | (module quote "(func block $a end $l)") 33 | "mismatching label" 34 | ) 35 | 36 | #clearConfig 37 | 38 | ;; Test ordering of definitions in modules. 39 | 40 | (module 41 | (start $main) ;; Should initialize memory position 1. 42 | (elem (i32.const 1) $store) 43 | (data (i32.const 100) "ba") 44 | (data (i32.const 100) "c") ;; Should overwrite previous, leaving "5 1" as memory bytes 45 | (func) 46 | (func $main (call_indirect (i32.const 1))) ;; Should call $store. 47 | (func $store (i32.store (i32.const 1) (i32.const 42))) 48 | (func $get (export "get") (result i32) 49 | (i32.add (i32.load (i32.const 1)) (i32.load (i32.const 100))) ;; For checking both data initialization. 50 | ) 51 | (memory 10 10) 52 | (elem (i32.const 0) 0) 53 | (table 2 funcref) 54 | ) 55 | 56 | (assert_return (invoke "get") i32.const 24973 ) 57 | 58 | #clearConfig 59 | -------------------------------------------------------------------------------- /tests/simple/polymorphic.wast: -------------------------------------------------------------------------------- 1 | ;; drop 2 | 3 | (i32.const 15) 4 | (drop) 5 | #assertStack .ValStack "drop i32" 6 | 7 | (i64.const 15) 8 | (drop) 9 | #assertStack .ValStack "drop i64" 10 | 11 | (f32.const 15.0) 12 | (drop) 13 | #assertStack .ValStack "drop f32" 14 | 15 | (f64.const 15.0) 16 | (drop) 17 | #assertStack .ValStack "drop f64" 18 | 19 | (i32.const 5) 20 | (drop (i32.const 1)) 21 | #assertTopStack < i32 > 5 "folded drop" 22 | 23 | ;; select 24 | 25 | (i32.const -1) 26 | (i32.const 1) 27 | (i32.const 1) 28 | (select) 29 | #assertTopStack < i32 > -1 "select i32 true" 30 | 31 | (i32.const -1) 32 | (i32.const 1) 33 | (i32.const 0) 34 | (select) 35 | #assertTopStack < i32 > 1 "select i32 false" 36 | 37 | (i64.const -1) 38 | (i64.const 1) 39 | (i32.const 1) 40 | (select) 41 | #assertTopStack < i64 > -1 "select i64 true" 42 | 43 | (i64.const -1) 44 | (i64.const 1) 45 | (i32.const 0) 46 | (select) 47 | #assertTopStack < i64 > 1 "select i64 false" 48 | 49 | (select (i32.const 1) (i32.const 0) (i32.const 1)) 50 | #assertTopStack < i32 > 1 "folded select i32" 51 | 52 | (select (i64.const 1) (i64.const 0) (i32.const 0)) 53 | #assertTopStack < i64 > 0 "folded select i64" 54 | 55 | (select (unreachable) (i64.const -1) (i32.const 0)) 56 | #assertTrap "select strict in first branch" 57 | 58 | (select (i64.const 1) (unreachable) (i32.const 0)) 59 | #assertTrap "select strict in second branch" 60 | #assertTopStack < i64 > 1 "select strict in second branch" 61 | 62 | (select (i64.const 1) (i64.const -1) (unreachable)) 63 | #assertTrap "select strict in condition" 64 | #assertTopStack < i64 > -1 "select strict in condition" 65 | (drop) 66 | #assertTopStack < i64 > 1 "select strict in condition" 67 | 68 | #clearConfig 69 | -------------------------------------------------------------------------------- /tests/simple/start.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 1) 3 | (func $inc 4 | (i32.store8 5 | (i32.const 0) 6 | (i32.add 7 | (i32.load8_u (i32.const 0)) 8 | (i32.const 1))) 9 | ) 10 | (func $main 11 | (i32.store (i32.const 0) (i32.const 65)) 12 | (call $inc) 13 | (call $inc) 14 | (call $inc) 15 | ) 16 | (start $main) 17 | ) 18 | 19 | #assertMemoryData (0, 68) "start inc" 20 | #assertFunction 0 [ ] -> [ ] [ ] "$inc" 21 | #assertFunction 1 [ ] -> [ ] [ ] "$main" 22 | #assertMemory 0 1 .Int "" 23 | 24 | #clearConfig 25 | 26 | (module 27 | (func $foo (unreachable)) 28 | (start $foo) 29 | ) 30 | #assertTrap "Trap propagates through start invocation" 31 | #assertFunction 0 [ ] -> [ ] [ ] "" 32 | 33 | (assert_trap 34 | (module (func $main (unreachable)) (start $main)) 35 | "unreachable" 36 | ) 37 | 38 | #clearConfig 39 | -------------------------------------------------------------------------------- /tests/simple/table.wast: -------------------------------------------------------------------------------- 1 | (module ( table 0 funcref ) ) 2 | #assertTable 0 0 .Int "table initial 1" 3 | 4 | (module ( table $named 4 funcref) ) 5 | #assertTable $named 4 .Int "table initial 2" 6 | 7 | (module ( table 14 21 funcref ) ) 8 | #assertTable 0 14 21 "table initial 3" 9 | 10 | (module ( 11 | table $named2 funcref (elem $f $g $k)) 12 | (func $f) (func $g) (func $k) 13 | ) 14 | #assertTableElem (0, $f) "table elem 0" 15 | #assertTableElem (1, $g) "table elem 1" 16 | #assertTableElem (2, $k) "table elem 2" 17 | #assertTable $named2 3 3 "table one with elements" 18 | 19 | (module 20 | ( elem (i32.const 1) $f $g) 21 | ( table 4 funcref) 22 | (func $f) (func $g) 23 | ) 24 | 25 | #assertTableElem (1, $f) "table elem 1" 26 | #assertTableElem (2, $g) "table elem 2" 27 | #assertTable 0 4 .Int "table two with elements" 28 | 29 | (module 30 | ( elem (i32.const 1) func $f $g) 31 | ( table 4 funcref) 32 | (func $f) (func $g) 33 | ) 34 | 35 | #assertTableElem (1, $f) "table elem 1" 36 | #assertTableElem (2, $g) "table elem 2" 37 | #assertTable 0 4 .Int "table two with elements" 38 | 39 | (module 40 | (type $out-i32 (func (result i32))) 41 | (table $tab 10 funcref) 42 | (elem (i32.const 8) $const-i32-a) 43 | (elem (i32.const 9) $const-i32-b) 44 | (func $const-i32-a (type $out-i32) (i32.const 65)) 45 | (func $const-i32-b (type $out-i32) (i32.const 66)) 46 | (func (export "call-7") (type $out-i32) 47 | (call_indirect (type $out-i32) (i32.const 7)) 48 | ) 49 | (func (export "call-8") (type $out-i32) 50 | (call_indirect (type $out-i32) (i32.const 8)) 51 | ) 52 | (func (export "call-9") (type $out-i32) 53 | (call_indirect (type $out-i32) (i32.const 9)) 54 | ) 55 | ) 56 | 57 | (invoke "call-8") 58 | 59 | #assertTopStack < i32> 65 "call_indirect_result1" 60 | 61 | (invoke "call-9") 62 | 63 | #assertTopStack < i32> 66 "call_indirect_result2" 64 | 65 | #assertFunction 0 [ ] -> [ i32 ] [ ] "call function 1 exists" 66 | #assertFunction 1 [ ] -> [ i32 ] [ ] "call function 2 exists" 67 | #assertFunction 2 [ ] -> [ i32 ] [ ] "call function 3 exists" 68 | #assertFunction 3 [ ] -> [ i32 ] [ ] "call function 4 exists" 69 | #assertFunction 4 [ ] -> [ i32 ] [ ] "call function 5 exists" 70 | #assertTableElem (8, $const-i32-a) "table elem 8" 71 | #assertTableElem (9, $const-i32-b) "table elem 9" 72 | #assertTable $tab 10 .Int "table three with elements" 73 | 74 | ;; Test offset unfolding. 75 | 76 | (module 77 | (table $t 10 funcref) 78 | (type $typ (func)) 79 | (func) 80 | (elem (offset (i32.const 0)) 0) 81 | (elem (offset (nop) (i32.const 1)) 0) 82 | (elem (offset (i32.const 2) (nop)) 0) 83 | (elem (table $t) (offset (i32.const 3)) 0) 84 | (elem (table $t) (offset (nop) (i32.const 4)) 0) 85 | (elem (table $t) (offset (i32.const 5) (nop)) 0) 86 | 87 | (elem (offset (i32.const 6 (nop))) 0) 88 | (elem (table $t) (offset (i32.const 7 (nop))) 0) 89 | 90 | (global $g i32 (i32.const 8)) 91 | (global $h i32 (i32.const 9)) 92 | 93 | (elem (offset (global.get $g)) 0) 94 | (elem (table $t) (offset (global.get $h)) 0) 95 | 96 | (func $main (local i32) 97 | (local.set 0 (i32.const 7)) 98 | loop 99 | (local.get 0) 100 | (call_indirect (type $typ)) 101 | (i32.sub (local.get 0) (i32.const 1)) 102 | (local.tee 0) 103 | (i32.eqz) 104 | (br_if 1) 105 | (br 0) 106 | end 107 | ) 108 | 109 | (start $main) 110 | ) 111 | 112 | #clearConfig 113 | -------------------------------------------------------------------------------- /tests/simple/text2abstract.wast: -------------------------------------------------------------------------------- 1 | (module) 2 | 3 | (module $id 4 | (func (export "foo") (param $a i32) (result i32) 5 | local.get $a 6 | ) 7 | 8 | (func (export "bar") (param $a i32) (result i32) 9 | block (result i32) 10 | local.get $a 11 | end 12 | ) 13 | 14 | (func (export "baz") (param $a i32) (result i32) 15 | loop (result i32) 16 | local.get $a 17 | end 18 | ) 19 | 20 | (func (export "baf") (param $a i32) (result i32) 21 | i32.const 1 22 | if (result i32) 23 | local.get $a 24 | else 25 | local.get $a 26 | end 27 | ) 28 | 29 | (func (export "bag") (param $a i32) (result i32) 30 | i32.const 0 31 | if (result i32) 32 | local.get $a 33 | else 34 | local.get $a 35 | end 36 | ) 37 | 38 | (func $far (param $a i32) (result i32) (local $b i64) 39 | local.get $a 40 | ) 41 | ) 42 | 43 | (assert_return (invoke "foo" (i32.const 7)) (i32.const 7)) 44 | (assert_return (invoke "bar" (i32.const 7)) (i32.const 7)) 45 | (assert_return (invoke "baz" (i32.const 7)) (i32.const 7)) 46 | (assert_return (invoke "baf" (i32.const 7)) (i32.const 7)) 47 | (assert_return (invoke "bag" (i32.const 7)) (i32.const 7)) 48 | 49 | #assertFunction 5 [ i32 ] -> [ i32 ] [ i64 ] "identifiers are erased inside module" 50 | 51 | #clearConfig 52 | 53 | ;; With sugared blocks 54 | 55 | (module $id 56 | 57 | (type $i32->i32 (func (param i32) (result i32))) 58 | 59 | (func (export "foo") (param $a i32) (result i32) 60 | (local.get $a) 61 | ) 62 | 63 | (func (export "bar") (type 0) (param $a i32) (result i32) 64 | (block (result i32) 65 | (local.get $a)) 66 | ) 67 | 68 | (func (export "baz") (type $i32->i32) (param $a i32) (result i32) 69 | (loop (result i32) 70 | (local.get $a)) 71 | ) 72 | 73 | (func (export "baf") (param $a i32) (result i32) 74 | i32.const 1 75 | (if (result i32) 76 | (then (local.get $a)) 77 | (else (local.get $a)) 78 | ) 79 | ) 80 | 81 | (func (export "bag") (param $a i32) (result i32) 82 | i32.const 0 83 | (if (result i32) 84 | (then (local.get $a)) 85 | (else (local.get $a)) 86 | ) 87 | ) 88 | ) 89 | 90 | (assert_return (invoke "foo" (i32.const 7)) (i32.const 7)) 91 | (assert_return (invoke "bar" (i32.const 7)) (i32.const 7)) 92 | (assert_return (invoke "baz" (i32.const 7)) (i32.const 7)) 93 | (assert_return (invoke "baf" (i32.const 7)) (i32.const 7)) 94 | (assert_return (invoke "bag" (i32.const 7)) (i32.const 7)) 95 | 96 | #clearConfig 97 | 98 | (type (func (param i32) (result i32))) 99 | 100 | (func $foo (type 0) (param $a i32) (result i32) 101 | local.get $a 102 | ) 103 | (export "foo" (func 0)) 104 | 105 | (func $bar (type 0) (param $a i32) (result i32) 106 | block (result i32) 107 | local.get $a 108 | end 109 | ) 110 | (export "bar" (func 1)) 111 | 112 | (func $baz (type 0) (param $a i32) (result i32) 113 | loop (result i32) 114 | local.get $a 115 | end 116 | ) 117 | (export "baz" (func 2)) 118 | 119 | (func $baf (type 0) (param $a i32) (result i32) 120 | i32.const 1 121 | if (result i32) 122 | local.get $a 123 | else 124 | local.get $a 125 | end 126 | ) 127 | (export "baf" (func 3)) 128 | 129 | (func $bag (type 0) (param $a i32) (result i32) 130 | i32.const 0 131 | if (result i32) 132 | local.get $a 133 | else 134 | local.get $a 135 | end 136 | ) 137 | (export "bag" (func 4)) 138 | 139 | (func $far (type 0) (param $a i32) (result i32) (local $b i64) 140 | local.get $a 141 | ) 142 | 143 | (assert_return (invoke "foo" (i32.const 7)) (i32.const 7)) 144 | (assert_return (invoke "bar" (i32.const 7)) (i32.const 7)) 145 | (assert_return (invoke "baz" (i32.const 7)) (i32.const 7)) 146 | (assert_return (invoke "baf" (i32.const 7)) (i32.const 7)) 147 | (assert_return (invoke "bag" (i32.const 7)) (i32.const 7)) 148 | 149 | #assertFunction 5 [ i32 ] -> [ i32 ] [ i64 ] "identifiers are erased outside module" 150 | 151 | (type (func)) 152 | 153 | (func $fir (type 1) (local i64) (local $a i32)) 154 | 155 | #assertFunction 6 [ ] -> [ ] [ i64 i32 ] "identifiers are erased inside module" 156 | 157 | #clearConfig 158 | -------------------------------------------------------------------------------- /tests/simple/unicode.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (memory 1) 3 | (data (i32.const 0) "~!@#$%\u{1}\u{11}\u{334}\u{EDFF}\u{BBBBB}\u{10EFEF}") 4 | (func (export "load8_u") (param $i i32) (result i64) 5 | (i64.load8_u offset=0 (local.get $i)) 6 | ) 7 | (func (export "load16_u") (param $i i32) (result i64) 8 | (i64.load16_u offset=0 (local.get $i)) 9 | ) 10 | (func (export "load32_u") (param $i i32) (result i64) 11 | (i64.load32_u offset=0 (local.get $i)) 12 | ) 13 | ) 14 | 15 | (assert_return (invoke "load8_u" (i32.const 0)) (i64.const 126)) 16 | (assert_return (invoke "load8_u" (i32.const 3)) (i64.const 35)) 17 | (assert_return (invoke "load8_u" (i32.const 6)) (i64.const 1)) 18 | (assert_return (invoke "load8_u" (i32.const 9)) (i64.const 180)) 19 | (assert_return (invoke "load8_u" (i32.const 11)) (i64.const 183)) 20 | (assert_return (invoke "load8_u" (i32.const 14)) (i64.const 187)) 21 | (assert_return (invoke "load8_u" (i32.const 15)) (i64.const 174)) 22 | 23 | (assert_return (invoke "load16_u" (i32.const 0)) (i64.const 8574)) 24 | (assert_return (invoke "load16_u" (i32.const 1)) (i64.const 16417)) 25 | (assert_return (invoke "load16_u" (i32.const 2)) (i64.const 9024)) 26 | (assert_return (invoke "load16_u" (i32.const 4)) (i64.const 9508)) 27 | (assert_return (invoke "load16_u" (i32.const 12)) (i64.const 62143)) 28 | (assert_return (invoke "load16_u" (i32.const 13)) (i64.const 48114)) 29 | (assert_return (invoke "load16_u" (i32.const 16)) (i64.const 62651)) 30 | 31 | (assert_return (invoke "load32_u" (i32.const 2)) (i64.const 623125312)) 32 | (assert_return (invoke "load32_u" (i32.const 3)) (i64.const 19211299)) 33 | (assert_return (invoke "load32_u" (i32.const 6)) (i64.const 3033272577)) 34 | (assert_return (invoke "load32_u" (i32.const 7)) (i64.const 4004826129)) 35 | (assert_return (invoke "load32_u" (i32.const 11)) (i64.const 3153248183)) 36 | (assert_return (invoke "load32_u" (i32.const 16)) (i64.const 3213817019)) 37 | (assert_return (invoke "load32_u" (i32.const 19)) (i64.const 44991)) 38 | 39 | #clearConfig 40 | -------------------------------------------------------------------------------- /tests/simple/variables.wast: -------------------------------------------------------------------------------- 1 | ;; Test locals 2 | 3 | init_locals < i32 > 0 : < i32 > 0 : < i32 > 0 : .ValStack 4 | 5 | (i32.const 43) 6 | (local.set 0) 7 | #assertLocal 0 < i32 > 43 "set_local" 8 | 9 | (i32.const 55) 10 | (local.set 1) 11 | (local.get 1) 12 | #assertTopStack < i32 > 55 "set_local stack" 13 | #assertLocal 1 < i32 > 55 "set_local" 14 | 15 | (i32.const 67) 16 | (local.tee 2) 17 | #assertTopStack < i32 > 67 "tee_local stack" 18 | #assertLocal 2 < i32 > 67 "tee_local local" 19 | 20 | ;; Test globals 21 | 22 | (module 23 | (global (mut i32) (i32.const 0)) 24 | (global $someglobal (mut i32) (i32.const 0)) 25 | 26 | (func 27 | (i32.const 43) 28 | (global.set 0) 29 | ) 30 | 31 | (func (export "set") 32 | (i32.const 55) 33 | (global.set $someglobal) 34 | ) 35 | 36 | (start 0) 37 | ) 38 | #assertGlobal 0 < i32 > 43 "set_global" 39 | 40 | (invoke "set") 41 | #assertGlobal $someglobal < i32 > 55 "set_global" 42 | 43 | ;; Test global folded forms 44 | 45 | #clearConfig 46 | 47 | (module 48 | (global (mut i32) (i32.const 0)) 49 | (global (mut i32) (i32.const 0)) 50 | 51 | (func 52 | (global.set 1 (i32.const 99)) 53 | (global.set 0 (i32.const 77)) 54 | ) 55 | 56 | (start 0) 57 | ) 58 | 59 | #assertGlobal 1 < i32 > 99 "set_global folded" 60 | #assertGlobal 0 < i32 > 77 "set_global folded 2" 61 | 62 | #clearConfig 63 | -------------------------------------------------------------------------------- /tests/success-k.out: -------------------------------------------------------------------------------- 1 | 2 | .K 3 | 4 | -------------------------------------------------------------------------------- /tests/success-llvm.out: -------------------------------------------------------------------------------- 1 | 2 | 3 | .K 4 | 5 | 6 | 7 | .K 8 | 9 | 10 | .ValStack 11 | 12 | 13 | 14 | .Map 15 | 16 | 17 | .Int 18 | 19 | 20 | 21 | .Map 22 | 23 | 24 | .Map 25 | 26 | 27 | .ModuleInstCellMap 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | .FuncDefCellMap 35 | 36 | 37 | 0 38 | 39 | 40 | .TabInstCellMap 41 | 42 | 43 | 0 44 | 45 | 46 | .MemInstCellMap 47 | 48 | 49 | 0 50 | 51 | 52 | .GlobalInstCellMap 53 | 54 | 55 | 0 56 | 57 | 58 | .ElemInstCellMap 59 | 60 | 61 | 0 62 | 63 | 64 | 65 | true 66 | 67 | 68 | 69 | --------------------------------------------------------------------------------