├── .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 |
--------------------------------------------------------------------------------