diff --git a/.github/actions/install-cargo-vet/action.yml b/.github/actions/install-cargo-vet/action.yml new file mode 100644 index 000000000000..0d481d744236 --- /dev/null +++ b/.github/actions/install-cargo-vet/action.yml @@ -0,0 +1,20 @@ +name: 'Install the `cargo-vet` tool' +description: 'Runs `cargo install cargo-vet`' + +inputs: + version: + description: 'Version to install' + required: false + default: '0.8.0' + +runs: + using: composite + steps: + - uses: actions/cache@v3 + with: + path: ${{ runner.tool_cache }}/cargo-vet + key: cargo-vet-bin-${{ inputs.version }} + - run: echo "${{ runner.tool_cache }}/cargo-vet/bin" >> $GITHUB_PATH + shell: bash + - run: cargo install --root ${{ runner.tool_cache }}/cargo-vet --version ${{ inputs.version }} cargo-vet + shell: bash diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d9800b7de6dd..4f155f96acab 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,19 +86,12 @@ jobs: needs: determine if: needs.determine.outputs.audit runs-on: ubuntu-latest - env: - CARGO_VET_VERSION: 0.8.0 steps: - uses: actions/checkout@v3 with: submodules: true - uses: ./.github/actions/install-rust - - uses: actions/cache@v3 - with: - path: ${{ runner.tool_cache }}/cargo-vet - key: cargo-vet-bin-${{ env.CARGO_VET_VERSION }} - - run: echo "${{ runner.tool_cache }}/cargo-vet/bin" >> $GITHUB_PATH - - run: cargo install --root ${{ runner.tool_cache }}/cargo-vet --version ${{ env.CARGO_VET_VERSION }} cargo-vet + - uses: ./.github/actions/install-cargo-vet - run: cargo vet --locked # common logic to cancel the entire run if this job fails @@ -194,7 +187,7 @@ jobs: submodules: true - uses: ./.github/actions/install-rust with: - toolchain: nightly-2023-03-20 + toolchain: nightly-2023-07-02 # Build C API documentation - run: curl -L https://sourceforge.net/projects/doxygen/files/rel-1.9.3/doxygen-1.9.3.linux.bin.tar.gz/download | tar xzf - @@ -353,7 +346,7 @@ jobs: # flags to rustc. - uses: ./.github/actions/install-rust with: - toolchain: nightly-2023-03-20 + toolchain: nightly-2023-07-02 - run: cargo install cargo-fuzz --vers "^0.11" # Install the OCaml packages necessary for fuzz targets that use the # `wasm-spec-interpreter`. @@ -651,7 +644,7 @@ jobs: submodules: true - uses: ./.github/actions/install-rust with: - toolchain: nightly-2023-03-20 + toolchain: nightly-2023-07-02 - run: rustup component add rust-src miri - uses: actions/cache@v3 with: diff --git a/.github/workflows/release-process.yml b/.github/workflows/release-process.yml index f1361ce89038..8e6a5e5855a7 100644 --- a/.github/workflows/release-process.yml +++ b/.github/workflows/release-process.yml @@ -48,6 +48,9 @@ jobs: git config user.email 'wasmtime-publish@users.noreply.github.com' git remote set-url origin https://git:${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/${{ github.repository }} + - uses: ./.github/actions/install-rust + - uses: ./.github/actions/install-cargo-vet + - name: Bump major version number run: | set -ex @@ -66,6 +69,9 @@ jobs: cat backup-releases >> RELEASES.md rm backup-releases + # Update `cargo vet` entries for all the new crate versions + cargo vet + # Commit all of the above changes. git commit -am "Bump Wasmtime to $num" diff --git a/Cargo.lock b/Cargo.lock index 7f10bf74ffe9..51a2da36da64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,7 +236,7 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "byte-array-literals" -version = "11.0.0" +version = "12.0.0" [[package]] name = "byteorder" @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "cranelift" -version = "0.98.0" +version = "0.99.0" dependencies = [ "cranelift-codegen", "cranelift-frontend", @@ -602,14 +602,14 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.98.0" +version = "0.99.0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.98.0" +version = "0.99.0" dependencies = [ "anyhow", "bincode", @@ -636,25 +636,25 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.98.0" +version = "0.99.0" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.98.0" +version = "0.99.0" [[package]] name = "cranelift-control" -version = "0.98.0" +version = "0.99.0" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.98.0" +version = "0.99.0" dependencies = [ "serde", ] @@ -691,7 +691,7 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.98.0" +version = "0.99.0" dependencies = [ "cranelift-codegen", "hashbrown 0.13.2", @@ -715,7 +715,7 @@ dependencies = [ [[package]] name = "cranelift-interpreter" -version = "0.98.0" +version = "0.99.0" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -729,7 +729,7 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.98.0" +version = "0.99.0" dependencies = [ "codespan-reporting", "log", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.98.0" +version = "0.99.0" dependencies = [ "anyhow", "cranelift", @@ -759,7 +759,7 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.98.0" +version = "0.99.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -770,7 +770,7 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.98.0" +version = "0.99.0" dependencies = [ "cranelift-codegen", "libc", @@ -779,7 +779,7 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.98.0" +version = "0.99.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -794,7 +794,7 @@ dependencies = [ [[package]] name = "cranelift-reader" -version = "0.98.0" +version = "0.99.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -804,7 +804,7 @@ dependencies = [ [[package]] name = "cranelift-serde" -version = "0.98.0" +version = "0.99.0" dependencies = [ "clap", "cranelift-codegen", @@ -851,7 +851,7 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.98.0" +version = "0.99.0" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -2422,9 +2422,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] @@ -3404,20 +3404,19 @@ dependencies = [ [[package]] name = "v8" -version = "0.44.3" +version = "0.74.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f92c29dd66c7342443280695afc5bb79d773c3aa3eb02978cf24f058ae2b3d" +checksum = "1202e0bd078112bf8d521491560645e1fd6955c4afd975c75b05596a7e7e4eea" dependencies = [ "bitflags 1.3.2", "fslock", - "lazy_static", - "libc", + "once_cell", "which", ] [[package]] name = "verify-component-adapter" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "wasmparser 0.92.0", @@ -3473,7 +3472,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-cap-std-sync" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "async-trait", @@ -3496,7 +3495,7 @@ dependencies = [ [[package]] name = "wasi-common" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "bitflags 1.3.2", @@ -3551,7 +3550,7 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter" -version = "11.0.0" +version = "12.0.0" dependencies = [ "byte-array-literals", "object", @@ -3571,7 +3570,7 @@ dependencies = [ [[package]] name = "wasi-tokio" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "cap-std", @@ -3794,7 +3793,7 @@ dependencies = [ [[package]] name = "wasmtime" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "async-trait", @@ -3834,14 +3833,14 @@ dependencies = [ [[package]] name = "wasmtime-asm-macros" -version = "11.0.0" +version = "12.0.0" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-bench-api" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "cap-std", @@ -3859,7 +3858,7 @@ dependencies = [ [[package]] name = "wasmtime-c-api" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "cap-std", @@ -3883,7 +3882,7 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "base64", @@ -3905,7 +3904,7 @@ dependencies = [ [[package]] name = "wasmtime-cli" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "async-trait", @@ -3955,7 +3954,7 @@ dependencies = [ [[package]] name = "wasmtime-cli-flags" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "clap", @@ -3967,7 +3966,7 @@ dependencies = [ [[package]] name = "wasmtime-component-macro" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "component-macro-test-helpers", @@ -3983,11 +3982,11 @@ dependencies = [ [[package]] name = "wasmtime-component-util" -version = "11.0.0" +version = "12.0.0" [[package]] name = "wasmtime-cranelift" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -4004,11 +4003,12 @@ dependencies = [ "wasmparser 0.107.0 (git+https://github.com/effect-handlers/wasm-tools?branch=typed-continuations)", "wasmtime-cranelift-shared", "wasmtime-environ", + "wasmtime-versioned-export-macros", ] [[package]] name = "wasmtime-cranelift-shared" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -4022,7 +4022,7 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "atty", @@ -4060,7 +4060,7 @@ dependencies = [ [[package]] name = "wasmtime-explorer" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "capstone", @@ -4073,19 +4073,20 @@ dependencies = [ [[package]] name = "wasmtime-fiber" -version = "11.0.0" +version = "12.0.0" dependencies = [ "backtrace", "cc", "cfg-if", "rustix", "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", "windows-sys 0.48.0", ] [[package]] name = "wasmtime-fibre" -version = "11.0.0" +version = "12.0.0" dependencies = [ "backtrace", "cc", @@ -4152,7 +4153,7 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "11.0.0" +version = "12.0.0" dependencies = [ "addr2line", "anyhow", @@ -4176,16 +4177,17 @@ dependencies = [ [[package]] name = "wasmtime-jit-debug" -version = "11.0.0" +version = "12.0.0" dependencies = [ "object", "once_cell", "rustix", + "wasmtime-versioned-export-macros", ] [[package]] name = "wasmtime-jit-icache-coherence" -version = "11.0.0" +version = "12.0.0" dependencies = [ "cfg-if", "libc", @@ -4194,7 +4196,7 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "cc", @@ -4216,12 +4218,13 @@ dependencies = [ "wasmtime-fiber", "wasmtime-fibre", "wasmtime-jit-debug", + "wasmtime-versioned-export-macros", "windows-sys 0.48.0", ] [[package]] name = "wasmtime-types" -version = "11.0.0" +version = "12.0.0" dependencies = [ "cranelift-entity", "serde", @@ -4229,9 +4232,18 @@ dependencies = [ "wasmparser 0.107.0 (git+https://github.com/effect-handlers/wasm-tools?branch=typed-continuations)", ] +[[package]] +name = "wasmtime-versioned-export-macros" +version = "12.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "wasmtime-wasi" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "async-trait", @@ -4257,7 +4269,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-crypto" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "wasi-crypto", @@ -4267,7 +4279,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-http" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "bytes", @@ -4285,7 +4297,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-nn" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "openvino", @@ -4296,7 +4308,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-threads" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "log", @@ -4308,7 +4320,7 @@ dependencies = [ [[package]] name = "wasmtime-wast" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "log", @@ -4318,7 +4330,7 @@ dependencies = [ [[package]] name = "wasmtime-winch" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -4333,7 +4345,7 @@ dependencies = [ [[package]] name = "wasmtime-wit-bindgen" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "heck", @@ -4413,7 +4425,7 @@ dependencies = [ [[package]] name = "wiggle" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "async-trait", @@ -4430,7 +4442,7 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "11.0.0" +version = "12.0.0" dependencies = [ "anyhow", "heck", @@ -4443,7 +4455,7 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "11.0.0" +version = "12.0.0" dependencies = [ "proc-macro2", "quote", @@ -4498,7 +4510,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "0.9.0" +version = "0.10.0" dependencies = [ "anyhow", "cranelift-codegen", diff --git a/Cargo.toml b/Cargo.toml index a3187fd65b88..767ff64fc418 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,64 +117,65 @@ exclude = [ ] [workspace.package] -version = "11.0.0" +version = "12.0.0" authors = ["The Wasmtime Project Developers"] edition = "2021" rust-version = "1.66.0" [workspace.dependencies] -wasmtime = { path = "crates/wasmtime", version = "11.0.0", default-features = false } -wasmtime-cache = { path = "crates/cache", version = "=11.0.0" } -wasmtime-cli-flags = { path = "crates/cli-flags", version = "=11.0.0" } -wasmtime-cranelift = { path = "crates/cranelift", version = "=11.0.0" } -wasmtime-cranelift-shared = { path = "crates/cranelift-shared", version = "=11.0.0" } -wasmtime-winch = { path = "crates/winch", version = "=11.0.0" } -wasmtime-environ = { path = "crates/environ", version = "=11.0.0" } -wasmtime-explorer = { path = "crates/explorer", version = "=11.0.0" } -wasmtime-fiber = { path = "crates/fiber", version = "=11.0.0" } -wasmtime-fibre = { path = "crates/fibre", version = "=11.0.0" } -wasmtime-types = { path = "crates/types", version = "11.0.0" } -wasmtime-jit = { path = "crates/jit", version = "=11.0.0" } -wasmtime-jit-debug = { path = "crates/jit-debug", version = "=11.0.0" } -wasmtime-runtime = { path = "crates/runtime", version = "=11.0.0" } -wasmtime-wast = { path = "crates/wast", version = "=11.0.0" } -wasmtime-wasi = { path = "crates/wasi", version = "11.0.0" } -wasmtime-wasi-crypto = { path = "crates/wasi-crypto", version = "11.0.0" } -wasmtime-wasi-http = { path = "crates/wasi-http", version = "=11.0.0" } -wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "11.0.0" } -wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "11.0.0" } -wasmtime-component-util = { path = "crates/component-util", version = "=11.0.0" } -wasmtime-component-macro = { path = "crates/component-macro", version = "=11.0.0" } -wasmtime-asm-macros = { path = "crates/asm-macros", version = "=11.0.0" } +wasmtime = { path = "crates/wasmtime", version = "12.0.0", default-features = false } +wasmtime-cache = { path = "crates/cache", version = "=12.0.0" } +wasmtime-cli-flags = { path = "crates/cli-flags", version = "=12.0.0" } +wasmtime-cranelift = { path = "crates/cranelift", version = "=12.0.0" } +wasmtime-cranelift-shared = { path = "crates/cranelift-shared", version = "=12.0.0" } +wasmtime-winch = { path = "crates/winch", version = "=12.0.0" } +wasmtime-environ = { path = "crates/environ", version = "=12.0.0" } +wasmtime-explorer = { path = "crates/explorer", version = "=12.0.0" } +wasmtime-fiber = { path = "crates/fiber", version = "=12.0.0" } +wasmtime-fibre = { path = "crates/fibre", version = "=12.0.0" } +wasmtime-types = { path = "crates/types", version = "12.0.0" } +wasmtime-jit = { path = "crates/jit", version = "=12.0.0" } +wasmtime-jit-debug = { path = "crates/jit-debug", version = "=12.0.0" } +wasmtime-runtime = { path = "crates/runtime", version = "=12.0.0" } +wasmtime-wast = { path = "crates/wast", version = "=12.0.0" } +wasmtime-wasi = { path = "crates/wasi", version = "12.0.0" } +wasmtime-wasi-crypto = { path = "crates/wasi-crypto", version = "12.0.0" } +wasmtime-wasi-http = { path = "crates/wasi-http", version = "=12.0.0" } +wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "12.0.0" } +wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "12.0.0" } +wasmtime-component-util = { path = "crates/component-util", version = "=12.0.0" } +wasmtime-component-macro = { path = "crates/component-macro", version = "=12.0.0" } +wasmtime-asm-macros = { path = "crates/asm-macros", version = "=12.0.0" } +wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=12.0.0" } component-test-util = { path = "crates/misc/component-test-util" } component-fuzz-util = { path = "crates/misc/component-fuzz-util" } -wiggle = { path = "crates/wiggle", version = "=11.0.0", default-features = false } -wiggle-macro = { path = "crates/wiggle/macro", version = "=11.0.0" } -wiggle-generate = { path = "crates/wiggle/generate", version = "=11.0.0" } -wasi-common = { path = "crates/wasi-common", version = "=11.0.0" } -wasi-tokio = { path = "crates/wasi-common/tokio", version = "=11.0.0" } -wasi-cap-std-sync = { path = "crates/wasi-common/cap-std-sync", version = "=11.0.0" } +wiggle = { path = "crates/wiggle", version = "=12.0.0", default-features = false } +wiggle-macro = { path = "crates/wiggle/macro", version = "=12.0.0" } +wiggle-generate = { path = "crates/wiggle/generate", version = "=12.0.0" } +wasi-common = { path = "crates/wasi-common", version = "=12.0.0" } +wasi-tokio = { path = "crates/wasi-common/tokio", version = "=12.0.0" } +wasi-cap-std-sync = { path = "crates/wasi-common/cap-std-sync", version = "=12.0.0" } wasmtime-fuzzing = { path = "crates/fuzzing" } -wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=11.0.0" } -wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=11.0.0" } +wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=12.0.0" } +wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=12.0.0" } -cranelift-wasm = { path = "cranelift/wasm", version = "0.98.0" } -cranelift-codegen = { path = "cranelift/codegen", version = "0.98.0" } -cranelift-frontend = { path = "cranelift/frontend", version = "0.98.0" } -cranelift-entity = { path = "cranelift/entity", version = "0.98.0" } -cranelift-native = { path = "cranelift/native", version = "0.98.0" } -cranelift-module = { path = "cranelift/module", version = "0.98.0" } -cranelift-interpreter = { path = "cranelift/interpreter", version = "0.98.0" } -cranelift-reader = { path = "cranelift/reader", version = "0.98.0" } +cranelift-wasm = { path = "cranelift/wasm", version = "0.99.0" } +cranelift-codegen = { path = "cranelift/codegen", version = "0.99.0" } +cranelift-frontend = { path = "cranelift/frontend", version = "0.99.0" } +cranelift-entity = { path = "cranelift/entity", version = "0.99.0" } +cranelift-native = { path = "cranelift/native", version = "0.99.0" } +cranelift-module = { path = "cranelift/module", version = "0.99.0" } +cranelift-interpreter = { path = "cranelift/interpreter", version = "0.99.0" } +cranelift-reader = { path = "cranelift/reader", version = "0.99.0" } cranelift-filetests = { path = "cranelift/filetests" } -cranelift-object = { path = "cranelift/object", version = "0.98.0" } -cranelift-jit = { path = "cranelift/jit", version = "0.98.0" } +cranelift-object = { path = "cranelift/object", version = "0.99.0" } +cranelift-jit = { path = "cranelift/jit", version = "0.99.0" } cranelift-fuzzgen = { path = "cranelift/fuzzgen" } -cranelift-bforest = { path = "cranelift/bforest", version = "0.98.0" } -cranelift-control = { path = "cranelift/control", version = "0.98.0" } -cranelift = { path = "cranelift/umbrella", version = "0.98.0" } +cranelift-bforest = { path = "cranelift/bforest", version = "0.99.0" } +cranelift-control = { path = "cranelift/control", version = "0.99.0" } +cranelift = { path = "cranelift/umbrella", version = "0.99.0" } -winch-codegen = { path = "winch/codegen", version = "=0.9.0" } +winch-codegen = { path = "winch/codegen", version = "=0.10.0" } winch-filetests = { path = "winch/filetests" } winch-test-macros = { path = "winch/test-macros" } diff --git a/RELEASES.md b/RELEASES.md index ef05439d9b5a..c69e15582c01 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,5 +1,15 @@ -------------------------------------------------------------------------------- +## 12.0.0 + +Unreleased. + +### Added + +### Changed + +-------------------------------------------------------------------------------- + ## 11.0.0 Unreleased. diff --git a/build.rs b/build.rs index f8cec9fc4afb..0c9fa0cc0721 100644 --- a/build.rs +++ b/build.rs @@ -18,9 +18,13 @@ fn main() -> anyhow::Result<()> { ); let mut out = String::new(); - for strategy in &["Cranelift"] { + for strategy in &["Cranelift", "Winch"] { writeln!(out, "#[cfg(test)]")?; writeln!(out, "#[allow(non_snake_case)]")?; + if *strategy == "Winch" { + // We only test Winch on x86_64, for now. + writeln!(out, "{}", "#[cfg(all(target_arch = \"x86_64\"))]")?; + } writeln!(out, "mod {} {{", strategy)?; with_test_module(&mut out, "misc", |out| { @@ -32,6 +36,7 @@ fn main() -> anyhow::Result<()> { test_directory_module(out, "tests/misc_testsuite/component-model", strategy)?; test_directory_module(out, "tests/misc_testsuite/function-references", strategy)?; test_directory_module(out, "tests/misc_testsuite/typed-continuations", strategy)?; + test_directory_module(out, "tests/misc_testsuite/winch", strategy)?; Ok(()) })?; @@ -187,7 +192,22 @@ fn write_testsuite_tests( /// Ignore tests that aren't supported yet. fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool { - assert_eq!(strategy, "Cranelift"); + assert!(strategy == "Cranelift" || strategy == "Winch"); + + // Ignore everything except the winch misc test suite. + // We ignore tests that assert for traps on windows, given + // that Winch doesn't encode unwind information for Windows, yet. + if strategy == "Winch" { + if testsuite != "winch" { + return true; + } + + let assert_trap = ["i32", "i64"].contains(&testname); + + if assert_trap && env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() == "windows" { + return true; + } + } // This is an empty file right now which the `wast` crate doesn't parse if testname.contains("memory_copy1") { diff --git a/cranelift/bforest/Cargo.toml b/cranelift/bforest/Cargo.toml index f452fe33680d..008e295bfb03 100644 --- a/cranelift/bforest/Cargo.toml +++ b/cranelift/bforest/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-bforest" -version = "0.98.0" +version = "0.99.0" description = "A forest of B+-trees" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-bforest" diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index 1a9c3b9da069..7ad2f9226aeb 100644 --- a/cranelift/codegen/Cargo.toml +++ b/cranelift/codegen/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-codegen" -version = "0.98.0" +version = "0.99.0" description = "Low-level code generator library" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-codegen" @@ -16,7 +16,7 @@ edition.workspace = true anyhow = { workspace = true, optional = true } bumpalo = "3" capstone = { workspace = true, optional = true } -cranelift-codegen-shared = { path = "./shared", version = "0.98.0" } +cranelift-codegen-shared = { path = "./shared", version = "0.99.0" } cranelift-entity = { workspace = true } cranelift-bforest = { workspace = true } cranelift-control = { workspace = true } @@ -40,8 +40,8 @@ criterion = { version = "0.4.0", features = ["html_reports"] } similar = "2.1.0" [build-dependencies] -cranelift-codegen-meta = { path = "meta", version = "0.98.0" } -cranelift-isle = { path = "../isle/isle", version = "=0.98.0" } +cranelift-codegen-meta = { path = "meta", version = "0.99.0" } +cranelift-isle = { path = "../isle/isle", version = "=0.99.0" } [features] default = ["std", "unwind", "host-arch"] diff --git a/cranelift/codegen/meta/Cargo.toml b/cranelift/codegen/meta/Cargo.toml index 499f141da9c0..9c6b1bbf9f3e 100644 --- a/cranelift/codegen/meta/Cargo.toml +++ b/cranelift/codegen/meta/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cranelift-codegen-meta" authors = ["The Cranelift Project Developers"] -version = "0.98.0" +version = "0.99.0" description = "Metaprogram for cranelift-codegen code generator library" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" @@ -13,4 +13,4 @@ edition.workspace = true # rustdoc-args = [ "--document-private-items" ] [dependencies] -cranelift-codegen-shared = { path = "../shared", version = "0.98.0" } +cranelift-codegen-shared = { path = "../shared", version = "0.99.0" } diff --git a/cranelift/codegen/shared/Cargo.toml b/cranelift/codegen/shared/Cargo.toml index b4c4ee7e1afe..6137d0d2f357 100644 --- a/cranelift/codegen/shared/Cargo.toml +++ b/cranelift/codegen/shared/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-codegen-shared" -version = "0.98.0" +version = "0.99.0" description = "For code shared between cranelift-codegen-meta and cranelift-codegen" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/codegen/src/isa/riscv64/inst.isle b/cranelift/codegen/src/isa/riscv64/inst.isle index e4ab3354e06f..498086e7ea9f 100644 --- a/cranelift/codegen/src/isa/riscv64/inst.isle +++ b/cranelift/codegen/src/isa/riscv64/inst.isle @@ -1717,6 +1717,40 @@ (rv_or (value_regs_get x 0) (value_regs_get y 0))) + +(decl gen_bswap (Type XReg) XReg) + +;; This is only here to make the rule below work. bswap.i8 isn't valid +(rule 0 (gen_bswap $I8 x) x) + +(rule 1 (gen_bswap (ty_int_ref_16_to_64 ty) x) + (if-let half_ty (ty_half_width ty)) + (if-let half_size (u64_to_imm12 (ty_bits half_ty))) + (let (;; This swaps the top bytes and zeroes the bottom bytes, so that + ;; we can or it with the bottom bytes later. + (swap_top XReg (gen_bswap half_ty x)) + (top XReg (rv_slli swap_top half_size)) + + ;; Get the top half, swap it, and zero extend it so we can `or` it + ;; with the bottom half. + (shifted XReg (rv_srli x half_size)) + (swap_bot XReg (gen_bswap half_ty shifted)) + (bot XReg (zext swap_bot half_ty $I64))) + (rv_or top bot))) + +;; With `zbb` we can use `rev8` and shift the result +(rule 2 (gen_bswap (int_fits_in_32 ty) x) + (if-let $true (has_zbb)) + (if-let shift_amt (u64_to_imm12 (u64_sub 64 (ty_bits ty)))) + (rv_srli (rv_rev8 x) shift_amt)) + +;; With `zbb` we can use `rev8` that does this +(rule 3 (gen_bswap $I64 x) + (if-let $true (has_zbb)) + (rv_rev8 x)) + + + (decl lower_bit_reverse (Reg Type) Reg) (rule diff --git a/cranelift/codegen/src/isa/riscv64/lower.isle b/cranelift/codegen/src/isa/riscv64/lower.isle index ae65b21a4aca..74adb15d8ec0 100644 --- a/cranelift/codegen/src/isa/riscv64/lower.isle +++ b/cranelift/codegen/src/isa/riscv64/lower.isle @@ -679,6 +679,15 @@ (hi_rev XReg (lower_bit_reverse (value_regs_get val 1) $I64))) (value_regs hi_rev lo_rev))) +;;;; Rules for `bswap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(rule 1 (lower (has_type (fits_in_64 (ty_int ty)) (bswap x))) + (gen_bswap ty x)) + +(rule 2 (lower (has_type $I128 (bswap x))) + (value_regs + (gen_bswap $I64 (value_regs_get x 1)) + (gen_bswap $I64 (value_regs_get x 0)))) + ;;;; Rules for `ctz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (has_type (fits_in_64 ty) (ctz x))) diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle index 250397f9a48a..3c36f64c44ac 100644 --- a/cranelift/codegen/src/isa/x64/lower.isle +++ b/cranelift/codegen/src/isa/x64/lower.isle @@ -4395,6 +4395,7 @@ (x64_vpbroadcastb (bitcast_gpr_to_xmm $I32 src))) (rule 3 (lower (has_type $I8X16 (splat (sinkable_load_exact addr)))) (if-let $true (use_sse41)) + (if-let $true (use_ssse3)) (x64_pshufb (x64_pinsrb (xmm_uninit_value) addr 0) (xmm_zero $I8X16))) (rule 4 (lower (has_type $I8X16 (splat (sinkable_load_exact addr)))) (if-let $true (use_avx2)) diff --git a/cranelift/codegen/src/opts/cprop.isle b/cranelift/codegen/src/opts/cprop.isle index 79c88d8a3a32..338c694b0449 100644 --- a/cranelift/codegen/src/opts/cprop.isle +++ b/cranelift/codegen/src/opts/cprop.isle @@ -70,6 +70,9 @@ (iconst _ k2))) (subsume (iconst ty (imm64_sshr ty k1 k2)))) +(rule (simplify (ireduce narrow (iconst (fits_in_64 _) (u64_from_imm64 imm)))) + (subsume (iconst narrow (imm64_masked narrow imm)))) + (rule (simplify (uextend (fits_in_64 wide) (iconst narrow imm))) (subsume (iconst wide (imm64 (u64_uextend_imm64 narrow imm))))) diff --git a/cranelift/control/Cargo.toml b/cranelift/control/Cargo.toml index 1ca59d9afe4a..0cd32a45733e 100644 --- a/cranelift/control/Cargo.toml +++ b/cranelift/control/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-control" -version = "0.98.0" +version = "0.99.0" description = "White-box fuzz testing framework" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/entity/Cargo.toml b/cranelift/entity/Cargo.toml index ac15a4e729c3..b1383a03d4c4 100644 --- a/cranelift/entity/Cargo.toml +++ b/cranelift/entity/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-entity" -version = "0.98.0" +version = "0.99.0" description = "Data structures using entity references as mapping keys" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-entity" diff --git a/cranelift/filetests/filetests/egraph/cprop.clif b/cranelift/filetests/filetests/egraph/cprop.clif index dc781a79a9ef..e9fef8ca8707 100644 --- a/cranelift/filetests/filetests/egraph/cprop.clif +++ b/cranelift/filetests/filetests/egraph/cprop.clif @@ -230,3 +230,33 @@ block0: ; check: v3 = iconst.i8 0 ; nextln: return v3 + +function %ireduce_iconst() -> i8 { +block0: + v1 = iconst.i16 -10 + v2 = ireduce.i8 v1 + return v2 +} + +; check: v3 = iconst.i8 246 +; nextln: return v3 + +function %sextend_iconst() -> i32 { +block0: + v1 = iconst.i16 -10 + v2 = sextend.i32 v1 + return v2 +} + +; check: v3 = iconst.i32 0xffff_fff6 +; nextln: return v3 + +function %uextend_iconst() -> i32 { +block0: + v1 = iconst.i16 0xfff6 + v2 = uextend.i32 v1 + return v2 +} + +; check: v3 = iconst.i32 0xfff6 +; nextln: return v3 diff --git a/cranelift/filetests/filetests/isa/riscv64/bswap-zbb.clif b/cranelift/filetests/filetests/isa/riscv64/bswap-zbb.clif new file mode 100644 index 000000000000..1de389278285 --- /dev/null +++ b/cranelift/filetests/filetests/isa/riscv64/bswap-zbb.clif @@ -0,0 +1,76 @@ +test compile precise-output +set unwind_info=false +target riscv64 has_zbb + +function %bswap_i16(i16) -> i16 { +block0(v0: i16): + v1 = bswap v0 + return v1 +} + +; VCode: +; block0: +; rev8 t2,a0 +; srli a0,t2,48 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; .byte 0x93, 0x53, 0x85, 0x6b +; srli a0, t2, 0x30 +; ret + +function %bswap_i32(i32) -> i32 { +block0(v0: i32): + v1 = bswap v0 + return v1 +} + +; VCode: +; block0: +; rev8 t2,a0 +; srli a0,t2,32 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; .byte 0x93, 0x53, 0x85, 0x6b +; srli a0, t2, 0x20 +; ret + +function %bswap_i64(i64) -> i64 { +block0(v0: i64): + v1 = bswap v0 + return v1 +} + +; VCode: +; block0: +; rev8 a0,a0 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; .byte 0x13, 0x55, 0x85, 0x6b +; ret + +function %bswap_i128(i128) -> i128 { +block0(v0: i128): + v1 = bswap v0 + return v1 +} + +; VCode: +; block0: +; mv a3,a0 +; rev8 a0,a1 +; rev8 a1,a3 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; ori a3, a0, 0 +; .byte 0x13, 0xd5, 0x85, 0x6b +; .byte 0x93, 0xd5, 0x86, 0x6b +; ret + diff --git a/cranelift/filetests/filetests/isa/riscv64/bswap.clif b/cranelift/filetests/filetests/isa/riscv64/bswap.clif new file mode 100644 index 000000000000..05e74875b82a --- /dev/null +++ b/cranelift/filetests/filetests/isa/riscv64/bswap.clif @@ -0,0 +1,307 @@ +test compile precise-output +set unwind_info=false +target riscv64 + +function %bswap_i16(i16) -> i16 { +block0(v0: i16): + v1 = bswap v0 + return v1 +} + +; VCode: +; block0: +; slli t2,a0,8 +; srli a1,a0,8 +; andi a3,a1,255 +; or a0,t2,a3 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; slli t2, a0, 8 +; srli a1, a0, 8 +; andi a3, a1, 0xff +; or a0, t2, a3 +; ret + +function %bswap_i32(i32) -> i32 { +block0(v0: i32): + v1 = bswap v0 + return v1 +} + +; VCode: +; block0: +; slli t2,a0,8 +; srli a1,a0,8 +; andi a3,a1,255 +; or a5,t2,a3 +; slli a7,a5,16 +; srli t4,a0,16 +; slli t1,t4,8 +; srli a0,t4,8 +; andi a2,a0,255 +; or a4,t1,a2 +; slli a6,a4,48 +; srli t3,a6,48 +; or a0,a7,t3 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; slli t2, a0, 8 +; srli a1, a0, 8 +; andi a3, a1, 0xff +; or a5, t2, a3 +; slli a7, a5, 0x10 +; srli t4, a0, 0x10 +; slli t1, t4, 8 +; srli a0, t4, 8 +; andi a2, a0, 0xff +; or a4, t1, a2 +; slli a6, a4, 0x30 +; srli t3, a6, 0x30 +; or a0, a7, t3 +; ret + +function %bswap_i64(i64) -> i64 { +block0(v0: i64): + v1 = bswap v0 + return v1 +} + +; VCode: +; block0: +; slli t2,a0,8 +; srli a1,a0,8 +; andi a3,a1,255 +; or a5,t2,a3 +; slli a7,a5,16 +; srli t4,a0,16 +; slli t1,t4,8 +; srli a1,t4,8 +; andi a2,a1,255 +; or a4,t1,a2 +; slli a6,a4,48 +; srli t3,a6,48 +; or t0,a7,t3 +; slli t2,t0,32 +; srli a1,a0,32 +; slli a3,a1,8 +; srli a5,a1,8 +; andi a7,a5,255 +; or t4,a3,a7 +; slli t1,t4,16 +; srli a0,a1,16 +; slli a2,a0,8 +; srli a4,a0,8 +; andi a6,a4,255 +; or t3,a2,a6 +; slli t0,t3,48 +; srli a0,t0,48 +; or a1,t1,a0 +; slli a3,a1,32 +; srli a5,a3,32 +; or a0,t2,a5 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; slli t2, a0, 8 +; srli a1, a0, 8 +; andi a3, a1, 0xff +; or a5, t2, a3 +; slli a7, a5, 0x10 +; srli t4, a0, 0x10 +; slli t1, t4, 8 +; srli a1, t4, 8 +; andi a2, a1, 0xff +; or a4, t1, a2 +; slli a6, a4, 0x30 +; srli t3, a6, 0x30 +; or t0, a7, t3 +; slli t2, t0, 0x20 +; srli a1, a0, 0x20 +; slli a3, a1, 8 +; srli a5, a1, 8 +; andi a7, a5, 0xff +; or t4, a3, a7 +; slli t1, t4, 0x10 +; srli a0, a1, 0x10 +; slli a2, a0, 8 +; srli a4, a0, 8 +; andi a6, a4, 0xff +; or t3, a2, a6 +; slli t0, t3, 0x30 +; srli a0, t0, 0x30 +; or a1, t1, a0 +; slli a3, a1, 0x20 +; srli a5, a3, 0x20 +; or a0, t2, a5 +; ret + +function %bswap_i128(i128) -> i128 { +block0(v0: i128): + v1 = bswap v0 + return v1 +} + +; VCode: +; add sp,-16 +; sd ra,8(sp) +; sd fp,0(sp) +; mv fp,sp +; sd s11,-8(sp) +; add sp,-16 +; block0: +; slli a2,a1,8 +; srli a3,a1,8 +; andi a4,a3,255 +; or a6,a2,a4 +; slli t3,a6,16 +; srli t0,a1,16 +; slli t2,t0,8 +; srli a2,t0,8 +; andi a3,a2,255 +; or a5,t2,a3 +; slli a7,a5,48 +; srli t4,a7,48 +; or t1,t3,t4 +; slli a2,t1,32 +; srli a3,a1,32 +; slli a4,a3,8 +; srli a6,a3,8 +; andi t3,a6,255 +; or t0,a4,t3 +; slli t2,t0,16 +; srli a1,a3,16 +; slli a3,a1,8 +; srli a5,a1,8 +; andi a7,a5,255 +; or t4,a3,a7 +; slli t1,t4,48 +; srli a1,t1,48 +; or a3,t2,a1 +; slli a4,a3,32 +; srli a6,a4,32 +; or t3,a2,a6 +; mv s11,t3 +; slli t0,a0,8 +; srli t2,a0,8 +; andi a1,t2,255 +; or a3,t0,a1 +; slli a5,a3,16 +; srli a7,a0,16 +; slli t4,a7,8 +; srli t1,a7,8 +; andi a1,t1,255 +; or a2,t4,a1 +; slli a4,a2,48 +; srli a6,a4,48 +; or t3,a5,a6 +; slli t0,t3,32 +; srli t2,a0,32 +; slli a1,t2,8 +; srli a3,t2,8 +; andi a5,a3,255 +; or a7,a1,a5 +; slli t4,a7,16 +; srli t1,t2,16 +; slli a0,t1,8 +; srli a2,t1,8 +; andi a4,a2,255 +; or a6,a0,a4 +; slli t3,a6,48 +; srli t1,t3,48 +; or t2,t4,t1 +; slli a1,t2,32 +; srli a3,a1,32 +; or a1,t0,a3 +; mv a0,s11 +; add sp,+16 +; ld s11,-8(sp) +; ld ra,8(sp) +; ld fp,0(sp) +; add sp,+16 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; addi sp, sp, -0x10 +; sd ra, 8(sp) +; sd s0, 0(sp) +; ori s0, sp, 0 +; sd s11, -8(sp) +; addi sp, sp, -0x10 +; block1: ; offset 0x18 +; slli a2, a1, 8 +; srli a3, a1, 8 +; andi a4, a3, 0xff +; or a6, a2, a4 +; slli t3, a6, 0x10 +; srli t0, a1, 0x10 +; slli t2, t0, 8 +; srli a2, t0, 8 +; andi a3, a2, 0xff +; or a5, t2, a3 +; slli a7, a5, 0x30 +; srli t4, a7, 0x30 +; or t1, t3, t4 +; slli a2, t1, 0x20 +; srli a3, a1, 0x20 +; slli a4, a3, 8 +; srli a6, a3, 8 +; andi t3, a6, 0xff +; or t0, a4, t3 +; slli t2, t0, 0x10 +; srli a1, a3, 0x10 +; slli a3, a1, 8 +; srli a5, a1, 8 +; andi a7, a5, 0xff +; or t4, a3, a7 +; slli t1, t4, 0x30 +; srli a1, t1, 0x30 +; or a3, t2, a1 +; slli a4, a3, 0x20 +; srli a6, a4, 0x20 +; or t3, a2, a6 +; ori s11, t3, 0 +; slli t0, a0, 8 +; srli t2, a0, 8 +; andi a1, t2, 0xff +; or a3, t0, a1 +; slli a5, a3, 0x10 +; srli a7, a0, 0x10 +; slli t4, a7, 8 +; srli t1, a7, 8 +; andi a1, t1, 0xff +; or a2, t4, a1 +; slli a4, a2, 0x30 +; srli a6, a4, 0x30 +; or t3, a5, a6 +; slli t0, t3, 0x20 +; srli t2, a0, 0x20 +; slli a1, t2, 8 +; srli a3, t2, 8 +; andi a5, a3, 0xff +; or a7, a1, a5 +; slli t4, a7, 0x10 +; srli t1, t2, 0x10 +; slli a0, t1, 8 +; srli a2, t1, 8 +; andi a4, a2, 0xff +; or a6, a0, a4 +; slli t3, a6, 0x30 +; srli t1, t3, 0x30 +; or t2, t4, t1 +; slli a1, t2, 0x20 +; srli a3, a1, 0x20 +; or a1, t0, a3 +; ori a0, s11, 0 +; addi sp, sp, 0x10 +; ld s11, -8(sp) +; ld ra, 8(sp) +; ld s0, 0(sp) +; addi sp, sp, 0x10 +; ret + diff --git a/cranelift/filetests/filetests/runtests/bswap.clif b/cranelift/filetests/filetests/runtests/bswap.clif index 066cf59d09e7..d8f168242766 100644 --- a/cranelift/filetests/filetests/runtests/bswap.clif +++ b/cranelift/filetests/filetests/runtests/bswap.clif @@ -3,6 +3,8 @@ test run target x86_64 target aarch64 target s390x +target riscv64 +target riscv64 has_zbb function %bswap_i16(i16) -> i16 { block0(v0: i16): diff --git a/cranelift/filetests/filetests/runtests/i128-bswap.clif b/cranelift/filetests/filetests/runtests/i128-bswap.clif index 62651992c376..33b03000481b 100644 --- a/cranelift/filetests/filetests/runtests/i128-bswap.clif +++ b/cranelift/filetests/filetests/runtests/i128-bswap.clif @@ -4,6 +4,8 @@ set enable_llvm_abi_extensions target x86_64 target aarch64 target s390x +target riscv64 +target riscv64 has_zbb function %bswap_i128(i128) -> i128 { block0(v0: i128): diff --git a/cranelift/filetests/filetests/runtests/simd-valltrue.clif b/cranelift/filetests/filetests/runtests/simd-valltrue.clif index a1cc51488564..870687b7702c 100644 --- a/cranelift/filetests/filetests/runtests/simd-valltrue.clif +++ b/cranelift/filetests/filetests/runtests/simd-valltrue.clif @@ -16,7 +16,12 @@ block0(v0: i8x16): ; run: %vall_true_i8x16([0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]) == 0 ; run: %vall_true_i8x16([-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]) == 0 ; run: %vall_true_i8x16([-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1]) == 1 - +; run: %vall_true_i8x16(0xffffffffffffffffffffffffffffff00) == 0 +; run: %vall_true_i8x16(0x00ffffffffffffffffffffffffffffff) == 0 +; run: %vall_true_i8x16(0xffffffffffffff00ffffffffffffffff) == 0 +; run: %vall_true_i8x16(0x01010101010101010101010101010101) == 1 +; run: %vall_true_i8x16(0xffffffffffffffffffffffffffffffff) == 1 +; run: %vall_true_i8x16(0xe66021830506f2fffdfebfc8c8c8c8c8) == 1 function %vall_true_i16x8(i16x8) -> i8 { block0(v0: i16x8): @@ -46,3 +51,4 @@ block0(v0: i64x2): ; run: %vall_true_i64x2([0 0]) == 0 ; run: %vall_true_i64x2([-1 0]) == 0 ; run: %vall_true_i64x2([-1 -1]) == 1 +; run: %vall_true_i64x2([0xffffffff_00000000 -1]) == 1 diff --git a/cranelift/filetests/src/function_runner.rs b/cranelift/filetests/src/function_runner.rs index dff1fda6cf9c..5f034fc51a21 100644 --- a/cranelift/filetests/src/function_runner.rs +++ b/cranelift/filetests/src/function_runner.rs @@ -90,7 +90,7 @@ impl TestFileCompiler { /// [TestFileCompiler::with_host_isa]). pub fn new(isa: OwnedTargetIsa) -> Self { let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); - drop(&mut builder); // require mutability on all architectures + let _ = &mut builder; // require mutability on all architectures #[cfg(target_arch = "x86_64")] { builder.symbol_lookup_fn(Box::new(|name| { diff --git a/cranelift/filetests/src/runtest_environment.rs b/cranelift/filetests/src/runtest_environment.rs deleted file mode 100644 index 8a32e8161809..000000000000 --- a/cranelift/filetests/src/runtest_environment.rs +++ /dev/null @@ -1,36 +0,0 @@ -use anyhow::anyhow; -use cranelift_codegen::ir::{ArgumentPurpose, Function}; -use cranelift_reader::Comment; - -/// Stores info about the expected environment for a test function. -#[derive(Debug, Clone)] -pub struct RuntestEnvironment {} - -impl RuntestEnvironment { - /// Parse the environment from a set of comments - pub fn parse(comments: &[Comment]) -> anyhow::Result { - let mut env = RuntestEnvironment {}; - Ok(env) - } - - /// Validates the signature of a [Function] ensuring that if this environment is active, the - /// function has a `vmctx` argument - pub fn validate_signature(&self, func: &Function) -> Result<(), String> { - let first_arg_is_vmctx = func - .signature - .params - .first() - .map(|p| p.purpose == ArgumentPurpose::VMContext) - .unwrap_or(false); - - if !first_arg_is_vmctx && self.is_active() { - return Err(concat!( - "This test requests a heap, but the first argument is not `i64 vmctx`.\n", - "See docs/testing.md for more info on using heap annotations." - ) - .to_string()); - } - - Ok(()) - } -} diff --git a/cranelift/frontend/Cargo.toml b/cranelift/frontend/Cargo.toml index b08e143753b7..68f29ec720c5 100644 --- a/cranelift/frontend/Cargo.toml +++ b/cranelift/frontend/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-frontend" -version = "0.98.0" +version = "0.99.0" description = "Cranelift IR builder helper" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-frontend" diff --git a/cranelift/fuzzgen/src/function_generator.rs b/cranelift/fuzzgen/src/function_generator.rs index f4d0746e58e5..dbc8d3d6788f 100644 --- a/cranelift/fuzzgen/src/function_generator.rs +++ b/cranelift/fuzzgen/src/function_generator.rs @@ -714,8 +714,6 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) - (Opcode::Iabs, &[I128]), // TODO (Opcode::Bitselect, &[I128, I128, I128]), - // TODO - (Opcode::Bswap), // https://github.com/bytecodealliance/wasmtime/issues/5528 ( Opcode::FcvtToUint | Opcode::FcvtToSint, diff --git a/cranelift/interpreter/Cargo.toml b/cranelift/interpreter/Cargo.toml index 3e9e7a9687f7..9648a7ccbd2d 100644 --- a/cranelift/interpreter/Cargo.toml +++ b/cranelift/interpreter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-interpreter" -version = "0.98.0" +version = "0.99.0" authors = ["The Cranelift Project Developers"] description = "Interpret Cranelift IR" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 8c8e19c263b2..3ee76362c869 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -1040,12 +1040,13 @@ where let any = fold_vector(arg(0), ctrl_ty, init.clone(), |acc, lane| acc.or(lane))?; assign(DataValue::bool(any != init, false, types::I8)?) } - Opcode::VallTrue => { - let lane_ty = ctrl_ty.lane_type(); - let init = DataValue::bool(true, true, lane_ty)?; - let all = fold_vector(arg(0), ctrl_ty, init.clone(), |acc, lane| acc.and(lane))?; - assign(DataValue::bool(all == init, false, types::I8)?) - } + Opcode::VallTrue => assign(DataValue::bool( + !(arg(0).iter_lanes(ctrl_ty)?.try_fold(false, |acc, lane| { + Ok::(acc | lane.is_zero()?) + })?), + false, + types::I8, + )?), Opcode::SwidenLow | Opcode::SwidenHigh | Opcode::UwidenLow | Opcode::UwidenHigh => { let new_type = ctrl_ty.merge_lanes().unwrap(); let conv_type = match inst.opcode() { @@ -1434,11 +1435,14 @@ fn fcmp(code: FloatCC, left: &DataValue, right: &DataValue) -> ValueResult }) } -type SimdVec = SmallVec<[DataValue; 4]>; +pub type SimdVec = SmallVec<[DataValue; 4]>; /// Converts a SIMD vector value into a Rust array of [Value] for processing. /// If `x` is a scalar, it will be returned as a single-element array. -fn extractlanes(x: &DataValue, vector_type: types::Type) -> ValueResult> { +pub(crate) fn extractlanes( + x: &DataValue, + vector_type: types::Type, +) -> ValueResult> { let lane_type = vector_type.lane_type(); let mut lanes = SimdVec::new(); // Wrap scalar values as a single-element vector and return. diff --git a/cranelift/interpreter/src/value.rs b/cranelift/interpreter/src/value.rs index d75307fdd474..abde5302d51f 100644 --- a/cranelift/interpreter/src/value.rs +++ b/cranelift/interpreter/src/value.rs @@ -8,6 +8,8 @@ use cranelift_codegen::ir::immediates::{Ieee32, Ieee64}; use cranelift_codegen::ir::{types, Type}; use thiserror::Error; +use crate::step::{extractlanes, SimdVec}; + pub type ValueResult = Result; pub trait DataValueExt: Sized { @@ -89,6 +91,9 @@ pub trait DataValueExt: Sized { fn trailing_zeros(self) -> ValueResult; fn reverse_bits(self) -> ValueResult; fn swap_bytes(self) -> ValueResult; + + // An iterator over the lanes of a SIMD type + fn iter_lanes(&self, ty: Type) -> ValueResult; } #[derive(Error, Debug, PartialEq)] @@ -484,9 +489,16 @@ impl DataValueExt for DataValue { fn is_zero(&self) -> ValueResult { match self { + DataValue::I8(f) => Ok(*f == 0), + DataValue::I16(f) => Ok(*f == 0), + DataValue::I32(f) => Ok(*f == 0), + DataValue::I64(f) => Ok(*f == 0), + DataValue::I128(f) => Ok(*f == 0), DataValue::F32(f) => Ok(f.is_zero()), DataValue::F64(f) => Ok(f.is_zero()), - _ => Err(ValueError::InvalidType(ValueTypeClass::Float, self.ty())), + DataValue::V64(_) | DataValue::V128(_) => { + Err(ValueError::InvalidType(ValueTypeClass::Float, self.ty())) + } } } @@ -808,4 +820,90 @@ impl DataValueExt for DataValue { fn swap_bytes(self) -> ValueResult { unary_match!(swap_bytes(&self); [I16, I32, I64, I128]) } + + fn iter_lanes(&self, ty: Type) -> ValueResult { + DataValueIterator::new(self, ty) + } +} + +/// Iterator for DataValue's +pub struct DataValueIterator { + ty: Type, + v: SimdVec, + idx: usize, +} + +impl DataValueIterator { + fn new(dv: &DataValue, ty: Type) -> Result { + match extractlanes(dv, ty) { + Ok(v) => return Ok(Self { ty, v, idx: 0 }), + Err(err) => return Err(err), + } + } +} + +impl Iterator for DataValueIterator { + type Item = DataValue; + + fn next(&mut self) -> Option { + if self.idx >= self.ty.lane_count() as usize { + return None; + } + + let dv = self.v[self.idx].clone(); + self.idx += 1; + Some(dv) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_iterator_v128() { + let dv = DataValue::V128([99, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + assert_eq!(simd_sum(dv, types::I8X16), 219); + } + + #[test] + fn test_iterator_v128_empty() { + let dv = DataValue::V128([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(simd_sum(dv, types::I8X16), 0); + } + + #[test] + fn test_iterator_v128_ones() { + let dv = DataValue::V128([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); + assert_eq!(simd_sum(dv, types::I8X16), 16); + } + + #[test] + fn test_iterator_v64_empty() { + let dv = DataValue::V64([0, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(simd_sum(dv, types::I8X8), 0); + } + #[test] + fn test_iterator_v64_ones() { + let dv = DataValue::V64([1, 1, 1, 1, 1, 1, 1, 1]); + assert_eq!(simd_sum(dv, types::I8X8), 8); + } + #[test] + fn test_iterator_v64() { + let dv = DataValue::V64([10, 20, 30, 40, 50, 60, 70, 80]); + assert_eq!(simd_sum(dv, types::I8X8), 360); + } + + fn simd_sum(dv: DataValue, ty: types::Type) -> i128 { + let itr = dv.iter_lanes(ty).unwrap(); + + itr.map(|e| { + if let Some(v) = e.into_int_signed().ok() { + v + } else { + 0 + } + }) + .sum() + } } diff --git a/cranelift/isle/isle/Cargo.toml b/cranelift/isle/isle/Cargo.toml index 3bedc884c242..dfd84f84dba2 100644 --- a/cranelift/isle/isle/Cargo.toml +++ b/cranelift/isle/isle/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0 WITH LLVM-exception" name = "cranelift-isle" readme = "../README.md" repository = "https://github.com/bytecodealliance/wasmtime/tree/main/cranelift/isle" -version = "0.98.0" +version = "0.99.0" [dependencies] codespan-reporting = { version = "0.11.1", optional = true } diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml index 88dcf7b2b380..73905f9089ed 100644 --- a/cranelift/jit/Cargo.toml +++ b/cranelift/jit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-jit" -version = "0.98.0" +version = "0.99.0" authors = ["The Cranelift Project Developers"] description = "A JIT library backed by Cranelift" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/jit/src/backend.rs b/cranelift/jit/src/backend.rs index 1bf34cc1f9cc..b564b82b6eb4 100644 --- a/cranelift/jit/src/backend.rs +++ b/cranelift/jit/src/backend.rs @@ -434,7 +434,7 @@ impl JITModule { // are profiling with perf and saving binaries to PERF_BUILDID_DIR // for post-profile analysis, write information about each function // we define. - if cfg!(target_os = "linux") && ::std::env::var_os("PERF_BUILDID_DIR").is_some() { + if cfg!(unix) && ::std::env::var_os("PERF_BUILDID_DIR").is_some() { let mut map_file = ::std::fs::OpenOptions::new() .create(true) .append(true) diff --git a/cranelift/module/Cargo.toml b/cranelift/module/Cargo.toml index e571012b9d99..b5c850f3b2e9 100644 --- a/cranelift/module/Cargo.toml +++ b/cranelift/module/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-module" -version = "0.98.0" +version = "0.99.0" authors = ["The Cranelift Project Developers"] description = "Support for linking functions and data with Cranelift" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/native/Cargo.toml b/cranelift/native/Cargo.toml index 69aa890a9dae..e37e998ee344 100644 --- a/cranelift/native/Cargo.toml +++ b/cranelift/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-native" -version = "0.98.0" +version = "0.99.0" authors = ["The Cranelift Project Developers"] description = "Support for targeting the host with Cranelift" documentation = "https://docs.rs/cranelift-native" diff --git a/cranelift/object/Cargo.toml b/cranelift/object/Cargo.toml index d22a5156e0dd..c576f310e282 100644 --- a/cranelift/object/Cargo.toml +++ b/cranelift/object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-object" -version = "0.98.0" +version = "0.99.0" authors = ["The Cranelift Project Developers"] description = "Emit Cranelift output to native object files with `object`" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/reader/Cargo.toml b/cranelift/reader/Cargo.toml index 7d38a05ec868..3ec07ce9c962 100644 --- a/cranelift/reader/Cargo.toml +++ b/cranelift/reader/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-reader" -version = "0.98.0" +version = "0.99.0" description = "Cranelift textual IR reader" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-reader" diff --git a/cranelift/serde/Cargo.toml b/cranelift/serde/Cargo.toml index a94f7762d9c7..2846623ec770 100644 --- a/cranelift/serde/Cargo.toml +++ b/cranelift/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-serde" -version = "0.98.0" +version = "0.99.0" authors = ["The Cranelift Project Developers"] description = "Serializer/Deserializer for Cranelift IR" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/umbrella/Cargo.toml b/cranelift/umbrella/Cargo.toml index 793dfde8c43d..2fdd8afdec74 100644 --- a/cranelift/umbrella/Cargo.toml +++ b/cranelift/umbrella/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift" -version = "0.98.0" +version = "0.99.0" description = "Umbrella for commonly-used cranelift crates" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift" diff --git a/cranelift/wasm/Cargo.toml b/cranelift/wasm/Cargo.toml index c594584a75d2..4657744ab976 100644 --- a/cranelift/wasm/Cargo.toml +++ b/cranelift/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-wasm" -version = "0.98.0" +version = "0.99.0" authors = ["The Cranelift Project Developers"] description = "Translator from WebAssembly to Cranelift IR" documentation = "https://docs.rs/cranelift-wasm" diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index 41096cb67f0b..cd7cc353c3ff 100644 --- a/crates/c-api/include/wasmtime.h +++ b/crates/c-api/include/wasmtime.h @@ -199,11 +199,11 @@ /** * \brief Wasmtime version string. */ -#define WASMTIME_VERSION "11.0.0" +#define WASMTIME_VERSION "12.0.0" /** * \brief Wasmtime major version number. */ -#define WASMTIME_VERSION_MAJOR 11 +#define WASMTIME_VERSION_MAJOR 12 /** * \brief Wasmtime minor version number. */ diff --git a/crates/cranelift/Cargo.toml b/crates/cranelift/Cargo.toml index 40a0a9bfc2d6..1de960f2f41d 100644 --- a/crates/cranelift/Cargo.toml +++ b/crates/cranelift/Cargo.toml @@ -26,6 +26,7 @@ target-lexicon = { workspace = true } gimli = { workspace = true } object = { workspace = true, features = ['write'] } thiserror = { workspace = true } +wasmtime-versioned-export-macros = { workspace = true } [features] all-arch = ["cranelift-codegen/all-arch"] diff --git a/crates/cranelift/src/compiler/component.rs b/crates/cranelift/src/compiler/component.rs index 22a2c3d24788..75b7a249fd83 100644 --- a/crates/cranelift/src/compiler/component.rs +++ b/crates/cranelift/src/compiler/component.rs @@ -525,7 +525,6 @@ impl Compiler { /// /// Note that a macro is used here to keep this in sync with the actual /// transcoder functions themselves which are also defined via a macro. -#[allow(unused_mut)] mod host { use crate::compiler::Compiler; use cranelift_codegen::ir::{self, AbiParam}; @@ -541,11 +540,12 @@ mod host { $( pub(super) fn $name(compiler: &Compiler, func: &mut ir::Function) -> (ir::SigRef, u32) { let pointer_type = compiler.isa.pointer_type(); - let mut params = vec![ + let params = vec![ $( AbiParam::new(host_transcode!(@ty pointer_type $param)) ),* ]; - let mut returns = Vec::new(); - $(host_transcode!(@push_return pointer_type params returns $result);)? + let returns = vec![ + $( AbiParam::new(host_transcode!(@ty pointer_type $result)) )? + ]; let sig = func.import_signature(ir::Signature { params, returns, @@ -560,12 +560,7 @@ mod host { (@ty $ptr:ident size) => ($ptr); (@ty $ptr:ident ptr_u8) => ($ptr); (@ty $ptr:ident ptr_u16) => ($ptr); - - (@push_return $ptr:ident $params:ident $returns:ident size) => ($returns.push(AbiParam::new($ptr));); - (@push_return $ptr:ident $params:ident $returns:ident size_pair) => ({ - $params.push(AbiParam::new($ptr)); - $returns.push(AbiParam::new($ptr)); - }); + (@ty $ptr:ident ptr_size) => ($ptr); } wasmtime_environ::foreach_transcoder!(host_transcode); diff --git a/crates/cranelift/src/debug/transform/unit.rs b/crates/cranelift/src/debug/transform/unit.rs index 1b220097c43e..eefed56d071b 100644 --- a/crates/cranelift/src/debug/transform/unit.rs +++ b/crates/cranelift/src/debug/transform/unit.rs @@ -15,6 +15,7 @@ use gimli::write; use gimli::{AttributeValue, DebuggingInformationEntry, Unit}; use std::collections::HashSet; use wasmtime_environ::DefinedFuncIndex; +use wasmtime_versioned_export_macros::versioned_stringify_ident; struct InheritedAttr { stack: Vec<(usize, T)>, @@ -198,7 +199,7 @@ where // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("resolve_vmctx_memory_ptr")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(resolve_vmctx_memory_ptr))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("ptr")), gimli::DW_AT_type = write::AttributeValue::UnitRef(ptr_type_id) }); @@ -215,7 +216,7 @@ where // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("resolve_vmctx_memory_ptr")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(resolve_vmctx_memory_ptr))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("operator*")), gimli::DW_AT_type = write::AttributeValue::UnitRef(ref_type_id) }); @@ -232,7 +233,7 @@ where // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("resolve_vmctx_memory_ptr")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(resolve_vmctx_memory_ptr))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("operator->")), gimli::DW_AT_type = write::AttributeValue::UnitRef(ptr_type_id) }); diff --git a/crates/cranelift/src/debug/transform/utils.rs b/crates/cranelift/src/debug/transform/utils.rs index 161612812528..0ffd19062490 100644 --- a/crates/cranelift/src/debug/transform/utils.rs +++ b/crates/cranelift/src/debug/transform/utils.rs @@ -6,8 +6,8 @@ use anyhow::Error; use cranelift_codegen::isa::TargetIsa; use gimli::write; use wasmtime_environ::DefinedFuncIndex; - -/// Adds internal Wasm utility types DIEs such as WebAssemblyPtr and +use wasmtime_versioned_export_macros::versioned_stringify_ident; +///Adds internal Wasm utility types DIEs such as WebAssemblyPtr and /// WasmtimeVMContext. /// /// For unwrapping Wasm pointer, the WasmtimeVMContext has the `set()` method @@ -113,7 +113,7 @@ pub(crate) fn add_internal_types( // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(vmctx_die_id, gimli::DW_TAG_subprogram => vmctx_set as vmctx_set_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("set_vmctx_memory")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(set_vmctx_memory))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("set")) }); add_tag!(vmctx_set_id, gimli::DW_TAG_formal_parameter => vmctx_set_this_param as vmctx_set_this_param_id { diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs index cc6ae5358128..87adcf182f07 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs @@ -7,7 +7,7 @@ use cranelift_codegen::ir; use cranelift_codegen::isa::{CallConv, TargetIsa}; use cranelift_entity::PrimaryMap; use cranelift_wasm::{DefinedFuncIndex, WasmFuncType, WasmType}; -use target_lexicon::CallingConvention; +use target_lexicon::Architecture; use wasmtime_cranelift_shared::CompiledFunctionMetadata; pub use builder::builder; @@ -126,18 +126,27 @@ fn array_call_signature(isa: &dyn TargetIsa) -> ir::Signature { /// Get the internal Wasm calling convention signature for the given type. fn wasm_call_signature(isa: &dyn TargetIsa, wasm_func_ty: &WasmFuncType) -> ir::Signature { - let call_conv = if isa.triple().default_calling_convention().ok() - == Some(CallingConvention::AppleAarch64) - { - // FIXME: We need an Apple-specific calling convention, so that - // Cranelift's ABI implementation generates unwinding directives - // about pointer authentication usage, so we can't just use - // `CallConv::Fast`. - CallConv::AppleAarch64 - } else { - CallConv::Fast - }; + // NB: this calling convention in the near future is expected to be + // unconditionally switched to the "tail" calling convention once all + // platforms have support for tail calls. + // + // Also note that the calling convention for wasm functions is purely an + // internal implementation detail of cranelift and Wasmtime. Native Rust + // code does not interact with raw wasm functions and instead always + // operates through trampolines either using the `array_call_signature` or + // `native_call_signature` where the default platform ABI is used. + let call_conv = match isa.triple().architecture { + // On s390x the "wasmtime" calling convention is used to give vectors + // little-endian lane order at the ABI layer which should reduce the + // need for conversion when operating on vector function arguments. By + // default vectors on s390x are otherwise in big-endian lane order which + // would require conversions. + Architecture::S390x => CallConv::WasmtimeSystemV, + // All other platforms pick "fast" as the calling convention since it's + // presumably, well, the fastest. + _ => CallConv::Fast, + }; let mut sig = blank_sig(isa, call_conv); let cvt = |ty: &WasmType| ir::AbiParam::new(value_type(isa, *ty)); sig.params.extend(wasm_func_ty.params().iter().map(&cvt)); diff --git a/crates/environ/src/component.rs b/crates/environ/src/component.rs index 0961b356e9a1..611f8c07d10e 100644 --- a/crates/environ/src/component.rs +++ b/crates/environ/src/component.rs @@ -60,11 +60,11 @@ macro_rules! foreach_transcoder { latin1_to_latin1(src: ptr_u8, len: size, dst: ptr_u8); latin1_to_utf16(src: ptr_u8, len: size, dst: ptr_u16); utf8_to_utf16(src: ptr_u8, len: size, dst: ptr_u16) -> size; - utf16_to_utf8(src: ptr_u16, src_len: size, dst: ptr_u8, dst_len: size) -> size_pair; - latin1_to_utf8(src: ptr_u8, src_len: size, dst: ptr_u8, dst_len: size) -> size_pair; + utf16_to_utf8(src: ptr_u16, src_len: size, dst: ptr_u8, dst_len: size, ret2: ptr_size) -> size; + latin1_to_utf8(src: ptr_u8, src_len: size, dst: ptr_u8, dst_len: size, ret2: ptr_size) -> size; utf16_to_compact_probably_utf16(src: ptr_u16, len: size, dst: ptr_u16) -> size; - utf8_to_latin1(src: ptr_u8, len: size, dst: ptr_u8) -> size_pair; - utf16_to_latin1(src: ptr_u16, len: size, dst: ptr_u8) -> size_pair; + utf8_to_latin1(src: ptr_u8, len: size, dst: ptr_u8, ret2: ptr_size) -> size; + utf16_to_latin1(src: ptr_u16, len: size, dst: ptr_u8, ret2: ptr_size) -> size; utf8_to_compact_utf16(src: ptr_u8, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size; utf16_to_compact_utf16(src: ptr_u16, src_len: size, dst: ptr_u16, dst_len: size, bytes_so_far: size) -> size; } diff --git a/crates/environ/src/component/dfg.rs b/crates/environ/src/component/dfg.rs index bd7ee965851a..aa02d6b7d408 100644 --- a/crates/environ/src/component/dfg.rs +++ b/crates/environ/src/component/dfg.rs @@ -303,7 +303,6 @@ impl ComponentDfg { let mut linearize = LinearizeDfg { dfg: &self, initializers: Vec::new(), - num_runtime_modules: 0, runtime_memories: Default::default(), runtime_post_return: Default::default(), runtime_reallocs: Default::default(), @@ -336,7 +335,6 @@ impl ComponentDfg { exports, initializers: linearize.initializers, - num_runtime_modules: linearize.num_runtime_modules, num_runtime_memories: linearize.runtime_memories.len() as u32, num_runtime_post_returns: linearize.runtime_post_return.len() as u32, num_runtime_reallocs: linearize.runtime_reallocs.len() as u32, @@ -355,7 +353,6 @@ impl ComponentDfg { struct LinearizeDfg<'a> { dfg: &'a ComponentDfg, initializers: Vec, - num_runtime_modules: u32, runtime_memories: HashMap, runtime_reallocs: HashMap, runtime_post_return: HashMap, @@ -412,20 +409,8 @@ impl LinearizeDfg<'_> { options, } } - Export::ModuleStatic(i) => { - let index = RuntimeModuleIndex::from_u32(self.num_runtime_modules); - self.num_runtime_modules += 1; - self.initializers - .push(GlobalInitializer::SaveStaticModule(*i)); - info::Export::Module(index) - } - Export::ModuleImport(i) => { - let index = RuntimeModuleIndex::from_u32(self.num_runtime_modules); - self.num_runtime_modules += 1; - self.initializers - .push(GlobalInitializer::SaveModuleImport(*i)); - info::Export::Module(index) - } + Export::ModuleStatic(i) => info::Export::ModuleStatic(*i), + Export::ModuleImport(i) => info::Export::ModuleImport(*i), Export::Instance(map) => info::Export::Instance( map.iter() .map(|(name, export)| (name.clone(), self.export(export))) diff --git a/crates/environ/src/component/info.rs b/crates/environ/src/component/info.rs index 9b74146f3e15..74e5189422ef 100644 --- a/crates/environ/src/component/info.rs +++ b/crates/environ/src/component/info.rs @@ -140,10 +140,6 @@ pub struct Component { /// instantiate this component. pub num_lowerings: u32, - /// The number of modules that are required to be saved within an instance - /// at runtime, or effectively the number of exported modules. - pub num_runtime_modules: u32, - /// The number of functions which "always trap" used to implement /// `canon.lower` of `canon.lift`'d functions within the same component. pub num_always_trap: u32, @@ -221,13 +217,6 @@ pub enum GlobalInitializer { /// used as a `post-return` function. ExtractPostReturn(ExtractPostReturn), - /// The `module` specified is saved into the runtime state at the next - /// `RuntimeModuleIndex`, referred to later by `Export` definitions. - SaveStaticModule(StaticModuleIndex), - - /// Same as `SaveModuleUpvar`, but for imports. - SaveModuleImport(RuntimeImportIndex), - /// Similar to `ExtractMemory` and friends and indicates that a `VMFuncRef` /// needs to be initialized for a transcoder function and this will later be /// used to instantiate an adapter module. @@ -434,10 +423,9 @@ pub enum Export { options: CanonicalOptions, }, /// A module defined within this component is exported. - /// - /// The module index here indexes a module recorded with - /// `GlobalInitializer::SaveModule` above. - Module(RuntimeModuleIndex), + ModuleStatic(StaticModuleIndex), + /// A module imported into this component is exported. + ModuleImport(RuntimeImportIndex), /// A nested instance is being exported which has recursively defined /// `Export` items. Instance(IndexMap), diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs index 3d135ab723de..b124587c29a2 100644 --- a/crates/environ/src/component/types.rs +++ b/crates/environ/src/component/types.rs @@ -173,10 +173,6 @@ indices! { /// Same as `RuntimeMemoryIndex` except for the `post-return` function. pub struct RuntimePostReturnIndex(u32); - /// Index that represents an exported module from a component since that's - /// currently the only use for saving the entire module state at runtime. - pub struct RuntimeModuleIndex(u32); - /// Index into the list of transcoders identified during compilation. /// /// This is used to index the `VMFuncRef` slots reserved for string encoders diff --git a/crates/fiber/Cargo.toml b/crates/fiber/Cargo.toml index e2acc6c0f444..f62c2f2fb689 100644 --- a/crates/fiber/Cargo.toml +++ b/crates/fiber/Cargo.toml @@ -7,14 +7,9 @@ license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" edition.workspace = true -# We link to some native code with symbols that don't change often, so let Cargo -# know that we can't show up multiple times in a crate graph. If this is an -# issue in the future we should tweak the build script to set `#define` -# directives or similar to embed a version number of this crate in symbols. -links = "wasmtime-fiber-shims" - [dependencies] cfg-if = { workspace = true } +wasmtime-versioned-export-macros = { workspace = true } [target.'cfg(unix)'.dependencies] rustix = { workspace = true, features = ["mm", "param"] } @@ -29,6 +24,7 @@ features = [ [build-dependencies] cc = "1.0" +wasmtime-versioned-export-macros = { workspace = true } [dev-dependencies] backtrace = "0.3.61" diff --git a/crates/fiber/build.rs b/crates/fiber/build.rs index 6bfc5c4b9daa..079a58167617 100644 --- a/crates/fiber/build.rs +++ b/crates/fiber/build.rs @@ -1,4 +1,5 @@ use std::env; +use wasmtime_versioned_export_macros::versioned_suffix; fn main() { let mut build = cc::Build::new(); @@ -7,9 +8,11 @@ fn main() { if os == "windows" { println!("cargo:rerun-if-changed=src/windows.c"); build.file("src/windows.c"); + build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); } else if arch == "s390x" { println!("cargo:rerun-if-changed=src/unix/s390x.S"); build.file("src/unix/s390x.S"); + build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); } else { // assume that this is included via inline assembly in the crate itself, // and the crate will otherwise have a `compile_error!` for unsupported diff --git a/crates/fiber/src/unix.rs b/crates/fiber/src/unix.rs index ef0ddea6b8fe..b148ff324bca 100644 --- a/crates/fiber/src/unix.rs +++ b/crates/fiber/src/unix.rs @@ -117,13 +117,16 @@ pub struct Fiber; pub struct Suspend(*mut u8); extern "C" { + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_init( top_of_stack: *mut u8, entry: extern "C" fn(*mut u8, *mut u8), entry_arg0: *mut u8, ); + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_switch(top_of_stack: *mut u8); #[allow(dead_code)] // only used in inline assembly for some platforms + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_start(); } diff --git a/crates/fiber/src/unix/aarch64.rs b/crates/fiber/src/unix/aarch64.rs index d77b1f2fbe25..92a09c24b0b1 100644 --- a/crates/fiber/src/unix/aarch64.rs +++ b/crates/fiber/src/unix/aarch64.rs @@ -39,7 +39,7 @@ cfg_if::cfg_if! { // fn(top_of_stack(%x0): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), concat!( " .cfi_startproc @@ -114,7 +114,7 @@ asm_func!( // wasmtime_fiber_start(), and provides wider coverage. #[rustfmt::skip] asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), concat!( " .cfi_startproc @@ -144,7 +144,7 @@ asm_func!( // doing. Like over there note that the relative offsets to registers here // match the frame layout in `wasmtime_fiber_switch`. asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " .cfi_startproc simple .cfi_def_cfa_offset 0 diff --git a/crates/fiber/src/unix/arm.rs b/crates/fiber/src/unix/arm.rs index 1d320fd1f85e..c2b3c0f0b248 100644 --- a/crates/fiber/src/unix/arm.rs +++ b/crates/fiber/src/unix/arm.rs @@ -12,7 +12,7 @@ use wasmtime_asm_macros::{asm_func, asm_sym}; // fn(top_of_stack(%r0): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), " // Save callee-saved registers push {{r4-r11,lr}} @@ -34,7 +34,7 @@ asm_func!( // entry_arg0(%r2): *mut u8, // ) asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), " adr r3, wasmtime_fiber_start str r3, [r0, #-0x0c] // => lr @@ -49,7 +49,7 @@ asm_func!( ); asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " .cfi_startproc simple .cfi_def_cfa_offset 0 diff --git a/crates/fiber/src/unix/riscv64.rs b/crates/fiber/src/unix/riscv64.rs index 9c7b0cb01f0e..61966f7b3f05 100644 --- a/crates/fiber/src/unix/riscv64.rs +++ b/crates/fiber/src/unix/riscv64.rs @@ -9,7 +9,7 @@ use wasmtime_asm_macros::asm_func; // fn(top_of_stack(rdi): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), " // See https://github.com/rust-lang/rust/issues/80608. .attribute arch, \"rv64gc\" @@ -90,7 +90,7 @@ asm_func!( // ) #[rustfmt::skip] asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), " lla t0,{} sd t0,-0x18(a0) // ra,first should be wasmtime_fiber_start. @@ -107,7 +107,7 @@ asm_func!( ); asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " .cfi_startproc simple .cfi_def_cfa_offset 0 diff --git a/crates/fiber/src/unix/s390x.S b/crates/fiber/src/unix/s390x.S index a5a47118bedb..4207fcb70c1d 100644 --- a/crates/fiber/src/unix/s390x.S +++ b/crates/fiber/src/unix/s390x.S @@ -10,11 +10,14 @@ .text -#define GLOBL(fnname) .globl fnname -#define HIDDEN(fnname) .hidden fnname -#define TYPE(fnname) .type fnname,@function -#define FUNCTION(fnname) fnname -#define SIZE(fnname) .size fnname,.-fnname +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) +#define GLOBL(fnname) .globl VERSIONED_SYMBOL(fnname) +#define HIDDEN(fnname) .hidden VERSIONED_SYMBOL(fnname) +#define TYPE(fnname) .type VERSIONED_SYMBOL(fnname),@function +#define FUNCTION(fnname) VERSIONED_SYMBOL(fnname) +#define SIZE(fnname) .size VERSIONED_SYMBOL(fnname),.-VERSIONED_SYMBOL(fnname) // fn(top_of_stack(%x0): *mut u8) HIDDEN(wasmtime_fiber_switch) diff --git a/crates/fiber/src/unix/x86_64.rs b/crates/fiber/src/unix/x86_64.rs index 420111c04361..15e4fd57a99f 100644 --- a/crates/fiber/src/unix/x86_64.rs +++ b/crates/fiber/src/unix/x86_64.rs @@ -9,7 +9,7 @@ use wasmtime_asm_macros::asm_func; // fn(top_of_stack(rdi): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), " // We're switching to arbitrary code somewhere else, so pessimistically // assume that all callee-save register are clobbered. This means we need @@ -49,7 +49,7 @@ asm_func!( // ) #[rustfmt::skip] asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), " // Here we're going to set up a stack frame as expected by // `wasmtime_fiber_switch`. The values we store here will get restored into @@ -89,7 +89,7 @@ asm_func!( // If you're curious a decent introduction to CFI things and unwinding is at // https://www.imperialviolet.org/2017/01/18/cfi.html asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " // Use the `simple` directive on the startproc here which indicates that // some default settings for the platform are omitted, since this diff --git a/crates/fiber/src/windows.c b/crates/fiber/src/windows.c index 9e017f9b0260..9d4176eb1b7b 100644 --- a/crates/fiber/src/windows.c +++ b/crates/fiber/src/windows.c @@ -1,5 +1,9 @@ #include -LPVOID wasmtime_fiber_get_current() { +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) + +LPVOID VERSIONED_SYMBOL(wasmtime_fiber_get_current)() { return GetCurrentFiber(); } diff --git a/crates/fiber/src/windows.rs b/crates/fiber/src/windows.rs index 04452bd87a90..2e09f28b7951 100644 --- a/crates/fiber/src/windows.rs +++ b/crates/fiber/src/windows.rs @@ -46,6 +46,7 @@ struct StartState { const FIBER_FLAG_FLOAT_SWITCH: u32 = 1; extern "C" { + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_get_current() -> *mut c_void; } diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index e712834e0739..06390fdacbb4 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -32,7 +32,7 @@ wasmi = "0.20.0" # though, so we could use that if we wanted. For now though just simplify a bit # and don't depend on this on Windows. The same applies on s390x and riscv. [target.'cfg(not(any(windows, target_arch = "s390x", target_arch = "riscv64")))'.dependencies] -v8 = "0.44.3" +v8 = "0.74.1" [dev-dependencies] wat = { workspace = true } diff --git a/crates/jit-debug/Cargo.toml b/crates/jit-debug/Cargo.toml index 5515be10199a..85c6b6840db3 100644 --- a/crates/jit-debug/Cargo.toml +++ b/crates/jit-debug/Cargo.toml @@ -13,6 +13,7 @@ edition.workspace = true [dependencies] once_cell = { workspace = true, optional = true } object = { workspace = true, optional = true } +wasmtime-versioned-export-macros = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] rustix = { workspace = true, features = ["mm", "param", "time"], optional = true } diff --git a/crates/jit-debug/src/gdb_jit_int.rs b/crates/jit-debug/src/gdb_jit_int.rs index e887cddb0d40..87ecd7ee4dac 100644 --- a/crates/jit-debug/src/gdb_jit_int.rs +++ b/crates/jit-debug/src/gdb_jit_int.rs @@ -6,6 +6,7 @@ use once_cell::sync::Lazy; use std::pin::Pin; use std::ptr; use std::sync::Mutex; +use wasmtime_versioned_export_macros::versioned_link; #[repr(C)] struct JITCodeEntry { @@ -28,6 +29,7 @@ struct JITDescriptor { } extern "C" { + #[versioned_link] fn wasmtime_jit_debug_descriptor() -> *mut JITDescriptor; fn __jit_debug_register_code(); } diff --git a/crates/jit/src/profiling.rs b/crates/jit/src/profiling.rs index 22f53f521fbe..d816d65f8ba5 100644 --- a/crates/jit/src/profiling.rs +++ b/crates/jit/src/profiling.rs @@ -20,7 +20,7 @@ cfg_if::cfg_if! { } cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { + if #[cfg(unix)] { mod perfmap; pub use perfmap::new as new_perfmap; } else { diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index 0a33291e1642..c29d53166a65 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -16,6 +16,7 @@ wasmtime-environ = { workspace = true } wasmtime-fiber = { workspace = true, optional = true } wasmtime-fibre = { workspace = true } wasmtime-jit-debug = { workspace = true, features = ["gdb_jit_int"] } +wasmtime-versioned-export-macros = { workspace = true } libc = { version = "0.2.112", default-features = false } log = { workspace = true } memoffset = "0.8.0" @@ -51,6 +52,7 @@ once_cell = { workspace = true } [build-dependencies] cc = "1.0" +wasmtime-versioned-export-macros = { workspace = true } [features] async = ["wasmtime-fiber"] diff --git a/crates/runtime/build.rs b/crates/runtime/build.rs index 5cf6326b3219..571f0c4b2267 100644 --- a/crates/runtime/build.rs +++ b/crates/runtime/build.rs @@ -1,4 +1,5 @@ use std::env; +use wasmtime_versioned_export_macros::versioned_suffix; fn main() { let mut build = cc::Build::new(); @@ -7,6 +8,7 @@ fn main() { let os = env::var("CARGO_CFG_TARGET_OS").unwrap(); build.define(&format!("CFG_TARGET_OS_{}", os), None); build.define(&format!("CFG_TARGET_ARCH_{}", arch), None); + build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); if arch == "s390x" { println!("cargo:rerun-if-changed=src/trampolines/s390x.S"); build.file("src/trampolines/s390x.S"); diff --git a/crates/runtime/src/component/transcode.rs b/crates/runtime/src/component/transcode.rs index 5c007c8df1a7..e67b87a0bc34 100644 --- a/crates/runtime/src/component/transcode.rs +++ b/crates/runtime/src/component/transcode.rs @@ -29,7 +29,6 @@ macro_rules! define_transcoders { $( $name: unsafe extern "C" fn( $(define_transcoders!(@ty $param),)* - $(define_transcoders!(@retptr $result),)? ) $( -> define_transcoders!(@ty $result))?, )* } @@ -42,12 +41,9 @@ macro_rules! define_transcoders { }; (@ty size) => (usize); - (@ty size_pair) => (usize); (@ty ptr_u8) => (*mut u8); (@ty ptr_u16) => (*mut u16); - - (@retptr size_pair) => (*mut usize); - (@retptr size) => (()); + (@ty ptr_size) => (*mut usize); } wasmtime_environ::foreach_transcoder!(define_transcoders); @@ -68,10 +64,6 @@ mod trampolines { $( pub unsafe extern "C" fn $name( $($pname : define_transcoders!(@ty $param),)* - // If a result is given then a `size_pair` results gets its - // second result value passed via a return pointer here, so - // optionally indicate a return pointer. - $(_retptr: define_transcoders!(@retptr $result))? ) $( -> define_transcoders!(@ty $result))? { $(transcoders!(@validate_param $pname $param);)* @@ -82,10 +74,10 @@ mod trampolines { // Additionally assume that every function below returns a // `Result` where errors turn into traps. let result = std::panic::catch_unwind(|| { - super::$name($($pname),*) + transcoders!(@invoke $name() $($pname)*) }); match result { - Ok(Ok(ret)) => transcoders!(@convert_ret ret _retptr $($result)?), + Ok(Ok(ret)) => transcoders!(@convert_ret ret $($pname: $param)*), Ok(Err(err)) => crate::traphandlers::raise_trap( crate::traphandlers::TrapReason::User { error: err, @@ -98,13 +90,17 @@ mod trampolines { )* ); - (@convert_ret $ret:ident $retptr:ident) => ($ret); - (@convert_ret $ret:ident $retptr:ident size) => ($ret); - (@convert_ret $ret:ident $retptr:ident size_pair) => ({ + // Helper macro to convert a 2-tuple automatically when the last + // parameter is a `ptr_size` argument. + (@convert_ret $ret:ident) => ($ret); + (@convert_ret $ret:ident $retptr:ident: ptr_size) => ({ let (a, b) = $ret; *$retptr = b; a }); + (@convert_ret $ret:ident $name:ident: $ty:ident $($rest:tt)*) => ( + transcoders!(@convert_ret $ret $($rest)*) + ); (@validate_param $arg:ident ptr_u16) => ({ // This should already be guaranteed by the canonical ABI and our @@ -113,6 +109,20 @@ mod trampolines { assert!(($arg as usize) % 2 == 0, "unaligned 16-bit pointer"); }); (@validate_param $arg:ident $ty:ident) => (); + + // Helper macro to invoke `$m` with all of the tokens passed except for + // any argument named `ret2` + (@invoke $m:ident ($($args:tt)*)) => (super::$m($($args)*)); + + // ignore `ret2`-named arguments + (@invoke $m:ident ($($args:tt)*) ret2 $($rest:tt)*) => ( + transcoders!(@invoke $m ($($args)*) $($rest)*) + ); + + // move all other arguments into the `$args` list + (@invoke $m:ident ($($args:tt)*) $param:ident $($rest:tt)*) => ( + transcoders!(@invoke $m ($($args)* $param,) $($rest)*) + ); } wasmtime_environ::foreach_transcoder!(transcoders); diff --git a/crates/runtime/src/debug_builtins.rs b/crates/runtime/src/debug_builtins.rs index 9e7ef295a374..82ac1cf37609 100644 --- a/crates/runtime/src/debug_builtins.rs +++ b/crates/runtime/src/debug_builtins.rs @@ -3,10 +3,11 @@ use crate::instance::Instance; use crate::vmcontext::VMContext; use wasmtime_environ::{EntityRef, MemoryIndex}; +use wasmtime_versioned_export_macros::versioned_export; static mut VMCTX_AND_MEMORY: (*mut VMContext, usize) = (std::ptr::null_mut(), 0); -#[no_mangle] +#[versioned_export] pub unsafe extern "C" fn resolve_vmctx_memory(ptr: usize) -> *const u8 { Instance::from_vmctx(VMCTX_AND_MEMORY.0, |handle| { assert!( @@ -19,7 +20,7 @@ pub unsafe extern "C" fn resolve_vmctx_memory(ptr: usize) -> *const u8 { }) } -#[no_mangle] +#[versioned_export] pub unsafe extern "C" fn resolve_vmctx_memory_ptr(p: *const u32) -> *const u8 { let ptr = std::ptr::read(p); assert!( @@ -37,7 +38,7 @@ pub unsafe extern "C" fn resolve_vmctx_memory_ptr(p: *const u32) -> *const u8 { }) } -#[no_mangle] +#[versioned_export] pub unsafe extern "C" fn set_vmctx_memory(vmctx_ptr: *mut VMContext) { // TODO multi-memory VMCTX_AND_MEMORY = (vmctx_ptr, 0); diff --git a/crates/runtime/src/helpers.c b/crates/runtime/src/helpers.c index 96019669de63..e3c9bb58240b 100644 --- a/crates/runtime/src/helpers.c +++ b/crates/runtime/src/helpers.c @@ -42,7 +42,11 @@ typedef void *platform_jmp_buf[5]; // this is the documented size; see the docs #endif -int wasmtime_setjmp( +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) + +int VERSIONED_SYMBOL(wasmtime_setjmp)( void **buf_storage, void (*body)(void*, void*), void *payload, @@ -56,7 +60,7 @@ int wasmtime_setjmp( return 1; } -void wasmtime_longjmp(void *JmpBuf) { +void VERSIONED_SYMBOL(wasmtime_longjmp)(void *JmpBuf) { platform_jmp_buf *buf = (platform_jmp_buf*) JmpBuf; platform_longjmp(*buf, 1); } @@ -99,6 +103,6 @@ struct JITDescriptor __jit_debug_descriptor = {1, 0, NULL, NULL}; -struct JITDescriptor* wasmtime_jit_debug_descriptor() { +struct JITDescriptor* VERSIONED_SYMBOL(wasmtime_jit_debug_descriptor)() { return &__jit_debug_descriptor; } diff --git a/crates/runtime/src/libcalls.rs b/crates/runtime/src/libcalls.rs index e730565be5ef..8fb8c8b33d77 100644 --- a/crates/runtime/src/libcalls.rs +++ b/crates/runtime/src/libcalls.rs @@ -91,6 +91,7 @@ pub mod trampolines { extern "C" { #[allow(missing_docs)] #[allow(improper_ctypes)] + #[wasmtime_versioned_export_macros::versioned_link] pub fn $name( vmctx: *mut VMContext, $( $pname: libcall!(@ty $param), )* @@ -109,7 +110,7 @@ pub mod trampolines { // the `sym` operator to get the symbol here, but other targets // like s390x need to use outlined assembly files which requires // `no_mangle`. - #[cfg_attr(target_arch = "s390x", no_mangle)] + #[cfg_attr(target_arch = "s390x", wasmtime_versioned_export_macros::versioned_export)] unsafe extern "C" fn []( vmctx: *mut VMContext, $( $pname : libcall!(@ty $param), )* diff --git a/crates/runtime/src/trampolines/aarch64.rs b/crates/runtime/src/trampolines/aarch64.rs index 80edd8ae5a89..29852bad1ae1 100644 --- a/crates/runtime/src/trampolines/aarch64.rs +++ b/crates/runtime/src/trampolines/aarch64.rs @@ -2,7 +2,7 @@ macro_rules! wasm_to_libcall_trampoline { ($libcall:ident ; $libcall_impl:ident) => { wasmtime_asm_macros::asm_func!( - stringify!($libcall), + wasmtime_versioned_export_macros::versioned_stringify_ident!($libcall), " .cfi_startproc bti c diff --git a/crates/runtime/src/trampolines/riscv64.rs b/crates/runtime/src/trampolines/riscv64.rs index 456800594367..e3b06863b217 100644 --- a/crates/runtime/src/trampolines/riscv64.rs +++ b/crates/runtime/src/trampolines/riscv64.rs @@ -2,7 +2,7 @@ macro_rules! wasm_to_libcall_trampoline { ($libcall:ident ; $libcall_impl:ident) => { wasmtime_asm_macros::asm_func!( - stringify!($libcall), + wasmtime_versioned_export_macros::versioned_stringify_ident!($libcall), concat!( " .cfi_startproc diff --git a/crates/runtime/src/trampolines/s390x.S b/crates/runtime/src/trampolines/s390x.S index e014e1205082..b6b8bf01d0c2 100644 --- a/crates/runtime/src/trampolines/s390x.S +++ b/crates/runtime/src/trampolines/s390x.S @@ -9,12 +9,16 @@ .type host_to_wasm_trampoline,@function .p2align 2 +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) + #define LIBCALL_TRAMPOLINE(libcall, libcall_impl) \ - .hidden libcall ; \ - .globl libcall ; \ - .type libcall,@function ; \ + .hidden VERSIONED_SYMBOL(libcall) ; \ + .globl VERSIONED_SYMBOL(libcall) ; \ + .type VERSIONED_SYMBOL(libcall),@function ; \ .p2align 2 ; \ -libcall: ; \ +VERSIONED_SYMBOL(libcall): ; \ .cfi_startproc ; \ \ /* Load the pointer to `VMRuntimeLimits` in `%r1`. */ \ @@ -28,10 +32,10 @@ libcall: ; stg %r14, 32(%r1) ; \ \ /* Tail call to the actual implementation of this libcall. */ \ - jg libcall_impl ; \ + jg VERSIONED_SYMBOL(libcall_impl) ; \ \ .cfi_endproc ; \ - .size libcall,.-libcall + .size VERSIONED_SYMBOL(libcall),.-VERSIONED_SYMBOL(libcall) LIBCALL_TRAMPOLINE(memory32_grow, impl_memory32_grow) LIBCALL_TRAMPOLINE(table_grow_func_ref, impl_table_grow_func_ref) diff --git a/crates/runtime/src/trampolines/x86_64.rs b/crates/runtime/src/trampolines/x86_64.rs index d5af4446dc71..d22bcaf1a0e3 100644 --- a/crates/runtime/src/trampolines/x86_64.rs +++ b/crates/runtime/src/trampolines/x86_64.rs @@ -21,7 +21,7 @@ cfg_if::cfg_if! { macro_rules! wasm_to_libcall_trampoline { ($libcall:ident ; $libcall_impl:ident) => { wasmtime_asm_macros::asm_func!( - stringify!($libcall), + wasmtime_versioned_export_macros::versioned_stringify_ident!($libcall), concat!( " .cfi_startproc simple diff --git a/crates/runtime/src/traphandlers.rs b/crates/runtime/src/traphandlers.rs index 25d852671ba5..c43c9779f3b2 100644 --- a/crates/runtime/src/traphandlers.rs +++ b/crates/runtime/src/traphandlers.rs @@ -24,6 +24,7 @@ cfg_if::cfg_if! { struct WasmtimeLongjmp; + #[wasmtime_versioned_export_macros::versioned_export] unsafe extern "C" fn wasmtime_setjmp( _jmp_buf: *mut *const u8, callback: extern "C" fn(*mut u8, *mut VMContext), @@ -46,12 +47,14 @@ cfg_if::cfg_if! { } } + #[wasmtime_versioned_export_macros::versioned_export] unsafe extern "C" fn wasmtime_longjmp(_jmp_buf: *const u8) -> ! { std::panic::panic_any(WasmtimeLongjmp) } } else { #[link(name = "wasmtime-helpers")] extern "C" { + #[wasmtime_versioned_export_macros::versioned_link] #[allow(improper_ctypes)] fn wasmtime_setjmp( jmp_buf: *mut *const u8, @@ -59,6 +62,7 @@ cfg_if::cfg_if! { payload: *mut u8, callee: *mut VMContext, ) -> i32; + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_longjmp(jmp_buf: *const u8) -> !; } } diff --git a/crates/test-programs/tests/command.rs b/crates/test-programs/tests/command.rs index f16f14405413..3473a7c9ddba 100644 --- a/crates/test-programs/tests/command.rs +++ b/crates/test-programs/tests/command.rs @@ -9,11 +9,11 @@ use wasmtime::{ Config, Engine, Store, }; use wasmtime_wasi::preview2::{ - clocks::{WasiMonotonicClock, WasiWallClock}, + clocks::{HostMonotonicClock, HostWallClock}, pipe::ReadPipe, wasi::command::add_to_linker, wasi::command::Command, - DirPerms, FilePerms, Table, WasiClocks, WasiCtx, WasiCtxBuilder, WasiView, + DirPerms, FilePerms, Table, WasiCtx, WasiCtxBuilder, WasiView, }; lazy_static::lazy_static! { @@ -131,7 +131,7 @@ async fn random() -> Result<()> { async fn time() -> Result<()> { struct FakeWallClock; - impl WasiWallClock for FakeWallClock { + impl HostWallClock for FakeWallClock { fn resolution(&self) -> Duration { Duration::from_secs(1) } @@ -145,7 +145,7 @@ async fn time() -> Result<()> { now: Mutex, } - impl WasiMonotonicClock for FakeMonotonicClock { + impl HostMonotonicClock for FakeMonotonicClock { fn resolution(&self) -> u64 { 1_000_000_000 } @@ -160,10 +160,8 @@ async fn time() -> Result<()> { let mut table = Table::new(); let wasi = WasiCtxBuilder::new() - .set_clocks(WasiClocks { - wall: Box::new(FakeWallClock), - monotonic: Box::new(FakeMonotonicClock { now: Mutex::new(0) }), - }) + .set_monotonic_clock(FakeMonotonicClock { now: Mutex::new(0) }) + .set_wall_clock(FakeWallClock) .build(&mut table)?; let (mut store, command) = diff --git a/crates/versioned-export-macros/Cargo.toml b/crates/versioned-export-macros/Cargo.toml new file mode 100644 index 000000000000..e8e3318231f8 --- /dev/null +++ b/crates/versioned-export-macros/Cargo.toml @@ -0,0 +1,18 @@ +[package] +authors = ["The Wasmtime Project Developers"] +description = "Macros for defining versioned exports in Wasmtime" +edition.workspace = true +license = "Apache-2.0 WITH LLVM-exception" +name = "wasmtime-versioned-export-macros" +repository = "https://github.com/bytecodealliance/wasmtime" +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +syn = { version = "2.0", features = ["full"] } +quote = "1.0" +proc-macro2 = "1.0" + +[lib] +proc-macro = true diff --git a/crates/versioned-export-macros/src/lib.rs b/crates/versioned-export-macros/src/lib.rs new file mode 100644 index 000000000000..065a0fc501f4 --- /dev/null +++ b/crates/versioned-export-macros/src/lib.rs @@ -0,0 +1,66 @@ +//! This crate defines macros to easily define and use functions with a +//! versioned suffix, to facilitate using multiple versions of the same +//! crate that generate assembly. + +use quote::ToTokens; + +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +fn version(value: impl std::fmt::Display) -> String { + format!("{}_{}", value, VERSION.replace('.', "_")) +} + +fn versioned_lit_str(value: impl std::fmt::Display) -> syn::LitStr { + syn::LitStr::new(version(value).as_str(), proc_macro2::Span::call_site()) +} + +#[proc_macro_attribute] +pub fn versioned_export( + _attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let mut function = syn::parse_macro_input!(item as syn::ItemFn); + + let export_name = versioned_lit_str(&function.sig.ident); + function + .attrs + .push(syn::parse_quote! { #[export_name = #export_name] }); + + function.to_token_stream().into() +} + +#[proc_macro_attribute] +pub fn versioned_link( + _attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let mut function = syn::parse_macro_input!(item as syn::ForeignItemFn); + + let link_name = versioned_lit_str(&function.sig.ident); + function + .attrs + .push(syn::parse_quote! { #[link_name = #link_name] }); + + function.to_token_stream().into() +} + +#[proc_macro] +pub fn versioned_stringify_ident(item: proc_macro::TokenStream) -> proc_macro::TokenStream { + let ident = syn::parse_macro_input!(item as syn::Ident); + + versioned_lit_str(ident).to_token_stream().into() +} + +#[proc_macro] +pub fn versioned_suffix(item: proc_macro::TokenStream) -> proc_macro::TokenStream { + if !item.is_empty() { + return syn::Error::new( + proc_macro2::Span::call_site(), + "`versioned_suffix!` accepts no input", + ) + .to_compile_error() + .into(); + }; + + versioned_lit_str("").to_token_stream().into() +} diff --git a/crates/wasi/src/preview2/clocks.rs b/crates/wasi/src/preview2/clocks.rs index edfa764c946f..53bca0507058 100644 --- a/crates/wasi/src/preview2/clocks.rs +++ b/crates/wasi/src/preview2/clocks.rs @@ -1,17 +1,12 @@ pub mod host; use cap_std::time::Duration; -pub trait WasiWallClock: Send + Sync { +pub trait HostWallClock: Send + Sync { fn resolution(&self) -> Duration; fn now(&self) -> Duration; } -pub trait WasiMonotonicClock: Send + Sync { +pub trait HostMonotonicClock: Send + Sync { fn resolution(&self) -> u64; fn now(&self) -> u64; } - -pub struct WasiClocks { - pub wall: Box, - pub monotonic: Box, -} diff --git a/crates/wasi/src/preview2/clocks/host.rs b/crates/wasi/src/preview2/clocks/host.rs index 965f7a4a4c9f..e0c9906c7598 100644 --- a/crates/wasi/src/preview2/clocks/host.rs +++ b/crates/wasi/src/preview2/clocks/host.rs @@ -1,4 +1,4 @@ -use super::{WasiClocks, WasiMonotonicClock, WasiWallClock}; +use super::{HostMonotonicClock, HostWallClock}; use cap_std::time::{Duration, Instant, SystemClock}; use cap_std::{ambient_authority, AmbientAuthority}; use cap_time_ext::{MonotonicClockExt, SystemClockExt}; @@ -16,7 +16,7 @@ impl WallClock { } } -impl WasiWallClock for WallClock { +impl HostWallClock for WallClock { fn resolution(&self) -> Duration { self.clock.resolution() } @@ -47,7 +47,7 @@ impl MonotonicClock { } } -impl WasiMonotonicClock for MonotonicClock { +impl HostMonotonicClock for MonotonicClock { fn resolution(&self) -> u64 { self.clock.resolution().as_nanos().try_into().unwrap() } @@ -64,10 +64,10 @@ impl WasiMonotonicClock for MonotonicClock { } } -pub fn clocks_ctx() -> WasiClocks { - // Create the per-instance clock resources. - let monotonic = Box::new(MonotonicClock::new(ambient_authority())); - let wall = Box::new(WallClock::new(ambient_authority())); +pub fn monotonic_clock() -> Box { + Box::new(MonotonicClock::new(ambient_authority())) +} - WasiClocks { monotonic, wall } +pub fn wall_clock() -> Box { + Box::new(WallClock::new(ambient_authority())) } diff --git a/crates/wasi/src/preview2/ctx.rs b/crates/wasi/src/preview2/ctx.rs index 681d4860b30a..ab5109afa9bc 100644 --- a/crates/wasi/src/preview2/ctx.rs +++ b/crates/wasi/src/preview2/ctx.rs @@ -1,5 +1,5 @@ use crate::preview2::{ - clocks::{self, WasiClocks}, + clocks::{self, HostMonotonicClock, HostWallClock}, filesystem::{Dir, TableFsExt}, pipe, random, stdio, stream::{InputStream, OutputStream, TableStreamExt}, @@ -7,6 +7,8 @@ use crate::preview2::{ }; use cap_rand::{Rng, RngCore, SeedableRng}; +use super::clocks::host::{monotonic_clock, wall_clock}; + pub struct WasiCtxBuilder { stdin: Box, stdout: Box, @@ -18,7 +20,8 @@ pub struct WasiCtxBuilder { random: Box, insecure_random: Box, insecure_random_seed: u128, - clocks: WasiClocks, + wall_clock: Box, + monotonic_clock: Box, } impl WasiCtxBuilder { @@ -43,7 +46,8 @@ impl WasiCtxBuilder { random: random::thread_rng(), insecure_random, insecure_random_seed, - clocks: clocks::host::clocks_ctx(), + wall_clock: wall_clock(), + monotonic_clock: monotonic_clock(), } } @@ -155,8 +159,14 @@ impl WasiCtxBuilder { self.insecure_random_seed = insecure_random_seed; self } - pub fn set_clocks(mut self, clocks: WasiClocks) -> Self { - self.clocks = clocks; + + pub fn set_wall_clock(mut self, clock: impl clocks::HostWallClock + 'static) -> Self { + self.wall_clock = Box::new(clock); + self + } + + pub fn set_monotonic_clock(mut self, clock: impl clocks::HostMonotonicClock + 'static) -> Self { + self.monotonic_clock = Box::new(clock); self } @@ -172,7 +182,8 @@ impl WasiCtxBuilder { random, insecure_random, insecure_random_seed, - clocks, + wall_clock, + monotonic_clock, } = self; let stdin = table.push_input_stream(stdin).context("stdin")?; @@ -199,7 +210,8 @@ impl WasiCtxBuilder { random, insecure_random, insecure_random_seed, - clocks, + wall_clock, + monotonic_clock, }) } } @@ -215,7 +227,8 @@ pub struct WasiCtx { pub(crate) random: Box, pub(crate) insecure_random: Box, pub(crate) insecure_random_seed: u128, - pub(crate) clocks: WasiClocks, + pub(crate) wall_clock: Box, + pub(crate) monotonic_clock: Box, pub(crate) env: Vec<(String, String)>, pub(crate) args: Vec, pub(crate) preopens: Vec<(u32, String)>, diff --git a/crates/wasi/src/preview2/mod.rs b/crates/wasi/src/preview2/mod.rs index 04816de7f279..f2b00ee17b26 100644 --- a/crates/wasi/src/preview2/mod.rs +++ b/crates/wasi/src/preview2/mod.rs @@ -36,7 +36,7 @@ pub mod wasi; pub use cap_fs_ext::SystemTimeSpec; pub use cap_rand::RngCore; -pub use clocks::{WasiClocks, WasiMonotonicClock, WasiWallClock}; +pub use clocks::{HostMonotonicClock, HostWallClock}; pub use ctx::{WasiCtx, WasiCtxBuilder, WasiView}; pub use error::I32Exit; pub use filesystem::{DirPerms, FilePerms}; diff --git a/crates/wasi/src/preview2/preview2/clocks.rs b/crates/wasi/src/preview2/preview2/clocks.rs index 75d2927515eb..0693f09f5c4b 100644 --- a/crates/wasi/src/preview2/preview2/clocks.rs +++ b/crates/wasi/src/preview2/preview2/clocks.rs @@ -27,7 +27,7 @@ impl TryFrom for Datetime { #[async_trait::async_trait] impl wall_clock::Host for T { async fn now(&mut self) -> anyhow::Result { - let now = self.ctx().clocks.wall.now(); + let now = self.ctx().wall_clock.now(); Ok(Datetime { seconds: now.as_secs(), nanoseconds: now.subsec_nanos(), @@ -35,7 +35,7 @@ impl wall_clock::Host for T { } async fn resolution(&mut self) -> anyhow::Result { - let res = self.ctx().clocks.wall.resolution(); + let res = self.ctx().wall_clock.resolution(); Ok(Datetime { seconds: res.as_secs(), nanoseconds: res.subsec_nanos(), @@ -46,11 +46,11 @@ impl wall_clock::Host for T { #[async_trait::async_trait] impl monotonic_clock::Host for T { async fn now(&mut self) -> anyhow::Result { - Ok(self.ctx().clocks.monotonic.now()) + Ok(self.ctx().monotonic_clock.now()) } async fn resolution(&mut self) -> anyhow::Result { - Ok(self.ctx().clocks.monotonic.resolution()) + Ok(self.ctx().monotonic_clock.resolution()) } async fn subscribe(&mut self, when: Instant, absolute: bool) -> anyhow::Result { diff --git a/crates/wasi/src/preview2/preview2/poll.rs b/crates/wasi/src/preview2/preview2/poll.rs index 338b83518eb1..58a7407eff7b 100644 --- a/crates/wasi/src/preview2/preview2/poll.rs +++ b/crates/wasi/src/preview2/preview2/poll.rs @@ -56,7 +56,7 @@ impl poll::Host for T { } PollableEntry::MonotonicClock(when, absolute) => { poll.subscribe_monotonic_clock( - &*self.ctx().clocks.monotonic, + &*self.ctx().monotonic_clock, when, absolute, userdata, diff --git a/crates/wasi/src/preview2/sched.rs b/crates/wasi/src/preview2/sched.rs index 4d4494e2efb0..23e6756b5be9 100644 --- a/crates/wasi/src/preview2/sched.rs +++ b/crates/wasi/src/preview2/sched.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] use crate::preview2::{ - clocks::WasiMonotonicClock, + clocks::HostMonotonicClock, stream::{InputStream, OutputStream}, }; use anyhow::Error; @@ -43,7 +43,7 @@ impl<'a> Poll<'a> { } pub fn subscribe_monotonic_clock( &mut self, - clock: &'a dyn WasiMonotonicClock, + clock: &'a dyn HostMonotonicClock, deadline: u64, absolute: bool, ud: Userdata, diff --git a/crates/wasi/src/preview2/sched/subscription.rs b/crates/wasi/src/preview2/sched/subscription.rs index feffe893ccd7..7d6f95fd6c24 100644 --- a/crates/wasi/src/preview2/sched/subscription.rs +++ b/crates/wasi/src/preview2/sched/subscription.rs @@ -1,5 +1,5 @@ use crate::preview2::{ - clocks::WasiMonotonicClock, + clocks::HostMonotonicClock, stream::{InputStream, OutputStream}, }; use anyhow::Error; @@ -61,7 +61,7 @@ impl<'a> RwSubscription<'a> { } pub struct MonotonicClockSubscription<'a> { - pub clock: &'a dyn WasiMonotonicClock, + pub clock: &'a dyn HostMonotonicClock, pub absolute_deadline: u64, } diff --git a/crates/wasmtime/src/compiler.rs b/crates/wasmtime/src/compiler.rs index 069c6b51db41..8a118c38cbd4 100644 --- a/crates/wasmtime/src/compiler.rs +++ b/crates/wasmtime/src/compiler.rs @@ -24,12 +24,11 @@ use crate::Engine; use anyhow::Result; -use std::collections::{btree_map, BTreeMap}; +use std::collections::{btree_map, BTreeMap, BTreeSet}; use std::{any::Any, collections::HashMap}; use wasmtime_environ::{ - Compiler, DefinedFuncIndex, FuncIndex, FunctionBodyData, FunctionLoc, ModuleTranslation, - ModuleType, ModuleTypes, PrimaryMap, SignatureIndex, StaticModuleIndex, Tunables, - WasmFunctionInfo, + Compiler, DefinedFuncIndex, FuncIndex, FunctionBodyData, ModuleTranslation, ModuleType, + ModuleTypes, PrimaryMap, SignatureIndex, StaticModuleIndex, Tunables, WasmFunctionInfo, }; use wasmtime_jit::{CompiledFunctionInfo, CompiledModuleInfo}; @@ -258,9 +257,7 @@ impl<'a> CompileInputs<'a> { wasmtime_environ::component::GlobalInitializer::InstantiateModule(_) | wasmtime_environ::component::GlobalInitializer::ExtractMemory(_) | wasmtime_environ::component::GlobalInitializer::ExtractRealloc(_) - | wasmtime_environ::component::GlobalInitializer::ExtractPostReturn(_) - | wasmtime_environ::component::GlobalInitializer::SaveStaticModule(_) - | wasmtime_environ::component::GlobalInitializer::SaveModuleImport(_) => { + | wasmtime_environ::component::GlobalInitializer::ExtractPostReturn(_) => { // Nothing to compile for these. } } @@ -588,6 +585,13 @@ impl FunctionIndices { .remove(&CompileKey::NATIVE_TO_WASM_TRAMPOLINE_KIND) .unwrap_or_default(); + // NB: unlike the above maps this is not emptied out during iteration + // since each module may reach into different portions of this map. + let wasm_to_native_trampolines = self + .indices + .remove(&CompileKey::WASM_TO_NATIVE_TRAMPOLINE_KIND) + .unwrap_or_default(); + artifacts.modules = translations .into_iter() .map(|(module, translation)| { @@ -621,16 +625,21 @@ impl FunctionIndices { }) .collect(); - let wasm_to_native_trampolines: Vec<(SignatureIndex, FunctionLoc)> = self - .indices - .remove(&CompileKey::WASM_TO_NATIVE_TRAMPOLINE_KIND) - .into_iter() - .flat_map(|x| x) - .map(|(key, i)| { - ( - SignatureIndex::from_u32(key.index), - symbol_ids_and_locs[i.unwrap_function()].1, - ) + let unique_and_sorted_sigs = translation + .module + .types + .iter() + .map(|(_, ty)| match ty { + ModuleType::Function(ty) => *ty, + ModuleType::Continuation(ty) => *ty, + }) + .collect::>(); + let wasm_to_native_trampolines = unique_and_sorted_sigs + .iter() + .map(|idx| { + let key = CompileKey::wasm_to_native_trampoline(*idx); + let compiled = wasm_to_native_trampolines[&key]; + (*idx, symbol_ids_and_locs[compiled.unwrap_function()].1) }) .collect(); @@ -680,17 +689,17 @@ pub struct Artifacts { #[cfg(feature = "component-model")] pub lowerings: PrimaryMap< wasmtime_environ::component::LoweredIndex, - wasmtime_environ::component::AllCallFunc, + wasmtime_environ::component::AllCallFunc, >, #[cfg(feature = "component-model")] pub always_traps: PrimaryMap< wasmtime_environ::component::RuntimeAlwaysTrapIndex, - wasmtime_environ::component::AllCallFunc, + wasmtime_environ::component::AllCallFunc, >, #[cfg(feature = "component-model")] pub transcoders: PrimaryMap< wasmtime_environ::component::RuntimeTranscoderIndex, - wasmtime_environ::component::AllCallFunc, + wasmtime_environ::component::AllCallFunc, >, } diff --git a/crates/wasmtime/src/component/instance.rs b/crates/wasmtime/src/component/instance.rs index f8e8f1dd2e74..2eeacd451596 100644 --- a/crates/wasmtime/src/component/instance.rs +++ b/crates/wasmtime/src/component/instance.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use wasmtime_environ::component::{ AlwaysTrap, ComponentTypes, CoreDef, CoreExport, Export, ExportItem, ExtractMemory, ExtractPostReturn, ExtractRealloc, GlobalInitializer, InstantiateModule, LowerImport, - RuntimeImportIndex, RuntimeInstanceIndex, RuntimeModuleIndex, Transcoder, + RuntimeImportIndex, RuntimeInstanceIndex, Transcoder, }; use wasmtime_environ::{EntityIndex, EntityType, Global, PrimaryMap, WasmType}; use wasmtime_runtime::component::{ComponentInstance, OwnedComponentInstance}; @@ -30,20 +30,35 @@ pub struct Instance(pub(crate) Stored>>); pub(crate) struct InstanceData { instances: PrimaryMap, - // FIXME: shouldn't store the entire component here which keeps upvars - // alive and things like that, instead only the bare minimum necessary - // should be kept alive here (mostly just `wasmtime_environ::Component`). + + // NB: in the future if necessary it would be possible to avoid storing an + // entire `Component` here and instead storing only information such as: + // + // * Some reference to `Arc` + // * Necessary references to closed-over modules which are exported from the + // component itself. + // + // Otherwise the full guts of this component should only ever be used during + // the instantiation of this instance, meaning that after instantiation much + // of the component can be thrown away (theoretically). component: Component, - exported_modules: PrimaryMap, state: OwnedComponentInstance, - /// Functions that this instance used during instantiation. + /// Arguments that this instance used to be instantiated. + /// + /// Strong references are stored to these arguments since pointers are saved + /// into the structures such as functions within the + /// `OwnedComponentInstance` but it's our job to keep them alive. /// - /// Strong references are stored to these functions since pointers are saved - /// into the functions within the `OwnedComponentInstance` but it's our job - /// to keep them alive. - funcs: Vec>, + /// One purpose of this storage is to enable embedders to drop a `Linker`, + /// for example, after a component is instantiated. In that situation if the + /// arguments weren't held here then they might be dropped, and structures + /// such as `.lowering()` which point back into the original function would + /// become stale and use-after-free conditions when used. By preserving the + /// entire list here though we're guaranteed that nothing is lost for the + /// duration of the lifetime of this instance. + imports: Arc>, } impl Instance { @@ -205,7 +220,7 @@ impl<'a> Instantiator<'a> { fn new( component: &'a Component, store: &mut StoreOpaque, - imports: &'a PrimaryMap, + imports: &'a Arc>, ) -> Instantiator<'a> { let env_component = component.env_component(); store.modules_mut().register_component(component); @@ -216,11 +231,8 @@ impl<'a> Instantiator<'a> { data: InstanceData { instances: PrimaryMap::with_capacity(env_component.num_runtime_instances as usize), component: component.clone(), - exported_modules: PrimaryMap::with_capacity( - env_component.num_runtime_modules as usize, - ), state: OwnedComponentInstance::new(component.runtime_info(), store.traitobj()), - funcs: Vec::new(), + imports: imports.clone(), }, } } @@ -288,19 +300,6 @@ impl<'a> Instantiator<'a> { self.extract_post_return(store.0, post_return) } - GlobalInitializer::SaveStaticModule(idx) => { - self.data - .exported_modules - .push(self.component.static_module(*idx).clone()); - } - - GlobalInitializer::SaveModuleImport(idx) => { - self.data.exported_modules.push(match &self.imports[*idx] { - RuntimeImport::Module(m) => m.clone(), - _ => unreachable!(), - }); - } - GlobalInitializer::Transcoder(e) => self.transcoder(e), } } @@ -330,15 +329,6 @@ impl<'a> Instantiator<'a> { array_call, type_index, ); - - // The `func` provided here must be retained within the `Store` itself - // after instantiation. Otherwise it might be possible to drop the - // `Arc` and possibly result in a use-after-free. This comes - // about because the `.lowering()` method returns a structure that - // points to an interior pointer within the `func`. By saving the list - // of host functions used we can ensure that the function lives long - // enough for the whole duration of this instance. - self.data.funcs.push(func.clone()); } fn always_trap(&mut self, trap: &AlwaysTrap) { @@ -440,7 +430,7 @@ impl<'a> Instantiator<'a> { } fn assert_type_matches( - &mut self, + &self, store: &mut StoreOpaque, module: &Module, arg: &CoreDef, @@ -485,7 +475,7 @@ impl<'a> Instantiator<'a> { /// method. pub struct InstancePre { component: Component, - imports: PrimaryMap, + imports: Arc>, _marker: marker::PhantomData T>, } @@ -513,7 +503,7 @@ impl InstancePre { ) -> InstancePre { InstancePre { component, - imports, + imports: Arc::new(imports), _marker: marker::PhantomData, } } @@ -649,7 +639,10 @@ impl<'a, 'store> ExportInstance<'a, 'store> { func, options, )), - Export::Module(_) | Export::Instance(_) | Export::Type(_) => None, + Export::ModuleStatic(_) + | Export::ModuleImport(_) + | Export::Instance(_) + | Export::Type(_) => None, } } @@ -670,7 +663,11 @@ impl<'a, 'store> ExportInstance<'a, 'store> { /// Same as [`Instance::get_module`] pub fn module(&mut self, name: &str) -> Option<&'a Module> { match self.exports.get(name)? { - Export::Module(idx) => Some(&self.data.exported_modules[*idx]), + Export::ModuleStatic(idx) => Some(&self.data.component.static_module(*idx)), + Export::ModuleImport(idx) => Some(match &self.data.imports[*idx] { + RuntimeImport::Module(m) => m, + _ => unreachable!(), + }), _ => None, } } @@ -688,12 +685,17 @@ impl<'a, 'store> ExportInstance<'a, 'store> { // For now this is just quick-and-dirty to get wast support for iterating // over exported modules to work. pub fn modules(&self) -> impl Iterator + '_ { - self.exports - .iter() - .filter_map(|(name, export)| match *export { - Export::Module(idx) => Some((name.as_str(), &self.data.exported_modules[idx])), - _ => None, - }) + self.exports.iter().filter_map(|(name, export)| { + let module = match *export { + Export::ModuleStatic(idx) => self.data.component.static_module(idx), + Export::ModuleImport(idx) => match &self.data.imports[idx] { + RuntimeImport::Module(m) => m, + _ => unreachable!(), + }, + _ => return None, + }; + Some((name.as_str(), module)) + }) } fn as_mut(&mut self) -> ExportInstance<'a, '_> { diff --git a/crates/wasmtime/src/component/linker.rs b/crates/wasmtime/src/component/linker.rs index cf2bbb302cca..c97308fa0685 100644 --- a/crates/wasmtime/src/component/linker.rs +++ b/crates/wasmtime/src/component/linker.rs @@ -4,9 +4,11 @@ use crate::component::matching::TypeChecker; use crate::component::{Component, ComponentNamedList, Instance, InstancePre, Lift, Lower, Val}; use crate::{AsContextMut, Engine, Module, StoreContextMut}; use anyhow::{anyhow, bail, Context, Result}; +use indexmap::IndexMap; use std::collections::hash_map::{Entry, HashMap}; use std::future::Future; use std::marker; +use std::ops::Deref; use std::pin::Pin; use std::sync::Arc; use wasmtime_environ::component::TypeDef; @@ -22,6 +24,7 @@ pub struct Linker { engine: Engine, strings: Strings, map: NameMap, + path: Vec, allow_shadowing: bool, _marker: marker::PhantomData T>, } @@ -38,7 +41,9 @@ pub struct Strings { /// a "bag of named items", so each [`LinkerInstance`] can further define items /// internally. pub struct LinkerInstance<'a, T> { - engine: Engine, + engine: &'a Engine, + path: &'a mut Vec, + path_len: usize, strings: &'a mut Strings, map: &'a mut NameMap, allow_shadowing: bool, @@ -63,6 +68,7 @@ impl Linker { strings: Strings::default(), map: NameMap::default(), allow_shadowing: false, + path: Vec::new(), _marker: marker::PhantomData, } } @@ -85,7 +91,9 @@ impl Linker { /// the root namespace. pub fn root(&mut self) -> LinkerInstance<'_, T> { LinkerInstance { - engine: self.engine.clone(), + engine: &self.engine, + path: &mut self.path, + path_len: 0, strings: &mut self.strings, map: &mut self.map, allow_shadowing: self.allow_shadowing, @@ -230,7 +238,9 @@ impl Linker { impl LinkerInstance<'_, T> { fn as_mut(&mut self) -> LinkerInstance<'_, T> { LinkerInstance { - engine: self.engine.clone(), + engine: self.engine, + path: self.path, + path_len: self.path_len, strings: self.strings, map: self.map, allow_shadowing: self.allow_shadowing, @@ -310,21 +320,39 @@ impl LinkerInstance<'_, T> { name: &str, func: F, ) -> Result<()> { - for (import_name, ty) in component.env_component().import_types.values() { - if name == import_name { - if let TypeDef::ComponentFunc(index) = ty { - let name = self.strings.intern(name); - return self.insert( - name, - Definition::Func(HostFunc::new_dynamic(func, *index, component.types())), - ); + let mut map = &component + .env_component() + .import_types + .values() + .map(|(k, v)| (k.clone(), *v)) + .collect::>(); + + for name in self.path.iter().copied().take(self.path_len) { + let name = self.strings.strings[name].deref(); + if let Some(ty) = map.get(name) { + if let TypeDef::ComponentInstance(index) = ty { + map = &component.types()[*index].exports; } else { - bail!("import `{name}` has the wrong type (expected a function)"); + bail!("import `{name}` has the wrong type (expected a component instance)"); } + } else { + bail!("import `{name}` not found"); } } - Err(anyhow!("import `{name}` not found")) + if let Some(ty) = map.get(name) { + if let TypeDef::ComponentFunc(index) = ty { + let name = self.strings.intern(name); + return self.insert( + name, + Definition::Func(HostFunc::new_dynamic(func, *index, component.types())), + ); + } else { + bail!("import `{name}` has the wrong type (expected a function)"); + } + } else { + Err(anyhow!("import `{name}` not found")) + } } // TODO: define func_new_async @@ -367,6 +395,9 @@ impl LinkerInstance<'_, T> { Definition::Instance(map) => map, _ => unreachable!(), }; + self.path.truncate(self.path_len); + self.path.push(name); + self.path_len += 1; Ok(self) } diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 9350ffbd8bbc..697e62a42ba0 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -666,36 +666,11 @@ pub struct InstancePre { /// instantiation time. /// /// This is an `Arc<[T]>` for the same reason as `items`. - func_refs: Arc<[PrePatchedFuncRef]>, + func_refs: Arc<[VMFuncRef]>, _marker: std::marker::PhantomData T>, } -pub(crate) use pre_patched_func_ref::PrePatchedFuncRef; -mod pre_patched_func_ref { - use super::*; - - pub struct PrePatchedFuncRef(VMFuncRef); - - impl PrePatchedFuncRef { - /// Safety: callers must arrange for the given `func_ref` to be usable - /// in a `Send + Sync` manner (i.e. its associated `Module` is kept - /// alive or `Func` is alive and supports these things) and that the - /// `wasm_call` field is already patched in, if necessary. - pub unsafe fn new(func_ref: VMFuncRef) -> PrePatchedFuncRef { - PrePatchedFuncRef(func_ref) - } - - pub fn func_ref(&self) -> &VMFuncRef { - &self.0 - } - } - - // Safety: This is upheld by `PrePatchedFuncRef::new` callers. - unsafe impl Send for InstancePre {} - unsafe impl Sync for InstancePre {} -} - /// InstancePre's clone does not require T: Clone impl Clone for InstancePre { fn clone(&self) -> Self { @@ -732,12 +707,12 @@ impl InstancePre { // `f` needs its `VMFuncRef::wasm_call` // patched with a Wasm-to-native trampoline. debug_assert!(matches!(f.host_ctx(), crate::HostContext::Native(_))); - func_refs.push(PrePatchedFuncRef::new(VMFuncRef { + func_refs.push(VMFuncRef { wasm_call: module .runtime_info() .wasm_to_native_trampoline(f.sig_index()), ..*f.func_ref() - })); + }); } } } @@ -835,7 +810,7 @@ fn pre_instantiate_raw( module: &Module, items: &Arc<[Definition]>, host_funcs: usize, - func_refs: &Arc<[PrePatchedFuncRef]>, + func_refs: &Arc<[VMFuncRef]>, ) -> Result { if host_funcs > 0 { // Any linker-defined function of the `Definition::HostFunc` variant @@ -852,7 +827,7 @@ fn pre_instantiate_raw( store.push_instance_pre_func_refs(func_refs.clone()); } - let mut func_refs = func_refs.iter().map(|f| NonNull::from(f.func_ref())); + let mut func_refs = func_refs.iter().map(|f| NonNull::from(f)); let mut imports = OwnedImports::new(module); for import in items.iter() { if !import.comes_from_same_store(store) { diff --git a/crates/wasmtime/src/store.rs b/crates/wasmtime/src/store.rs index 930a73ee93aa..df3f6d0231f7 100644 --- a/crates/wasmtime/src/store.rs +++ b/crates/wasmtime/src/store.rs @@ -76,7 +76,6 @@ //! contents of `StoreOpaque`. This is an invariant that we, as the authors of //! `wasmtime`, must uphold for the public interface to be safe. -use crate::instance::PrePatchedFuncRef; use crate::linker::Definition; use crate::module::BareModuleInfo; use crate::trampoline::VMHostGlobalContext; @@ -97,7 +96,7 @@ use std::task::{Context, Poll}; use wasmtime_runtime::{ InstanceAllocationRequest, InstanceAllocator, InstanceHandle, ModuleInfo, OnDemandInstanceAllocator, SignalHandler, StoreBox, StorePtr, VMContext, VMExternRef, - VMExternRefActivationsTable, VMRuntimeLimits, WasmFault, + VMExternRefActivationsTable, VMFuncRef, VMRuntimeLimits, WasmFault, }; mod context; @@ -1215,7 +1214,7 @@ impl StoreOpaque { self.func_refs.fill(&mut self.modules); } - pub(crate) fn push_instance_pre_func_refs(&mut self, func_refs: Arc<[PrePatchedFuncRef]>) { + pub(crate) fn push_instance_pre_func_refs(&mut self, func_refs: Arc<[VMFuncRef]>) { self.func_refs.push_instance_pre_func_refs(func_refs); } diff --git a/crates/wasmtime/src/store/func_refs.rs b/crates/wasmtime/src/store/func_refs.rs index 16ab2c2226a7..b84849cdc29e 100644 --- a/crates/wasmtime/src/store/func_refs.rs +++ b/crates/wasmtime/src/store/func_refs.rs @@ -1,4 +1,4 @@ -use crate::{instance::PrePatchedFuncRef, module::ModuleRegistry}; +use crate::module::ModuleRegistry; use std::{ptr::NonNull, sync::Arc}; use wasmtime_runtime::{SendSyncPtr, VMFuncRef, VMNativeCallHostFuncContext}; @@ -20,7 +20,7 @@ pub struct FuncRefs { /// Pinned `VMFuncRef`s that had their `wasm_call` field /// pre-patched when constructing an `InstancePre`, and which we need to /// keep alive for our owning store's lifetime. - instance_pre_func_refs: Vec>, + instance_pre_func_refs: Vec>, } use send_sync_bump::SendSyncBump; @@ -79,7 +79,7 @@ impl FuncRefs { } /// Push pre-patched `VMFuncRef`s from an `InstancePre`. - pub fn push_instance_pre_func_refs(&mut self, func_refs: Arc<[PrePatchedFuncRef]>) { + pub fn push_instance_pre_func_refs(&mut self, func_refs: Arc<[VMFuncRef]>) { self.instance_pre_func_refs.push(func_refs); } } diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 52abd5788d8b..0e02f5c170f8 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -38,6 +38,7 @@ - [Using the `wasmtime` CLI](./cli.md) - [Installation](./cli-install.md) - [CLI Options](./cli-options.md) + - [CLI Logging](./cli-logging.md) - [Cache Configuration](./cli-cache.md) - [Writing WebAssembly](./wasm.md) - [Rust](./wasm-rust.md) diff --git a/fuzz/fuzz_targets/compile.rs b/fuzz/fuzz_targets/compile.rs index 93ff23c1b0c0..743ea9468bce 100644 --- a/fuzz/fuzz_targets/compile.rs +++ b/fuzz/fuzz_targets/compile.rs @@ -1,10 +1,12 @@ -//! Compile arbitrary bytes from the fuzzer as if they were Wasm. Also use -//! `wasm-mutate` to mutate the fuzz inputs. +//! Compile arbitrary bytes from the fuzzer as if they were Wasm, checking that +//! compilation is deterministic. +//! +//! Also use `wasm-mutate` to mutate the fuzz inputs. #![no_main] use libfuzzer_sys::{fuzz_mutator, fuzz_target}; -use wasmtime::{Config, Engine, Module}; +use wasmtime::{Config, Engine, Module, Result}; fn create_engine() -> Engine { let mut config = Config::default(); @@ -17,10 +19,24 @@ fn create_engine() -> Engine { Engine::new(&config).expect("Could not construct Engine") } +fn compile_and_serialize(engine: &Engine, wasm: &[u8]) -> Result> { + let module = Module::new(&engine, wasm)?; + module.serialize() +} + fuzz_target!(|data: &[u8]| { let engine = create_engine(); wasmtime_fuzzing::oracles::log_wasm(data); - drop(Module::new(&engine, data)); + + if let Ok(bytes1) = compile_and_serialize(&engine, data) { + let bytes2 = compile_and_serialize(&engine, data) + .expect("successfully compiled once, should successfully compile again"); + + // NB: Don't use `assert_eq!` here because it prints out the LHS and RHS + // to stderr on failure, which isn't helpful here since it is just a + // huge serialized binary. + assert!(bytes1 == bytes2, "Wasm compilation should be deterministic"); + } }); fuzz_mutator!(|data: &mut [u8], size: usize, max_size: usize, seed: u32| { diff --git a/fuzz/fuzz_targets/differential.rs b/fuzz/fuzz_targets/differential.rs index f7845803bbcf..f4d321faaa78 100644 --- a/fuzz/fuzz_targets/differential.rs +++ b/fuzz/fuzz_targets/differential.rs @@ -354,6 +354,9 @@ fn winch_supports_module(module: &[u8]) -> bool { | I64Popcnt { .. } | LocalGet { .. } | LocalSet { .. } + | LocalTee { .. } + | GlobalGet { .. } + | GlobalSet { .. } | Call { .. } | Nop { .. } | End { .. } diff --git a/scripts/publish.rs b/scripts/publish.rs index 513b0fea6099..29ccf1372ecf 100644 --- a/scripts/publish.rs +++ b/scripts/publish.rs @@ -45,6 +45,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[ "winch", // wasmtime "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", "wasmtime-component-util", "wasmtime-wit-bindgen", "wasmtime-component-macro", diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index fe0998ffd3f5..0575d71a9164 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -1607,6 +1607,15 @@ who = "Pat Hickey " criteria = "safe-to-deploy" delta = "1.0.51 -> 1.0.57" +[[audits.proc-macro2]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "1.0.59 -> 1.0.63" +notes = """ +This is a routine update for new nightly features and new syntax popping up on +nightly, nothing out of the ordinary. +""" + [[audits.pulldown-cmark]] who = "Alex Crichton " criteria = "safe-to-deploy" @@ -2648,6 +2657,132 @@ criteria = "safe-to-deploy" version = "0.6.4" notes = "The Bytecode Alliance is the author of this crate." +[[trusted.async-trait]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-07-23" +end = "2024-07-06" + +[[trusted.clap]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2021-12-08" +end = "2024-07-06" + +[[trusted.clap_derive]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2021-12-08" +end = "2024-07-06" + +[[trusted.clap_lex]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2022-04-15" +end = "2024-07-06" + +[[trusted.indexmap]] +criteria = "safe-to-deploy" +user-id = 539 # Josh Stone (cuviper) +start = "2020-01-15" +end = "2024-07-06" + +[[trusted.itoa]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-05-02" +end = "2024-07-06" + +[[trusted.libc]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2021-01-27" +end = "2024-07-06" + +[[trusted.libm]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2022-02-06" +end = "2024-07-06" + +[[trusted.lock_api]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-05-04" +end = "2024-07-06" + +[[trusted.parking_lot]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-05-04" +end = "2024-07-06" + +[[trusted.parking_lot_core]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-05-04" +end = "2024-07-06" + +[[trusted.paste]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-19" +end = "2024-07-06" + +[[trusted.ryu]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-05-02" +end = "2024-07-06" + +[[trusted.scopeguard]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2020-02-16" +end = "2024-07-06" + +[[trusted.serde]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2024-07-06" + +[[trusted.serde_derive]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2024-07-06" + +[[trusted.serde_json]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-02-28" +end = "2024-07-06" + +[[trusted.syn]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2024-07-06" + +[[trusted.thiserror]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-10-09" +end = "2024-07-06" + +[[trusted.thiserror-impl]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-10-09" +end = "2024-07-06" + +[[trusted.toml]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-05-16" +end = "2024-07-06" + [[trusted.windows-sys]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 3cc9326d6c23..37e7d2a74c14 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -148,6 +148,9 @@ audit-as-crates-io = true [policy.wasmtime-types] audit-as-crates-io = true +[policy.wasmtime-versioned-export-macros] +audit-as-crates-io = false + [policy.wasmtime-wasi] audit-as-crates-io = true @@ -218,10 +221,6 @@ criteria = "safe-to-deploy" version = "0.7.18" criteria = "safe-to-deploy" -[[exemptions.async-trait]] -version = "0.1.53" -criteria = "safe-to-deploy" - [[exemptions.autocfg]] version = "0.1.8" criteria = "safe-to-deploy" @@ -274,18 +273,6 @@ criteria = "safe-to-deploy" version = "0.3.0" criteria = "safe-to-deploy" -[[exemptions.clap]] -version = "3.2.8" -criteria = "safe-to-deploy" - -[[exemptions.clap_derive]] -version = "3.2.7" -criteria = "safe-to-deploy" - -[[exemptions.clap_lex]] -version = "0.2.4" -criteria = "safe-to-deploy" - [[exemptions.console]] version = "0.15.0" criteria = "safe-to-deploy" @@ -508,10 +495,6 @@ version = "1.0.0-rc.3" criteria = "safe-to-deploy" notes = "we are exempting tokio, hyper, and their tightly coupled dependencies by the same authors, expecting that the authors at aws will publish attestions we can import at some point soon" -[[exemptions.indexmap]] -version = "1.9.1" -criteria = "safe-to-deploy" - [[exemptions.indicatif]] version = "0.13.0" criteria = "safe-to-deploy" @@ -528,10 +511,6 @@ criteria = "safe-to-deploy" version = "0.10.3" criteria = "safe-to-deploy" -[[exemptions.itoa]] -version = "1.0.1" -criteria = "safe-to-deploy" - [[exemptions.jobserver]] version = "0.1.24" criteria = "safe-to-deploy" @@ -545,26 +524,14 @@ notes = "dependency of ring for wasm32 browser platform, which our project does version = "0.9.6" criteria = "safe-to-deploy" -[[exemptions.libc]] -version = "0.2.133" -criteria = "safe-to-deploy" - [[exemptions.libloading]] version = "0.7.3" criteria = "safe-to-deploy" -[[exemptions.libm]] -version = "0.2.2" -criteria = "safe-to-deploy" - [[exemptions.listenfd]] version = "1.0.0" criteria = "safe-to-deploy" -[[exemptions.lock_api]] -version = "0.4.7" -criteria = "safe-to-deploy" - [[exemptions.mach]] version = "0.3.2" criteria = "safe-to-deploy" @@ -638,18 +605,6 @@ criteria = "safe-to-deploy" version = "0.9.0" criteria = "safe-to-deploy" -[[exemptions.parking_lot]] -version = "0.11.2" -criteria = "safe-to-deploy" - -[[exemptions.parking_lot_core]] -version = "0.8.5" -criteria = "safe-to-deploy" - -[[exemptions.paste]] -version = "1.0.7" -criteria = "safe-to-deploy" - [[exemptions.pem-rfc7468]] version = "0.2.4" criteria = "safe-to-deploy" @@ -807,30 +762,10 @@ criteria = "safe-to-deploy" version = "0.3.0" criteria = "safe-to-deploy" -[[exemptions.ryu]] -version = "1.0.9" -criteria = "safe-to-deploy" - [[exemptions.same-file]] version = "1.0.6" criteria = "safe-to-deploy" -[[exemptions.scopeguard]] -version = "1.1.0" -criteria = "safe-to-deploy" - -[[exemptions.serde]] -version = "1.0.137" -criteria = "safe-to-deploy" - -[[exemptions.serde_derive]] -version = "1.0.137" -criteria = "safe-to-deploy" - -[[exemptions.serde_json]] -version = "1.0.80" -criteria = "safe-to-deploy" - [[exemptions.sha2]] version = "0.9.9" criteria = "safe-to-deploy" @@ -891,10 +826,6 @@ criteria = "safe-to-deploy" version = "5.0.3" criteria = "safe-to-run" -[[exemptions.syn]] -version = "1.0.92" -criteria = "safe-to-deploy" - [[exemptions.target-lexicon]] version = "0.12.3" criteria = "safe-to-deploy" @@ -915,14 +846,6 @@ criteria = "safe-to-deploy" version = "0.15.0" criteria = "safe-to-deploy" -[[exemptions.thiserror]] -version = "1.0.31" -criteria = "safe-to-deploy" - -[[exemptions.thiserror-impl]] -version = "1.0.31" -criteria = "safe-to-deploy" - [[exemptions.thread_local]] version = "1.1.4" criteria = "safe-to-run" @@ -940,10 +863,6 @@ notes = "we are exempting tokio, hyper, and their tightly coupled dependencies b version = "1.7.0" criteria = "safe-to-deploy" -[[exemptions.toml]] -version = "0.5.9" -criteria = "safe-to-deploy" - [[exemptions.tracing]] version = "0.1.34" criteria = "safe-to-deploy" @@ -969,7 +888,7 @@ version = "1.0.0" criteria = "safe-to-deploy" [[exemptions.v8]] -version = "0.44.3" +version = "0.74.1" criteria = "safe-to-run" [[exemptions.wait-timeout]] diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 028fe833bbbe..a66102b509d3 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -5,194 +5,386 @@ version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-bforest]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-bforest]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-codegen]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-codegen]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-codegen-meta]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-codegen-meta]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-codegen-shared]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-codegen-shared]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-control]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-control]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-entity]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-entity]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-frontend]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-frontend]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-interpreter]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-interpreter]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-isle]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-isle]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-jit]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-jit]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-module]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-module]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-native]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-native]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-object]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-object]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-reader]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-reader]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-serde]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-serde]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.cranelift-wasm]] version = "0.98.0" audited_as = "0.97.1" +[[unpublished.cranelift-wasm]] +version = "0.99.0" +audited_as = "0.97.1" + [[unpublished.wasi-cap-std-sync]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasi-cap-std-sync]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasi-common]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasi-common]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasi-tokio]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasi-tokio]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-asm-macros]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-asm-macros]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-cache]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-cache]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-cli]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-cli]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-cli-flags]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-cli-flags]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-component-macro]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-component-macro]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-component-util]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-component-util]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-cranelift]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-cranelift]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-cranelift-shared]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-cranelift-shared]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-environ]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-environ]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-explorer]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-explorer]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-fiber]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-fiber]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-jit]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-jit]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-jit-debug]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-jit-debug]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-jit-icache-coherence]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-jit-icache-coherence]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-runtime]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-runtime]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-types]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-types]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-wasi]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-wasi]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-wasi-crypto]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-wasi-crypto]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-wasi-http]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-wasi-http]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-wasi-nn]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-wasi-nn]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-wasi-threads]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-wasi-threads]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-wast]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-wast]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-winch]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-winch]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wasmtime-wit-bindgen]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wasmtime-wit-bindgen]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wiggle]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wiggle]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wiggle-generate]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wiggle-generate]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wiggle-macro]] version = "11.0.0" audited_as = "10.0.1" +[[unpublished.wiggle-macro]] +version = "12.0.0" +audited_as = "10.0.1" + [[unpublished.wiggle-test]] version = "0.0.0" audited_as = "0.1.0" @@ -201,6 +393,10 @@ audited_as = "0.1.0" version = "0.9.0" audited_as = "0.8.1" +[[unpublished.winch-codegen]] +version = "0.10.0" +audited_as = "0.8.1" + [[publisher.arbitrary]] version = "1.3.0" when = "2023-03-13" @@ -208,6 +404,13 @@ user-id = 696 user-login = "fitzgen" user-name = "Nick Fitzgerald" +[[publisher.async-trait]] +version = "0.1.53" +when = "2022-03-25" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + [[publisher.bumpalo]] version = "3.12.0" when = "2023-01-17" @@ -215,6 +418,27 @@ user-id = 696 user-login = "fitzgen" user-name = "Nick Fitzgerald" +[[publisher.clap]] +version = "3.2.8" +when = "2022-06-30" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.clap_derive]] +version = "3.2.7" +when = "2022-06-28" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.clap_lex]] +version = "0.2.4" +when = "2022-06-28" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + [[publisher.cranelift]] version = "0.97.1" when = "2023-06-21" @@ -324,6 +548,62 @@ user-id = 696 user-login = "fitzgen" user-name = "Nick Fitzgerald" +[[publisher.indexmap]] +version = "1.9.1" +when = "2022-06-21" +user-id = 539 +user-login = "cuviper" +user-name = "Josh Stone" + +[[publisher.itoa]] +version = "1.0.1" +when = "2021-12-12" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.libc]] +version = "0.2.132" +when = "2022-08-16" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.libm]] +version = "0.2.7" +when = "2023-05-15" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.lock_api]] +version = "0.4.7" +when = "2022-03-30" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.parking_lot]] +version = "0.11.2" +when = "2021-08-27" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.parking_lot_core]] +version = "0.8.5" +when = "2021-08-28" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.paste]] +version = "1.0.7" +when = "2022-03-27" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + [[publisher.regalloc2]] version = "0.9.1" when = "2023-05-31" @@ -331,6 +611,76 @@ user-id = 187138 user-login = "elliottt" user-name = "Trevor Elliott" +[[publisher.ryu]] +version = "1.0.9" +when = "2021-12-12" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.scopeguard]] +version = "1.1.0" +when = "2020-02-16" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.serde]] +version = "1.0.137" +when = "2022-05-01" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.serde_derive]] +version = "1.0.137" +when = "2022-05-01" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.serde_json]] +version = "1.0.80" +when = "2022-04-30" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.syn]] +version = "1.0.92" +when = "2022-04-29" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.syn]] +version = "2.0.16" +when = "2023-05-14" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.thiserror]] +version = "1.0.31" +when = "2022-04-30" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.thiserror-impl]] +version = "1.0.31" +when = "2022-04-30" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.toml]] +version = "0.5.7" +when = "2020-10-11" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.unicode-segmentation]] version = "1.10.1" when = "2023-01-31" @@ -877,6 +1227,21 @@ who = "David Cook " criteria = "safe-to-deploy" version = "0.9.0" +[[audits.isrg.audits.libc]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.2.139 -> 0.2.141" + +[[audits.isrg.audits.once_cell]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "1.17.1 -> 1.17.2" + +[[audits.isrg.audits.once_cell]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "1.17.2 -> 1.18.0" + [[audits.isrg.audits.opaque-debug]] who = "David Cook " criteria = "safe-to-deploy" @@ -1101,6 +1466,18 @@ version = "1.4.0" notes = "I have read over the macros, and audited the unsafe code." aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" +[[audits.mozilla.audits.libc]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.2.132 -> 0.2.138" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.libc]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.2.138 -> 0.2.139" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + [[audits.mozilla.audits.log]] who = "Mike Hommey " criteria = "safe-to-deploy" @@ -1158,6 +1535,12 @@ criteria = "safe-to-deploy" delta = "1.13.1 -> 1.16.0" aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" +[[audits.mozilla.audits.once_cell]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "1.16.0 -> 1.17.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + [[audits.mozilla.audits.proc-macro2]] who = "Nika Layzell " criteria = "safe-to-deploy" @@ -1206,6 +1589,13 @@ criteria = "safe-to-deploy" delta = "1.0.49 -> 1.0.51" aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" +[[audits.mozilla.audits.proc-macro2]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "1.0.57 -> 1.0.59" +notes = "Enabled on Wasm" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + [[audits.mozilla.audits.quote]] who = "Nika Layzell " criteria = "safe-to-deploy" @@ -1288,6 +1678,12 @@ harmless. It will be removed in the next version. """ aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" +[[audits.mozilla.audits.toml]] +who = "Bobby Holley " +criteria = "safe-to-deploy" +delta = "0.5.7 -> 0.5.9" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + [[audits.mozilla.audits.unicode-normalization]] who = "Mike Hommey " criteria = "safe-to-deploy" diff --git a/tests/all/component_model/aot.rs b/tests/all/component_model/aot.rs index 3b03aef23755..df6e0b66318c 100644 --- a/tests/all/component_model/aot.rs +++ b/tests/all/component_model/aot.rs @@ -98,3 +98,24 @@ fn cannot_serialize_exported_module() -> Result<()> { assert!(module.serialize().is_err()); Ok(()) } + +#[test] +fn usable_exported_modules() -> Result<()> { + let engine = super::engine(); + let component = Component::new( + &engine, + r#"(component + (core module $m) + (core module $m1 (export "a") + (import "" "" (func (param i32))) + ) + )"#, + )?; + let mut store = Store::new(&engine, ()); + let instance = Linker::new(&engine).instantiate(&mut store, &component)?; + let module = instance.get_module(&mut store, "a").unwrap(); + let mut core_linker = wasmtime::Linker::new(&engine); + core_linker.func_wrap("", "", |_: u32| {})?; + core_linker.instantiate(&mut store, &module)?; + Ok(()) +} diff --git a/tests/all/component_model/import.rs b/tests/all/component_model/import.rs index be5ba39bedf5..705348e9dfa7 100644 --- a/tests/all/component_model/import.rs +++ b/tests/all/component_model/import.rs @@ -169,6 +169,111 @@ fn simple() -> Result<()> { Ok(()) } +#[test] +fn functions_in_instances() -> Result<()> { + let component = r#" + (component + (type $import-type (instance + (export "a" (func (param "a" string))) + )) + (import (interface "test:test/foo") (instance $import (type $import-type))) + (alias export $import "a" (func $log)) + + (core module $libc + (memory (export "memory") 1) + + (func (export "realloc") (param i32 i32 i32 i32) (result i32) + unreachable) + ) + (core instance $libc (instantiate $libc)) + (core func $log_lower + (canon lower (func $log) (memory $libc "memory") (realloc (func $libc "realloc"))) + ) + (core module $m + (import "libc" "memory" (memory 1)) + (import "host" "log" (func $log (param i32 i32))) + + (func (export "call") + i32.const 5 + i32.const 11 + call $log) + + (data (i32.const 5) "hello world") + ) + (core instance $i (instantiate $m + (with "libc" (instance $libc)) + (with "host" (instance (export "log" (func $log_lower)))) + )) + (func $call + (canon lift (core func $i "call")) + ) + (component $c + (import "import-call" (func $f)) + (export "call" (func $f)) + ) + (instance $export (instantiate $c + (with "import-call" (func $call)) + )) + (export (interface "test:test/foo") (instance $export)) + ) + "#; + + let engine = super::engine(); + let component = Component::new(&engine, component)?; + let mut store = Store::new(&engine, None); + assert!(store.data().is_none()); + + // First, test the static API + + let mut linker = Linker::new(&engine); + linker.instance("test:test/foo")?.func_wrap( + "a", + |mut store: StoreContextMut<'_, Option>, (arg,): (WasmStr,)| -> Result<_> { + let s = arg.to_str(&store)?.to_string(); + assert!(store.data().is_none()); + *store.data_mut() = Some(s); + Ok(()) + }, + )?; + let instance = linker.instantiate(&mut store, &component)?; + let func = instance + .exports(&mut store) + .instance("test:test/foo") + .unwrap() + .typed_func::<(), ()>("call")?; + func.call(&mut store, ())?; + assert_eq!(store.data().as_ref().unwrap(), "hello world"); + + // Next, test the dynamic API + + *store.data_mut() = None; + let mut linker = Linker::new(&engine); + linker.instance("test:test/foo")?.func_new( + &component, + "a", + |mut store: StoreContextMut<'_, Option>, args, _results| { + if let Val::String(s) = &args[0] { + assert!(store.data().is_none()); + *store.data_mut() = Some(s.to_string()); + Ok(()) + } else { + panic!() + } + }, + )?; + let instance = linker.instantiate(&mut store, &component)?; + let func = instance + .exports(&mut store) + .instance("test:test/foo") + .unwrap() + .func("call") + .unwrap(); + func.call(&mut store, &[], &mut [])?; + assert_eq!(store.data().as_ref().unwrap(), "hello world"); + + Ok(()) +} + #[test] fn attempt_to_leave_during_malloc() -> Result<()> { let component = r#" diff --git a/tests/all/wast.rs b/tests/all/wast.rs index 6a140c7161f4..71f8e32b09b1 100644 --- a/tests/all/wast.rs +++ b/tests/all/wast.rs @@ -19,11 +19,6 @@ fn run_wast(wast: &str, strategy: Strategy, pooling: bool) -> anyhow::Result<()> let wast_bytes = std::fs::read(wast).with_context(|| format!("failed to read `{}`", wast))?; - match strategy { - Strategy::Cranelift => {} - _ => unimplemented!(), - } - let wast = Path::new(wast); let memory64 = feature_found(wast, "memory64"); @@ -42,6 +37,11 @@ fn run_wast(wast: &str, strategy: Strategy, pooling: bool) -> anyhow::Result<()> return Ok(()); } + let is_cranelift = match strategy { + Strategy::Cranelift => true, + _ => false, + }; + let mut cfg = Config::new(); cfg.wasm_multi_memory(multi_memory) .wasm_threads(threads) @@ -51,11 +51,15 @@ fn run_wast(wast: &str, strategy: Strategy, pooling: bool) -> anyhow::Result<()> .wasm_relaxed_simd(relaxed_simd) .wasm_exceptions(exceptions) .wasm_typed_continuations(typed_continuations) - .cranelift_debug_verifier(true); + .strategy(strategy); + + if is_cranelift { + cfg.cranelift_debug_verifier(true); + } cfg.wasm_component_model(feature_found(wast, "component-model")); - if feature_found(wast, "canonicalize-nan") { + if feature_found(wast, "canonicalize-nan") && is_cranelift { cfg.cranelift_nan_canonicalization(true); } let test_allocates_lots_of_memory = wast.ends_with("more-than-4gb.wast"); diff --git a/tests/misc_testsuite/winch/block.wast b/tests/misc_testsuite/winch/block.wast new file mode 100644 index 000000000000..2d433b1e1eef --- /dev/null +++ b/tests/misc_testsuite/winch/block.wast @@ -0,0 +1,161 @@ +;; Test `block` operator + +(module + ;; Auxiliary definition + (memory 1) + + (func $dummy) + + (func (export "empty") + (block) + (block $l) + ) + + (func (export "singular") (result i32) + (block (nop)) + (block (result i32) (i32.const 7)) + ) + + (func (export "nested") (result i32) + (block (result i32) + (block (call $dummy) (block) (nop)) + (block (result i32) (call $dummy) (i32.const 9)) + ) + ) + + (func (export "deep") (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (block (result i32) (block (result i32) + (call $dummy) (i32.const 150) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + ) + + (func (export "as-if-condition") + (block (result i32) (i32.const 1)) (if (then (call $dummy))) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) (then (block (result i32) (i32.const 1))) (else (i32.const 2))) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 1) (then (i32.const 2)) (else (block (result i32) (i32.const 1)))) + ) + + (func (export "as-br_if-first") (result i32) + (block (result i32) (br_if 0 (block (result i32) (i32.const 1)) (i32.const 2))) + ) + (func (export "as-br_if-last") (result i32) + (block (result i32) (br_if 0 (i32.const 2) (block (result i32) (i32.const 1)))) + ) + + + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "as-call-value") (result i32) + (call $f (block (result i32) (i32.const 1))) + ) + (func (export "as-return-value") (result i32) + (block (result i32) (i32.const 1)) (return) + ) + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (block (result i32) (i32.const 1)))) + ) + (func (export "as-local.set-value") (result i32) + (local i32) (local.set 0 (block (result i32) (i32.const 1))) (local.get 0) + ) + + (func (export "as-unary-operand") (result i32) + (i32.ctz (block (result i32) (call $dummy) (i32.const 13))) + ) + (func (export "as-binary-operand") (result i32) + (i32.mul + (block (result i32) (call $dummy) (i32.const 3)) + (block (result i32) (call $dummy) (i32.const 4)) + ) + ) + (func (export "as-test-operand") (result i32) + (i32.eqz (block (result i32) (call $dummy) (i32.const 13))) + ) + (func (export "break-value") (result i32) + (block (result i32) (br 0 (i32.const 18)) (i32.const 19)) + ) + (func (export "break-inner") (result i32) + (local i32) + (local.set 0 (i32.const 0)) + (local.set 0 (i32.add (local.get 0) (block (result i32) (block (result i32) (br 1 (i32.const 0x1)))))) + (local.set 0 (i32.add (local.get 0) (block (result i32) (block (br 0)) (i32.const 0x2)))) + (local.set 0 + (i32.add (local.get 0) (block (result i32) (i32.ctz (br 0 (i32.const 0x4))))) + ) + (local.set 0 + (i32.add (local.get 0) (block (result i32) (i32.ctz (block (result i32) (br 1 (i32.const 0x8)))))) + ) + (local.get 0) + ) + + (func (export "effects") (result i32) + (local i32) + (block + (local.set 0 (i32.const 1)) + (local.set 0 (i32.mul (local.get 0) (i32.const 3))) + (local.set 0 (i32.sub (local.get 0) (i32.const 5))) + (local.set 0 (i32.mul (local.get 0) (i32.const 7))) + (br 0) + (local.set 0 (i32.mul (local.get 0) (i32.const 100))) + ) + (i32.eq (local.get 0) (i32.const -14)) + ) +) + +(assert_return (invoke "empty")) +(assert_return (invoke "singular") (i32.const 7)) +(assert_return (invoke "nested") (i32.const 9)) +(assert_return (invoke "deep") (i32.const 150)) +(assert_return (invoke "as-if-condition")) +(assert_return (invoke "as-if-then") (i32.const 1)) +(assert_return (invoke "as-if-else") (i32.const 2)) +(assert_return (invoke "as-br_if-first") (i32.const 1)) +(assert_return (invoke "as-br_if-last") (i32.const 2)) +(assert_return (invoke "as-call-value") (i32.const 1)) +(assert_return (invoke "as-return-value") (i32.const 1)) +(assert_return (invoke "as-br-value") (i32.const 1)) +(assert_return (invoke "as-local.set-value") (i32.const 1)) +(assert_return (invoke "as-unary-operand") (i32.const 0)) +(assert_return (invoke "as-binary-operand") (i32.const 12)) +(assert_return (invoke "as-test-operand") (i32.const 0)) +(assert_return (invoke "break-inner") (i32.const 0xf)) +(assert_return (invoke "effects") (i32.const 1)) diff --git a/tests/misc_testsuite/winch/br.wast b/tests/misc_testsuite/winch/br.wast new file mode 100644 index 000000000000..af653bcb0907 --- /dev/null +++ b/tests/misc_testsuite/winch/br.wast @@ -0,0 +1,156 @@ +;; Test `br` operator + +(module + ;; Auxiliary definition + (func $dummy) + + (func (export "type-i32-value") (result i32) + (block (result i32) (i32.ctz (br 0 (i32.const 1)))) + ) + (func (export "type-i64-value") (result i64) + (block (result i64) (i64.ctz (br 0 (i64.const 2)))) + ) + + (func (export "as-block-first") + (block (br 0) (call $dummy)) + ) + (func (export "as-block-mid") + (block (call $dummy) (br 0) (call $dummy)) + ) + (func (export "as-block-last") + (block (nop) (call $dummy) (br 0)) + ) + (func (export "as-block-value") (result i32) + (block (result i32) (nop) (call $dummy) (br 0 (i32.const 2))) + ) + + (func (export "as-loop-first") (result i32) + (block (result i32) (loop (result i32) (br 1 (i32.const 3)) (i32.const 2))) + ) + (func (export "as-loop-mid") (result i32) + (block (result i32) + (loop (result i32) (call $dummy) (br 1 (i32.const 4)) (i32.const 2)) + ) + ) + (func (export "as-loop-last") (result i32) + (block (result i32) + (loop (result i32) (nop) (call $dummy) (br 1 (i32.const 5))) + ) + ) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (br 0 (i32.const 9)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (br 0))) + ) + + (func (export "as-return-value") (result i64) + (block (result i64) (return (br 0 (i64.const 7)))) + ) + + (func (export "as-if-cond") (result i32) + (block (result i32) + (if (result i32) (br 0 (i32.const 2)) + (then (i32.const 0)) + (else (i32.const 1)) + ) + ) + ) + (func (export "as-if-then") (param i32 i32) (result i32) + (block (result i32) + (if (result i32) (local.get 0) + (then (br 1 (i32.const 3))) + (else (local.get 1)) + ) + ) + ) + (func (export "as-if-else") (param i32 i32) (result i32) + (block (result i32) + (if (result i32) (local.get 0) + (then (local.get 1)) + (else (br 1 (i32.const 4))) + ) + ) + ) + + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (block (result i32) + (call $f (br 0 (i32.const 12)) (i32.const 2) (i32.const 3)) + ) + ) + (func (export "as-call-mid") (result i32) + (block (result i32) + (call $f (i32.const 1) (br 0 (i32.const 13)) (i32.const 3)) + ) + ) + (func (export "as-call-last") (result i32) + (block (result i32) + (call $f (i32.const 1) (i32.const 2) (br 0 (i32.const 14))) + ) + ) + (func (export "as-call-all") (result i32) + (block (result i32) (call $f (br 0 (i32.const 15)))) + ) + + (func (export "as-binary-left") (result i32) + (block (result i32) (i32.add (br 0 (i32.const 3)) (i32.const 10))) + ) + (func (export "as-binary-right") (result i64) + (block (result i64) (i64.sub (i64.const 10) (br 0 (i64.const 45)))) + ) + (func (export "as-binary-both") (result i32) + (block (result i32) (i32.add (br 0 (i32.const 46)))) + ) + + (func (export "as-test-operand") (result i32) + (block (result i32) (i32.eqz (br 0 (i32.const 44)))) + ) + + (func (export "nested-block-value") (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (call $dummy) + (i32.add (i32.const 4) (br 0 (i32.const 8))) + ) + ) + ) +) + +(assert_return (invoke "type-i32-value") (i32.const 1)) +(assert_return (invoke "type-i64-value") (i64.const 2)) +(assert_return (invoke "as-block-first")) +(assert_return (invoke "as-block-mid")) +(assert_return (invoke "as-block-last")) +(assert_return (invoke "as-block-value") (i32.const 2)) +(assert_return (invoke "as-loop-first") (i32.const 3)) +(assert_return (invoke "as-loop-mid") (i32.const 4)) +(assert_return (invoke "as-loop-last") (i32.const 5)) +(assert_return (invoke "as-br-value") (i32.const 9)) +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-return-value") (i64.const 7)) + +(assert_return (invoke "as-if-cond") (i32.const 2)) +(assert_return (invoke "as-if-then" (i32.const 1) (i32.const 6)) (i32.const 3)) +(assert_return (invoke "as-if-then" (i32.const 0) (i32.const 6)) (i32.const 6)) +(assert_return (invoke "as-if-else" (i32.const 0) (i32.const 6)) (i32.const 4)) +(assert_return (invoke "as-if-else" (i32.const 1) (i32.const 6)) (i32.const 6)) + +(assert_return (invoke "as-call-first") (i32.const 12)) +(assert_return (invoke "as-call-mid") (i32.const 13)) +(assert_return (invoke "as-call-last") (i32.const 14)) +(assert_return (invoke "as-call-all") (i32.const 15)) + + +(assert_return (invoke "as-binary-left") (i32.const 3)) +(assert_return (invoke "as-binary-right") (i64.const 45)) +(assert_return (invoke "as-binary-both") (i32.const 46)) + +(assert_return (invoke "as-test-operand") (i32.const 44)) + +(assert_return (invoke "nested-block-value") (i32.const 9)) + diff --git a/tests/misc_testsuite/winch/br_if.wast b/tests/misc_testsuite/winch/br_if.wast new file mode 100644 index 000000000000..088433ccfb6e --- /dev/null +++ b/tests/misc_testsuite/winch/br_if.wast @@ -0,0 +1,159 @@ +;; Test `br_if` operator + +(module + (func $dummy) + + (func (export "type-i32-value") (result i32) + (block (result i32) (i32.ctz (br_if 0 (i32.const 1) (i32.const 1)))) + ) + (func (export "type-i64-value") (result i64) + (block (result i64) (i64.ctz (br_if 0 (i64.const 2) (i32.const 1)))) + ) + + (func (export "as-block-first") (param i32) (result i32) + (block (br_if 0 (local.get 0)) (return (i32.const 2))) (i32.const 3) + ) + (func (export "as-block-mid") (param i32) (result i32) + (block (call $dummy) (br_if 0 (local.get 0)) (return (i32.const 2))) + (i32.const 3) + ) + (func (export "as-block-last") (param i32) + (block (call $dummy) (call $dummy) (br_if 0 (local.get 0))) + ) + (func (export "as-block-last-value") (param i32) (result i32) + (block (result i32) + (call $dummy) (call $dummy) (br_if 0 (i32.const 11) (local.get 0)) + ) + ) + + (func (export "as-loop-first") (param i32) (result i32) + (block (loop (br_if 1 (local.get 0)) (return (i32.const 2)))) (i32.const 3) + ) + (func (export "as-loop-mid") (param i32) (result i32) + (block (loop (call $dummy) (br_if 1 (local.get 0)) (return (i32.const 2)))) + (i32.const 4) + ) + (func (export "as-loop-last") (param i32) + (loop (call $dummy) (br_if 1 (local.get 0))) + ) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (br_if 0 (i32.const 1) (i32.const 2)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (br_if 0 (i32.const 1) (i32.const 1)))) + ) + + (func (export "as-return-value") (result i64) + (block (result i64) (return (br_if 0 (i64.const 1) (i32.const 2)))) + ) + + (func (export "as-if-cond") (param i32) (result i32) + (block (result i32) + (if (result i32) + (br_if 0 (i32.const 1) (local.get 0)) + (then (i32.const 2)) + (else (i32.const 3)) + ) + ) + ) + (func (export "as-if-then") (param i32 i32) + (block + (if (local.get 0) (then (br_if 1 (local.get 1))) (else (call $dummy))) + ) + ) + (func (export "as-if-else") (param i32 i32) + (block + (if (local.get 0) (then (call $dummy)) (else (br_if 1 (local.get 1)))) + ) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (block (result i32) + (call $f + (br_if 0 (i32.const 12) (i32.const 1)) (i32.const 2) (i32.const 3) + ) + ) + ) + (func (export "as-call-mid") (result i32) + (block (result i32) + (call $f + (i32.const 1) (br_if 0 (i32.const 13) (i32.const 1)) (i32.const 3) + ) + ) + ) + (func (export "as-call-last") (result i32) + (block (result i32) + (call $f + (i32.const 1) (i32.const 2) (br_if 0 (i32.const 14) (i32.const 1)) + ) + ) + ) + + (func (export "as-local.set-value") (param i32) (result i32) + (local i32) + (block (result i32) + (local.set 0 (br_if 0 (i32.const 17) (local.get 0))) + (i32.const -1) + ) + ) + + (func (export "as-binary-left") (result i32) + (block (result i32) (i32.add (br_if 0 (i32.const 1) (i32.const 1)) (i32.const 10))) + ) + (func (export "as-binary-right") (result i32) + (block (result i32) (i32.sub (i32.const 10) (br_if 0 (i32.const 1) (i32.const 1)))) + ) + (func (export "as-test-operand") (result i32) + (block (result i32) (i32.eqz (br_if 0 (i32.const 0) (i32.const 1)))) + ) + (func (export "as-compare-left") (result i32) + (block (result i32) (i32.le_u (br_if 0 (i32.const 1) (i32.const 1)) (i32.const 10))) + ) + (func (export "as-compare-right") (result i32) + (block (result i32) (i32.ne (i32.const 10) (br_if 0 (i32.const 1) (i32.const 42)))) + ) +) + + +(assert_return (invoke "type-i32-value") (i32.const 1)) +(assert_return (invoke "type-i64-value") (i64.const 2)) +(assert_return (invoke "as-block-first" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-block-first" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-block-mid" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-block-mid" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-block-last" (i32.const 0))) +(assert_return (invoke "as-block-last" (i32.const 1))) +(assert_return (invoke "as-block-last-value" (i32.const 0)) (i32.const 11)) +(assert_return (invoke "as-block-last-value" (i32.const 1)) (i32.const 11)) +(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-loop-first" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-loop-mid" (i32.const 1)) (i32.const 4)) +(assert_return (invoke "as-loop-last" (i32.const 0))) +(assert_return (invoke "as-loop-last" (i32.const 1))) +(assert_return (invoke "as-br-value") (i32.const 1)) +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-return-value") (i64.const 1)) +(assert_return (invoke "as-if-cond" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-if-cond" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-if-then" (i32.const 0) (i32.const 0))) +(assert_return (invoke "as-if-then" (i32.const 4) (i32.const 0))) +(assert_return (invoke "as-if-then" (i32.const 0) (i32.const 1))) +(assert_return (invoke "as-if-then" (i32.const 4) (i32.const 1))) +(assert_return (invoke "as-if-else" (i32.const 0) (i32.const 0))) +(assert_return (invoke "as-if-else" (i32.const 3) (i32.const 0))) +(assert_return (invoke "as-if-else" (i32.const 0) (i32.const 1))) +(assert_return (invoke "as-if-else" (i32.const 3) (i32.const 1))) +(assert_return (invoke "as-call-first") (i32.const 12)) +(assert_return (invoke "as-call-mid") (i32.const 13)) +(assert_return (invoke "as-call-last") (i32.const 14)) +(assert_return (invoke "as-local.set-value" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 17)) +(assert_return (invoke "as-binary-left") (i32.const 1)) +(assert_return (invoke "as-binary-right") (i32.const 1)) +(assert_return (invoke "as-test-operand") (i32.const 0)) +(assert_return (invoke "as-compare-left") (i32.const 1)) +(assert_return (invoke "as-compare-right") (i32.const 1)) diff --git a/tests/misc_testsuite/winch/call.wast b/tests/misc_testsuite/winch/call.wast new file mode 100644 index 000000000000..db90832d3b27 --- /dev/null +++ b/tests/misc_testsuite/winch/call.wast @@ -0,0 +1,179 @@ +;; Test `call` operator + + +(module + ;; Auxiliary definitions + (func $const-i32 (result i32) (i32.const 0x132)) + (func $const-i64 (result i64) (i64.const 0x164)) + + (func $id-i32 (param i32) (result i32) (local.get 0)) + (func $id-i64 (param i64) (result i64) (local.get 0)) + + (func $i32-i64 (param i32 i64) (result i64) (local.get 1)) + + ;; Typing + + (func (export "type-i32") (result i32) (call $const-i32)) + (func (export "type-i64") (result i64) (call $const-i64)) + + (func (export "type-first-i32") (result i32) (call $id-i32 (i32.const 32))) + (func (export "type-first-i64") (result i64) (call $id-i64 (i64.const 64))) + + (func (export "type-second-i64") (result i64) + (call $i32-i64 (i32.const 32) (i64.const 64)) + ) + + ;; Recursion + + (func $fac (export "fac") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 1)) + (else + (i64.mul + (local.get 0) + (call $fac (i64.sub (local.get 0) (i64.const 1))) + ) + ) + ) + ) + + (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (call $fac-acc + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + ) + ) + ) + ) + + (func $fib (export "fib") (param i64) (result i64) + (if (result i64) (i64.le_u (local.get 0) (i64.const 1)) + (then (i64.const 1)) + (else + (i64.add + (call $fib (i64.sub (local.get 0) (i64.const 2))) + (call $fib (i64.sub (local.get 0) (i64.const 1))) + ) + ) + ) + ) + + (func $even (export "even") (param i64) (result i32) + (if (result i32) (i64.eqz (local.get 0)) + (then (i32.const 44)) + (else (call $odd (i64.sub (local.get 0) (i64.const 1)))) + ) + ) + (func $odd (export "odd") (param i64) (result i32) + (if (result i32) (i64.eqz (local.get 0)) + (then (i32.const 99)) + (else (call $even (i64.sub (local.get 0) (i64.const 1)))) + ) + ) + + ;; Stack exhaustion + + ;; Implementations are required to have every call consume some abstract + ;; resource towards exhausting some abstract finite limit, such that + ;; infinitely recursive test cases reliably trap in finite time. This is + ;; because otherwise applications could come to depend on it on those + ;; implementations and be incompatible with implementations that don't do + ;; it (or don't do it under the same circumstances). + + (func $runaway (export "runaway") (call $runaway)) + + (func $mutual-runaway1 (export "mutual-runaway") (call $mutual-runaway2)) + (func $mutual-runaway2 (call $mutual-runaway1)) + + ;; As parameter of control constructs and instructions + + (memory 1) + + (func (export "as-if-condition") (result i32) + (if (result i32) (call $const-i32) (then (i32.const 1)) (else (i32.const 2))) + ) + + (func (export "as-br_if-first") (result i32) + (block (result i32) (br_if 0 (call $const-i32) (i32.const 2))) + ) + (func (export "as-br_if-last") (result i32) + (block (result i32) (br_if 0 (i32.const 2) (call $const-i32))) + ) + + + (func (export "as-return-value") (result i32) + (call $const-i32) (return) + ) + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (call $const-i32))) + ) + (func (export "as-local.set-value") (result i32) + (local i32) (local.set 0 (call $const-i32)) (local.get 0) + ) + (func $dummy (param i32) (result i32) (local.get 0)) + + (func (export "as-binary-left") (result i32) + (block (result i32) (i32.add (call $dummy (i32.const 1)) (i32.const 10))) + ) + (func (export "as-binary-right") (result i32) + (block (result i32) (i32.sub (i32.const 10) (call $dummy (i32.const 1)))) + ) + + (func (export "as-test-operand") (result i32) + (block (result i32) (i32.eqz (call $dummy (i32.const 1)))) + ) + + (func (export "as-compare-left") (result i32) + (block (result i32) (i32.le_u (call $dummy (i32.const 1)) (i32.const 10))) + ) + (func (export "as-compare-right") (result i32) + (block (result i32) (i32.ne (i32.const 10) (call $dummy (i32.const 1)))) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-second-i64") (i64.const 64)) + +(assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) +(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) +(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) +(assert_return + (invoke "fac-acc" (i64.const 25) (i64.const 1)) + (i64.const 7034535277573963776) +) + +(assert_return (invoke "fib" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "fib" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fib" (i64.const 2)) (i64.const 2)) +(assert_return (invoke "fib" (i64.const 5)) (i64.const 8)) +(assert_return (invoke "fib" (i64.const 20)) (i64.const 10946)) +(assert_return (invoke "even" (i64.const 0)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 1)) (i32.const 99)) +(assert_return (invoke "even" (i64.const 100)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 77)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 0)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 1)) (i32.const 44)) +(assert_return (invoke "odd" (i64.const 200)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 77)) (i32.const 44)) +(assert_return (invoke "as-if-condition") (i32.const 1)) +(assert_return (invoke "as-br_if-first") (i32.const 0x132)) +(assert_return (invoke "as-br_if-last") (i32.const 2)) +(assert_return (invoke "as-return-value") (i32.const 0x132)) +(assert_return (invoke "as-br-value") (i32.const 0x132)) +(assert_return (invoke "as-local.set-value") (i32.const 0x132)) + +(assert_return (invoke "as-binary-left") (i32.const 11)) +(assert_return (invoke "as-binary-right") (i32.const 9)) +(assert_return (invoke "as-test-operand") (i32.const 0)) +(assert_return (invoke "as-compare-left") (i32.const 1)) +(assert_return (invoke "as-compare-right") (i32.const 1)) diff --git a/tests/misc_testsuite/winch/globals.wast b/tests/misc_testsuite/winch/globals.wast new file mode 100644 index 000000000000..fa2a8f75ff15 --- /dev/null +++ b/tests/misc_testsuite/winch/globals.wast @@ -0,0 +1,154 @@ +;; Test globals + +(module + (global (import "spectest" "global_i32") i32) + (global (import "spectest" "global_i64") i64) + + (global $a i32 (i32.const -2)) + (global $b i64 (i64.const -5)) + + (global $x (mut i32) (i32.const -12)) + (global $y (mut i64) (i64.const -15)) + + (global $z1 i32 (global.get 0)) + (global $z2 i64 (global.get 1)) + + (func (export "get-a") (result i32) (global.get $a)) + (func (export "get-b") (result i64) (global.get $b)) + (func (export "get-x") (result i32) (global.get $x)) + (func (export "get-y") (result i64) (global.get $y)) + (func (export "get-z1") (result i32) (global.get $z1)) + (func (export "get-z2") (result i64) (global.get $z2)) + (func (export "set-x") (param i32) (global.set $x (local.get 0))) + (func (export "set-y") (param i64) (global.set $y (local.get 0))) + + ;; As the argument of control constructs and instructions + + (memory 1) + + (func $dummy) + + (func (export "as-loop-first") (result i32) + (loop (result i32) + (global.get $x) (call $dummy) (call $dummy) + ) + ) + (func (export "as-loop-mid") (result i32) + (loop (result i32) + (call $dummy) (global.get $x) (call $dummy) + ) + ) + (func (export "as-loop-last") (result i32) + (loop (result i32) + (call $dummy) (call $dummy) (global.get $x) + ) + ) + + (func (export "as-if-condition") (result i32) + (if (result i32) (global.get $x) + (then (call $dummy) (i32.const 2)) + (else (call $dummy) (i32.const 3)) + ) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) + (then (global.get $x)) (else (i32.const 2)) + ) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 0) + (then (i32.const 2)) (else (global.get $x)) + ) + ) + + (func (export "as-br_if-first") (result i32) + (block (result i32) + (br_if 0 (global.get $x) (i32.const 2)) + (return (i32.const 3)) + ) + ) + (func (export "as-br_if-last") (result i32) + (block (result i32) + (br_if 0 (i32.const 2) (global.get $x)) + (return (i32.const 3)) + ) + ) + + (func $f (param i32) (result i32) (local.get 0)) + (func (export "as-call-value") (result i32) + (call $f (global.get $x)) + ) + + (func (export "as-return-value") (result i32) + (global.get $x) (return) + ) + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (global.get $x))) + ) + + (func (export "as-local.set-value") (param i32) (result i32) + (local.set 0 (global.get $x)) + (local.get 0) + ) + (func (export "as-local.tee-value") (param i32) (result i32) + (local.tee 0 (global.get $x)) + ) + (func (export "as-global.set-value") (result i32) + (global.set $x (global.get $x)) + (global.get $x) + ) + + (func (export "as-unary-operand") (result i32) + (i32.eqz (global.get $x)) + ) + (func (export "as-binary-operand") (result i32) + (i32.mul + (global.get $x) (global.get $x) + ) + ) + (func (export "as-compare-operand") (result i32) + (i32.gt_u + (global.get 0) (i32.const 1) + ) + ) +) + +(assert_return (invoke "get-a") (i32.const -2)) +(assert_return (invoke "get-b") (i64.const -5)) +(assert_return (invoke "get-x") (i32.const -12)) +(assert_return (invoke "get-y") (i64.const -15)) +(assert_return (invoke "get-z1") (i32.const 666)) +(assert_return (invoke "get-z2") (i64.const 666)) + +(assert_return (invoke "set-x" (i32.const 6))) +(assert_return (invoke "set-y" (i64.const 7))) + +(assert_return (invoke "get-x") (i32.const 6)) +(assert_return (invoke "get-y") (i64.const 7)) + +(assert_return (invoke "get-x") (i32.const 6)) +(assert_return (invoke "get-y") (i64.const 7)) + +(assert_return (invoke "as-loop-first") (i32.const 6)) +(assert_return (invoke "as-loop-mid") (i32.const 6)) +(assert_return (invoke "as-loop-last") (i32.const 6)) + +(assert_return (invoke "as-if-condition") (i32.const 2)) +(assert_return (invoke "as-if-then") (i32.const 6)) +(assert_return (invoke "as-if-else") (i32.const 6)) + +(assert_return (invoke "as-br_if-first") (i32.const 6)) +(assert_return (invoke "as-br_if-last") (i32.const 2)) + +(assert_return (invoke "as-call-value") (i32.const 6)) + +(assert_return (invoke "as-return-value") (i32.const 6)) +(assert_return (invoke "as-br-value") (i32.const 6)) + +(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 6)) +(assert_return (invoke "as-local.tee-value" (i32.const 1)) (i32.const 6)) +(assert_return (invoke "as-global.set-value") (i32.const 6)) + +(assert_return (invoke "as-unary-operand") (i32.const 0)) +(assert_return (invoke "as-binary-operand") (i32.const 36)) +(assert_return (invoke "as-compare-operand") (i32.const 1)) diff --git a/tests/misc_testsuite/winch/i32.wast b/tests/misc_testsuite/winch/i32.wast new file mode 100644 index 000000000000..8a06d0914500 --- /dev/null +++ b/tests/misc_testsuite/winch/i32.wast @@ -0,0 +1,422 @@ +;; i32 operations + +(module + (func (export "add") (param $x i32) (param $y i32) (result i32) (i32.add (local.get $x) (local.get $y))) + (func (export "sub") (param $x i32) (param $y i32) (result i32) (i32.sub (local.get $x) (local.get $y))) + (func (export "mul") (param $x i32) (param $y i32) (result i32) (i32.mul (local.get $x) (local.get $y))) + (func (export "div_s") (param $x i32) (param $y i32) (result i32) (i32.div_s (local.get $x) (local.get $y))) + (func (export "div_u") (param $x i32) (param $y i32) (result i32) (i32.div_u (local.get $x) (local.get $y))) + (func (export "rem_s") (param $x i32) (param $y i32) (result i32) (i32.rem_s (local.get $x) (local.get $y))) + (func (export "rem_u") (param $x i32) (param $y i32) (result i32) (i32.rem_u (local.get $x) (local.get $y))) + (func (export "and") (param $x i32) (param $y i32) (result i32) (i32.and (local.get $x) (local.get $y))) + (func (export "or") (param $x i32) (param $y i32) (result i32) (i32.or (local.get $x) (local.get $y))) + (func (export "xor") (param $x i32) (param $y i32) (result i32) (i32.xor (local.get $x) (local.get $y))) + (func (export "shl") (param $x i32) (param $y i32) (result i32) (i32.shl (local.get $x) (local.get $y))) + (func (export "shr_s") (param $x i32) (param $y i32) (result i32) (i32.shr_s (local.get $x) (local.get $y))) + (func (export "shr_u") (param $x i32) (param $y i32) (result i32) (i32.shr_u (local.get $x) (local.get $y))) + (func (export "rotl") (param $x i32) (param $y i32) (result i32) (i32.rotl (local.get $x) (local.get $y))) + (func (export "rotr") (param $x i32) (param $y i32) (result i32) (i32.rotr (local.get $x) (local.get $y))) + (func (export "clz") (param $x i32) (result i32) (i32.clz (local.get $x))) + (func (export "ctz") (param $x i32) (result i32) (i32.ctz (local.get $x))) + (func (export "popcnt") (param $x i32) (result i32) (i32.popcnt (local.get $x))) + (func (export "eqz") (param $x i32) (result i32) (i32.eqz (local.get $x))) + (func (export "eq") (param $x i32) (param $y i32) (result i32) (i32.eq (local.get $x) (local.get $y))) + (func (export "ne") (param $x i32) (param $y i32) (result i32) (i32.ne (local.get $x) (local.get $y))) + (func (export "lt_s") (param $x i32) (param $y i32) (result i32) (i32.lt_s (local.get $x) (local.get $y))) + (func (export "lt_u") (param $x i32) (param $y i32) (result i32) (i32.lt_u (local.get $x) (local.get $y))) + (func (export "le_s") (param $x i32) (param $y i32) (result i32) (i32.le_s (local.get $x) (local.get $y))) + (func (export "le_u") (param $x i32) (param $y i32) (result i32) (i32.le_u (local.get $x) (local.get $y))) + (func (export "gt_s") (param $x i32) (param $y i32) (result i32) (i32.gt_s (local.get $x) (local.get $y))) + (func (export "gt_u") (param $x i32) (param $y i32) (result i32) (i32.gt_u (local.get $x) (local.get $y))) + (func (export "ge_s") (param $x i32) (param $y i32) (result i32) (i32.ge_s (local.get $x) (local.get $y))) + (func (export "ge_u") (param $x i32) (param $y i32) (result i32) (i32.ge_u (local.get $x) (local.get $y))) +) + +(assert_return (invoke "add" (i32.const 1) (i32.const 1)) (i32.const 2)) +(assert_return (invoke "add" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "add" (i32.const -1) (i32.const -1)) (i32.const -2)) +(assert_return (invoke "add" (i32.const -1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "add" (i32.const 0x7fffffff) (i32.const 1)) (i32.const 0x80000000)) +(assert_return (invoke "add" (i32.const 0x80000000) (i32.const -1)) (i32.const 0x7fffffff)) +(assert_return (invoke "add" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "add" (i32.const 0x3fffffff) (i32.const 1)) (i32.const 0x40000000)) + +(assert_return (invoke "sub" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "sub" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "sub" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "sub" (i32.const 0x7fffffff) (i32.const -1)) (i32.const 0x80000000)) +(assert_return (invoke "sub" (i32.const 0x80000000) (i32.const 1)) (i32.const 0x7fffffff)) +(assert_return (invoke "sub" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "sub" (i32.const 0x3fffffff) (i32.const -1)) (i32.const 0x40000000)) + +(assert_return (invoke "mul" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "mul" (i32.const 1) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "mul" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "mul" (i32.const 0x10000000) (i32.const 4096)) (i32.const 0)) +(assert_return (invoke "mul" (i32.const 0x80000000) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "mul" (i32.const 0x80000000) (i32.const -1)) (i32.const 0x80000000)) +(assert_return (invoke "mul" (i32.const 0x7fffffff) (i32.const -1)) (i32.const 0x80000001)) +(assert_return (invoke "mul" (i32.const 0x01234567) (i32.const 0x76543210)) (i32.const 0x358e7470)) +(assert_return (invoke "mul" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 1)) + +(assert_trap (invoke "div_s" (i32.const 1) (i32.const 0)) "integer divide by zero") +(assert_trap (invoke "div_s" (i32.const 0) (i32.const 0)) "integer divide by zero") +(assert_trap (invoke "div_s" (i32.const 0x80000000) (i32.const -1)) "integer overflow") +(assert_trap (invoke "div_s" (i32.const 0x80000000) (i32.const 0)) "integer divide by zero") +(assert_return (invoke "div_s" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "div_s" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "div_s" (i32.const 0) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "div_s" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "div_s" (i32.const 0x80000000) (i32.const 2)) (i32.const 0xc0000000)) +(assert_return (invoke "div_s" (i32.const 0x80000001) (i32.const 1000)) (i32.const 0xffdf3b65)) +(assert_return (invoke "div_s" (i32.const 5) (i32.const 2)) (i32.const 2)) +(assert_return (invoke "div_s" (i32.const -5) (i32.const 2)) (i32.const -2)) +(assert_return (invoke "div_s" (i32.const 5) (i32.const -2)) (i32.const -2)) +(assert_return (invoke "div_s" (i32.const -5) (i32.const -2)) (i32.const 2)) +(assert_return (invoke "div_s" (i32.const 7) (i32.const 3)) (i32.const 2)) +(assert_return (invoke "div_s" (i32.const -7) (i32.const 3)) (i32.const -2)) +(assert_return (invoke "div_s" (i32.const 7) (i32.const -3)) (i32.const -2)) +(assert_return (invoke "div_s" (i32.const -7) (i32.const -3)) (i32.const 2)) +(assert_return (invoke "div_s" (i32.const 11) (i32.const 5)) (i32.const 2)) +(assert_return (invoke "div_s" (i32.const 17) (i32.const 7)) (i32.const 2)) + +(assert_trap (invoke "div_u" (i32.const 1) (i32.const 0)) "integer divide by zero") +(assert_trap (invoke "div_u" (i32.const 0) (i32.const 0)) "integer divide by zero") +(assert_return (invoke "div_u" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "div_u" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "div_u" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "div_u" (i32.const 0x80000000) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "div_u" (i32.const 0x80000000) (i32.const 2)) (i32.const 0x40000000)) +(assert_return (invoke "div_u" (i32.const 0x8ff00ff0) (i32.const 0x10001)) (i32.const 0x8fef)) +(assert_return (invoke "div_u" (i32.const 0x80000001) (i32.const 1000)) (i32.const 0x20c49b)) +(assert_return (invoke "div_u" (i32.const 5) (i32.const 2)) (i32.const 2)) +(assert_return (invoke "div_u" (i32.const -5) (i32.const 2)) (i32.const 0x7ffffffd)) +(assert_return (invoke "div_u" (i32.const 5) (i32.const -2)) (i32.const 0)) +(assert_return (invoke "div_u" (i32.const -5) (i32.const -2)) (i32.const 0)) +(assert_return (invoke "div_u" (i32.const 7) (i32.const 3)) (i32.const 2)) +(assert_return (invoke "div_u" (i32.const 11) (i32.const 5)) (i32.const 2)) +(assert_return (invoke "div_u" (i32.const 17) (i32.const 7)) (i32.const 2)) + +(assert_trap (invoke "rem_s" (i32.const 1) (i32.const 0)) "integer divide by zero") +(assert_trap (invoke "rem_s" (i32.const 0) (i32.const 0)) "integer divide by zero") +(assert_return (invoke "rem_s" (i32.const 0x7fffffff) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "rem_s" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "rem_s" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "rem_s" (i32.const 0) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "rem_s" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "rem_s" (i32.const 0x80000000) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "rem_s" (i32.const 0x80000000) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "rem_s" (i32.const 0x80000001) (i32.const 1000)) (i32.const -647)) +(assert_return (invoke "rem_s" (i32.const 5) (i32.const 2)) (i32.const 1)) +(assert_return (invoke "rem_s" (i32.const -5) (i32.const 2)) (i32.const -1)) +(assert_return (invoke "rem_s" (i32.const 5) (i32.const -2)) (i32.const 1)) +(assert_return (invoke "rem_s" (i32.const -5) (i32.const -2)) (i32.const -1)) +(assert_return (invoke "rem_s" (i32.const 7) (i32.const 3)) (i32.const 1)) +(assert_return (invoke "rem_s" (i32.const -7) (i32.const 3)) (i32.const -1)) +(assert_return (invoke "rem_s" (i32.const 7) (i32.const -3)) (i32.const 1)) +(assert_return (invoke "rem_s" (i32.const -7) (i32.const -3)) (i32.const -1)) +(assert_return (invoke "rem_s" (i32.const 11) (i32.const 5)) (i32.const 1)) +(assert_return (invoke "rem_s" (i32.const 17) (i32.const 7)) (i32.const 3)) + +(assert_trap (invoke "rem_u" (i32.const 1) (i32.const 0)) "integer divide by zero") +(assert_trap (invoke "rem_u" (i32.const 0) (i32.const 0)) "integer divide by zero") +(assert_return (invoke "rem_u" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "rem_u" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "rem_u" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "rem_u" (i32.const 0x80000000) (i32.const -1)) (i32.const 0x80000000)) +(assert_return (invoke "rem_u" (i32.const 0x80000000) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "rem_u" (i32.const 0x8ff00ff0) (i32.const 0x10001)) (i32.const 0x8001)) +(assert_return (invoke "rem_u" (i32.const 0x80000001) (i32.const 1000)) (i32.const 649)) +(assert_return (invoke "rem_u" (i32.const 5) (i32.const 2)) (i32.const 1)) +(assert_return (invoke "rem_u" (i32.const -5) (i32.const 2)) (i32.const 1)) +(assert_return (invoke "rem_u" (i32.const 5) (i32.const -2)) (i32.const 5)) +(assert_return (invoke "rem_u" (i32.const -5) (i32.const -2)) (i32.const -5)) +(assert_return (invoke "rem_u" (i32.const 7) (i32.const 3)) (i32.const 1)) +(assert_return (invoke "rem_u" (i32.const 11) (i32.const 5)) (i32.const 1)) +(assert_return (invoke "rem_u" (i32.const 17) (i32.const 7)) (i32.const 3)) + +(assert_return (invoke "and" (i32.const 1) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "and" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "and" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "and" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "and" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "and" (i32.const 0x7fffffff) (i32.const -1)) (i32.const 0x7fffffff)) +(assert_return (invoke "and" (i32.const 0xf0f0ffff) (i32.const 0xfffff0f0)) (i32.const 0xf0f0f0f0)) +(assert_return (invoke "and" (i32.const 0xffffffff) (i32.const 0xffffffff)) (i32.const 0xffffffff)) + +(assert_return (invoke "or" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "or" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "or" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "or" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "or" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const -1)) +(assert_return (invoke "or" (i32.const 0x80000000) (i32.const 0)) (i32.const 0x80000000)) +(assert_return (invoke "or" (i32.const 0xf0f0ffff) (i32.const 0xfffff0f0)) (i32.const 0xffffffff)) +(assert_return (invoke "or" (i32.const 0xffffffff) (i32.const 0xffffffff)) (i32.const 0xffffffff)) + +(assert_return (invoke "xor" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "xor" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "xor" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "xor" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "xor" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const -1)) +(assert_return (invoke "xor" (i32.const 0x80000000) (i32.const 0)) (i32.const 0x80000000)) +(assert_return (invoke "xor" (i32.const -1) (i32.const 0x80000000)) (i32.const 0x7fffffff)) +(assert_return (invoke "xor" (i32.const -1) (i32.const 0x7fffffff)) (i32.const 0x80000000)) +(assert_return (invoke "xor" (i32.const 0xf0f0ffff) (i32.const 0xfffff0f0)) (i32.const 0x0f0f0f0f)) +(assert_return (invoke "xor" (i32.const 0xffffffff) (i32.const 0xffffffff)) (i32.const 0)) + +(assert_return (invoke "shl" (i32.const 1) (i32.const 1)) (i32.const 2)) +(assert_return (invoke "shl" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "shl" (i32.const 0x7fffffff) (i32.const 1)) (i32.const 0xfffffffe)) +(assert_return (invoke "shl" (i32.const 0xffffffff) (i32.const 1)) (i32.const 0xfffffffe)) +(assert_return (invoke "shl" (i32.const 0x80000000) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "shl" (i32.const 0x40000000) (i32.const 1)) (i32.const 0x80000000)) +(assert_return (invoke "shl" (i32.const 1) (i32.const 31)) (i32.const 0x80000000)) +(assert_return (invoke "shl" (i32.const 1) (i32.const 32)) (i32.const 1)) +(assert_return (invoke "shl" (i32.const 1) (i32.const 33)) (i32.const 2)) +(assert_return (invoke "shl" (i32.const 1) (i32.const -1)) (i32.const 0x80000000)) +(assert_return (invoke "shl" (i32.const 1) (i32.const 0x7fffffff)) (i32.const 0x80000000)) + +(assert_return (invoke "shr_s" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "shr_s" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "shr_s" (i32.const -1) (i32.const 1)) (i32.const -1)) +(assert_return (invoke "shr_s" (i32.const 0x7fffffff) (i32.const 1)) (i32.const 0x3fffffff)) +(assert_return (invoke "shr_s" (i32.const 0x80000000) (i32.const 1)) (i32.const 0xc0000000)) +(assert_return (invoke "shr_s" (i32.const 0x40000000) (i32.const 1)) (i32.const 0x20000000)) +(assert_return (invoke "shr_s" (i32.const 1) (i32.const 32)) (i32.const 1)) +(assert_return (invoke "shr_s" (i32.const 1) (i32.const 33)) (i32.const 0)) +(assert_return (invoke "shr_s" (i32.const 1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "shr_s" (i32.const 1) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "shr_s" (i32.const 1) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "shr_s" (i32.const 0x80000000) (i32.const 31)) (i32.const -1)) +(assert_return (invoke "shr_s" (i32.const -1) (i32.const 32)) (i32.const -1)) +(assert_return (invoke "shr_s" (i32.const -1) (i32.const 33)) (i32.const -1)) +(assert_return (invoke "shr_s" (i32.const -1) (i32.const -1)) (i32.const -1)) +(assert_return (invoke "shr_s" (i32.const -1) (i32.const 0x7fffffff)) (i32.const -1)) +(assert_return (invoke "shr_s" (i32.const -1) (i32.const 0x80000000)) (i32.const -1)) + +(assert_return (invoke "shr_u" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "shr_u" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "shr_u" (i32.const -1) (i32.const 1)) (i32.const 0x7fffffff)) +(assert_return (invoke "shr_u" (i32.const 0x7fffffff) (i32.const 1)) (i32.const 0x3fffffff)) +(assert_return (invoke "shr_u" (i32.const 0x80000000) (i32.const 1)) (i32.const 0x40000000)) +(assert_return (invoke "shr_u" (i32.const 0x40000000) (i32.const 1)) (i32.const 0x20000000)) +(assert_return (invoke "shr_u" (i32.const 1) (i32.const 32)) (i32.const 1)) +(assert_return (invoke "shr_u" (i32.const 1) (i32.const 33)) (i32.const 0)) +(assert_return (invoke "shr_u" (i32.const 1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "shr_u" (i32.const 1) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "shr_u" (i32.const 1) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "shr_u" (i32.const 0x80000000) (i32.const 31)) (i32.const 1)) +(assert_return (invoke "shr_u" (i32.const -1) (i32.const 32)) (i32.const -1)) +(assert_return (invoke "shr_u" (i32.const -1) (i32.const 33)) (i32.const 0x7fffffff)) +(assert_return (invoke "shr_u" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "shr_u" (i32.const -1) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "shr_u" (i32.const -1) (i32.const 0x80000000)) (i32.const -1)) + +(assert_return (invoke "rotl" (i32.const 1) (i32.const 1)) (i32.const 2)) +(assert_return (invoke "rotl" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "rotl" (i32.const -1) (i32.const 1)) (i32.const -1)) +(assert_return (invoke "rotl" (i32.const 1) (i32.const 32)) (i32.const 1)) +(assert_return (invoke "rotl" (i32.const 0xabcd9876) (i32.const 1)) (i32.const 0x579b30ed)) +(assert_return (invoke "rotl" (i32.const 0xfe00dc00) (i32.const 4)) (i32.const 0xe00dc00f)) +(assert_return (invoke "rotl" (i32.const 0xb0c1d2e3) (i32.const 5)) (i32.const 0x183a5c76)) +(assert_return (invoke "rotl" (i32.const 0x00008000) (i32.const 37)) (i32.const 0x00100000)) +(assert_return (invoke "rotl" (i32.const 0xb0c1d2e3) (i32.const 0xff05)) (i32.const 0x183a5c76)) +(assert_return (invoke "rotl" (i32.const 0x769abcdf) (i32.const 0xffffffed)) (i32.const 0x579beed3)) +(assert_return (invoke "rotl" (i32.const 0x769abcdf) (i32.const 0x8000000d)) (i32.const 0x579beed3)) +(assert_return (invoke "rotl" (i32.const 1) (i32.const 31)) (i32.const 0x80000000)) +(assert_return (invoke "rotl" (i32.const 0x80000000) (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "rotr" (i32.const 1) (i32.const 1)) (i32.const 0x80000000)) +(assert_return (invoke "rotr" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "rotr" (i32.const -1) (i32.const 1)) (i32.const -1)) +(assert_return (invoke "rotr" (i32.const 1) (i32.const 32)) (i32.const 1)) +(assert_return (invoke "rotr" (i32.const 0xff00cc00) (i32.const 1)) (i32.const 0x7f806600)) +(assert_return (invoke "rotr" (i32.const 0x00080000) (i32.const 4)) (i32.const 0x00008000)) +(assert_return (invoke "rotr" (i32.const 0xb0c1d2e3) (i32.const 5)) (i32.const 0x1d860e97)) +(assert_return (invoke "rotr" (i32.const 0x00008000) (i32.const 37)) (i32.const 0x00000400)) +(assert_return (invoke "rotr" (i32.const 0xb0c1d2e3) (i32.const 0xff05)) (i32.const 0x1d860e97)) +(assert_return (invoke "rotr" (i32.const 0x769abcdf) (i32.const 0xffffffed)) (i32.const 0xe6fbb4d5)) +(assert_return (invoke "rotr" (i32.const 0x769abcdf) (i32.const 0x8000000d)) (i32.const 0xe6fbb4d5)) +(assert_return (invoke "rotr" (i32.const 1) (i32.const 31)) (i32.const 2)) +(assert_return (invoke "rotr" (i32.const 0x80000000) (i32.const 31)) (i32.const 1)) + +(assert_return (invoke "clz" (i32.const 0xffffffff)) (i32.const 0)) +(assert_return (invoke "clz" (i32.const 0)) (i32.const 32)) +(assert_return (invoke "clz" (i32.const 0x00008000)) (i32.const 16)) +(assert_return (invoke "clz" (i32.const 0xff)) (i32.const 24)) +(assert_return (invoke "clz" (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "clz" (i32.const 1)) (i32.const 31)) +(assert_return (invoke "clz" (i32.const 2)) (i32.const 30)) +(assert_return (invoke "clz" (i32.const 0x7fffffff)) (i32.const 1)) + +(assert_return (invoke "ctz" (i32.const -1)) (i32.const 0)) +(assert_return (invoke "ctz" (i32.const 0)) (i32.const 32)) +(assert_return (invoke "ctz" (i32.const 0x00008000)) (i32.const 15)) +(assert_return (invoke "ctz" (i32.const 0x00010000)) (i32.const 16)) +(assert_return (invoke "ctz" (i32.const 0x80000000)) (i32.const 31)) +(assert_return (invoke "ctz" (i32.const 0x7fffffff)) (i32.const 0)) + +(assert_return (invoke "popcnt" (i32.const -1)) (i32.const 32)) +(assert_return (invoke "popcnt" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "popcnt" (i32.const 0x00008000)) (i32.const 1)) +(assert_return (invoke "popcnt" (i32.const 0x80008000)) (i32.const 2)) +(assert_return (invoke "popcnt" (i32.const 0x7fffffff)) (i32.const 31)) +(assert_return (invoke "popcnt" (i32.const 0xAAAAAAAA)) (i32.const 16)) +(assert_return (invoke "popcnt" (i32.const 0x55555555)) (i32.const 16)) +(assert_return (invoke "popcnt" (i32.const 0xDEADBEEF)) (i32.const 24)) + +(assert_return (invoke "eqz" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "eqz" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eqz" (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "eqz" (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "eqz" (i32.const 0xffffffff)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const -1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0x80000000) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0x80000000) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const -1) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 0)) + +(assert_return (invoke "ne" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "ne" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "ne" (i32.const -1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "ne" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "ne" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "ne" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const 0x80000000) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const 0) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const 0x80000000) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const -1) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "ne" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 1)) + +(assert_return (invoke "lt_s" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const -1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "lt_s" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const 1) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "lt_s" (i32.const 0x80000000) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "lt_s" (i32.const 0) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const 0x80000000) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "lt_s" (i32.const -1) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "lt_s" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "lt_s" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 0)) + +(assert_return (invoke "lt_u" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const -1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 1) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "lt_u" (i32.const 0x80000000) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 0) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "lt_u" (i32.const 0x80000000) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "lt_u" (i32.const -1) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "lt_u" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 1)) + +(assert_return (invoke "le_s" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const -1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const 1) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "le_s" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const 0x80000000) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const 0) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "le_s" (i32.const 0x80000000) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const -1) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "le_s" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "le_s" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 0)) + +(assert_return (invoke "le_u" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const -1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "le_u" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const 1) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "le_u" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const 0x80000000) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "le_u" (i32.const 0) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const 0x80000000) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "le_u" (i32.const -1) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "le_u" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "le_u" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 1)) + +(assert_return (invoke "gt_s" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const -1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "gt_s" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const 0x80000000) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const 0) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "gt_s" (i32.const 0x80000000) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const -1) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "gt_s" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "gt_s" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 1)) + +(assert_return (invoke "gt_u" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const 1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const -1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "gt_u" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const -1) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "gt_u" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const 0x80000000) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "gt_u" (i32.const 0) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const 0x80000000) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i32.const -1) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "gt_u" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "gt_u" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 0)) + +(assert_return (invoke "ge_s" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const -1) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "ge_s" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "ge_s" (i32.const 0x80000000) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "ge_s" (i32.const 0) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const 0x80000000) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "ge_s" (i32.const -1) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "ge_s" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 0)) +(assert_return (invoke "ge_s" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 1)) + +(assert_return (invoke "ge_u" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const -1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 0x80000000) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 0x7fffffff) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const -1) (i32.const -1)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "ge_u" (i32.const 0x80000000) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 0) (i32.const 0x80000000)) (i32.const 0)) +(assert_return (invoke "ge_u" (i32.const 0x80000000) (i32.const -1)) (i32.const 0)) +(assert_return (invoke "ge_u" (i32.const -1) (i32.const 0x80000000)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 0x80000000) (i32.const 0x7fffffff)) (i32.const 1)) +(assert_return (invoke "ge_u" (i32.const 0x7fffffff) (i32.const 0x80000000)) (i32.const 0)) diff --git a/tests/misc_testsuite/winch/i64.wast b/tests/misc_testsuite/winch/i64.wast new file mode 100644 index 000000000000..1783c61782d1 --- /dev/null +++ b/tests/misc_testsuite/winch/i64.wast @@ -0,0 +1,422 @@ +;; i64 operations + +(module + (func (export "add") (param $x i64) (param $y i64) (result i64) (i64.add (local.get $x) (local.get $y))) + (func (export "sub") (param $x i64) (param $y i64) (result i64) (i64.sub (local.get $x) (local.get $y))) + (func (export "mul") (param $x i64) (param $y i64) (result i64) (i64.mul (local.get $x) (local.get $y))) + (func (export "div_s") (param $x i64) (param $y i64) (result i64) (i64.div_s (local.get $x) (local.get $y))) + (func (export "div_u") (param $x i64) (param $y i64) (result i64) (i64.div_u (local.get $x) (local.get $y))) + (func (export "rem_s") (param $x i64) (param $y i64) (result i64) (i64.rem_s (local.get $x) (local.get $y))) + (func (export "rem_u") (param $x i64) (param $y i64) (result i64) (i64.rem_u (local.get $x) (local.get $y))) + (func (export "and") (param $x i64) (param $y i64) (result i64) (i64.and (local.get $x) (local.get $y))) + (func (export "or") (param $x i64) (param $y i64) (result i64) (i64.or (local.get $x) (local.get $y))) + (func (export "xor") (param $x i64) (param $y i64) (result i64) (i64.xor (local.get $x) (local.get $y))) + (func (export "shl") (param $x i64) (param $y i64) (result i64) (i64.shl (local.get $x) (local.get $y))) + (func (export "shr_s") (param $x i64) (param $y i64) (result i64) (i64.shr_s (local.get $x) (local.get $y))) + (func (export "shr_u") (param $x i64) (param $y i64) (result i64) (i64.shr_u (local.get $x) (local.get $y))) + (func (export "rotl") (param $x i64) (param $y i64) (result i64) (i64.rotl (local.get $x) (local.get $y))) + (func (export "rotr") (param $x i64) (param $y i64) (result i64) (i64.rotr (local.get $x) (local.get $y))) + (func (export "clz") (param $x i64) (result i64) (i64.clz (local.get $x))) + (func (export "ctz") (param $x i64) (result i64) (i64.ctz (local.get $x))) + (func (export "popcnt") (param $x i64) (result i64) (i64.popcnt (local.get $x))) + (func (export "eqz") (param $x i64) (result i32) (i64.eqz (local.get $x))) + (func (export "eq") (param $x i64) (param $y i64) (result i32) (i64.eq (local.get $x) (local.get $y))) + (func (export "ne") (param $x i64) (param $y i64) (result i32) (i64.ne (local.get $x) (local.get $y))) + (func (export "lt_s") (param $x i64) (param $y i64) (result i32) (i64.lt_s (local.get $x) (local.get $y))) + (func (export "lt_u") (param $x i64) (param $y i64) (result i32) (i64.lt_u (local.get $x) (local.get $y))) + (func (export "le_s") (param $x i64) (param $y i64) (result i32) (i64.le_s (local.get $x) (local.get $y))) + (func (export "le_u") (param $x i64) (param $y i64) (result i32) (i64.le_u (local.get $x) (local.get $y))) + (func (export "gt_s") (param $x i64) (param $y i64) (result i32) (i64.gt_s (local.get $x) (local.get $y))) + (func (export "gt_u") (param $x i64) (param $y i64) (result i32) (i64.gt_u (local.get $x) (local.get $y))) + (func (export "ge_s") (param $x i64) (param $y i64) (result i32) (i64.ge_s (local.get $x) (local.get $y))) + (func (export "ge_u") (param $x i64) (param $y i64) (result i32) (i64.ge_u (local.get $x) (local.get $y))) +) + +(assert_return (invoke "add" (i64.const 1) (i64.const 1)) (i64.const 2)) +(assert_return (invoke "add" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "add" (i64.const -1) (i64.const -1)) (i64.const -2)) +(assert_return (invoke "add" (i64.const -1) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "add" (i64.const 0x7fffffffffffffff) (i64.const 1)) (i64.const 0x8000000000000000)) +(assert_return (invoke "add" (i64.const 0x8000000000000000) (i64.const -1)) (i64.const 0x7fffffffffffffff)) +(assert_return (invoke "add" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i64.const 0)) +(assert_return (invoke "add" (i64.const 0x3fffffff) (i64.const 1)) (i64.const 0x40000000)) + +(assert_return (invoke "sub" (i64.const 1) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "sub" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "sub" (i64.const -1) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "sub" (i64.const 0x7fffffffffffffff) (i64.const -1)) (i64.const 0x8000000000000000)) +(assert_return (invoke "sub" (i64.const 0x8000000000000000) (i64.const 1)) (i64.const 0x7fffffffffffffff)) +(assert_return (invoke "sub" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i64.const 0)) +(assert_return (invoke "sub" (i64.const 0x3fffffff) (i64.const -1)) (i64.const 0x40000000)) + +(assert_return (invoke "mul" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "mul" (i64.const 1) (i64.const 0)) (i64.const 0)) +(assert_return (invoke "mul" (i64.const -1) (i64.const -1)) (i64.const 1)) +(assert_return (invoke "mul" (i64.const 0x1000000000000000) (i64.const 4096)) (i64.const 0)) +(assert_return (invoke "mul" (i64.const 0x8000000000000000) (i64.const 0)) (i64.const 0)) +(assert_return (invoke "mul" (i64.const 0x8000000000000000) (i64.const -1)) (i64.const 0x8000000000000000)) +(assert_return (invoke "mul" (i64.const 0x7fffffffffffffff) (i64.const -1)) (i64.const 0x8000000000000001)) +(assert_return (invoke "mul" (i64.const 0x0123456789abcdef) (i64.const 0xfedcba9876543210)) (i64.const 0x2236d88fe5618cf0)) +(assert_return (invoke "mul" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i64.const 1)) + +(assert_trap (invoke "div_s" (i64.const 1) (i64.const 0)) "integer divide by zero") +(assert_trap (invoke "div_s" (i64.const 0) (i64.const 0)) "integer divide by zero") +(assert_trap (invoke "div_s" (i64.const 0x8000000000000000) (i64.const -1)) "integer overflow") +(assert_trap (invoke "div_s" (i64.const 0x8000000000000000) (i64.const 0)) "integer divide by zero") +(assert_return (invoke "div_s" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "div_s" (i64.const 0) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "div_s" (i64.const 0) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "div_s" (i64.const -1) (i64.const -1)) (i64.const 1)) +(assert_return (invoke "div_s" (i64.const 0x8000000000000000) (i64.const 2)) (i64.const 0xc000000000000000)) +(assert_return (invoke "div_s" (i64.const 0x8000000000000001) (i64.const 1000)) (i64.const 0xffdf3b645a1cac09)) +(assert_return (invoke "div_s" (i64.const 5) (i64.const 2)) (i64.const 2)) +(assert_return (invoke "div_s" (i64.const -5) (i64.const 2)) (i64.const -2)) +(assert_return (invoke "div_s" (i64.const 5) (i64.const -2)) (i64.const -2)) +(assert_return (invoke "div_s" (i64.const -5) (i64.const -2)) (i64.const 2)) +(assert_return (invoke "div_s" (i64.const 7) (i64.const 3)) (i64.const 2)) +(assert_return (invoke "div_s" (i64.const -7) (i64.const 3)) (i64.const -2)) +(assert_return (invoke "div_s" (i64.const 7) (i64.const -3)) (i64.const -2)) +(assert_return (invoke "div_s" (i64.const -7) (i64.const -3)) (i64.const 2)) +(assert_return (invoke "div_s" (i64.const 11) (i64.const 5)) (i64.const 2)) +(assert_return (invoke "div_s" (i64.const 17) (i64.const 7)) (i64.const 2)) + +(assert_trap (invoke "div_u" (i64.const 1) (i64.const 0)) "integer divide by zero") +(assert_trap (invoke "div_u" (i64.const 0) (i64.const 0)) "integer divide by zero") +(assert_return (invoke "div_u" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "div_u" (i64.const 0) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "div_u" (i64.const -1) (i64.const -1)) (i64.const 1)) +(assert_return (invoke "div_u" (i64.const 0x8000000000000000) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "div_u" (i64.const 0x8000000000000000) (i64.const 2)) (i64.const 0x4000000000000000)) +(assert_return (invoke "div_u" (i64.const 0x8ff00ff00ff00ff0) (i64.const 0x100000001)) (i64.const 0x8ff00fef)) +(assert_return (invoke "div_u" (i64.const 0x8000000000000001) (i64.const 1000)) (i64.const 0x20c49ba5e353f7)) +(assert_return (invoke "div_u" (i64.const 5) (i64.const 2)) (i64.const 2)) +(assert_return (invoke "div_u" (i64.const -5) (i64.const 2)) (i64.const 0x7ffffffffffffffd)) +(assert_return (invoke "div_u" (i64.const 5) (i64.const -2)) (i64.const 0)) +(assert_return (invoke "div_u" (i64.const -5) (i64.const -2)) (i64.const 0)) +(assert_return (invoke "div_u" (i64.const 7) (i64.const 3)) (i64.const 2)) +(assert_return (invoke "div_u" (i64.const 11) (i64.const 5)) (i64.const 2)) +(assert_return (invoke "div_u" (i64.const 17) (i64.const 7)) (i64.const 2)) + +(assert_trap (invoke "rem_s" (i64.const 1) (i64.const 0)) "integer divide by zero") +(assert_trap (invoke "rem_s" (i64.const 0) (i64.const 0)) "integer divide by zero") +(assert_return (invoke "rem_s" (i64.const 0x7fffffffffffffff) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "rem_s" (i64.const 1) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "rem_s" (i64.const 0) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "rem_s" (i64.const 0) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "rem_s" (i64.const -1) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "rem_s" (i64.const 0x8000000000000000) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "rem_s" (i64.const 0x8000000000000000) (i64.const 2)) (i64.const 0)) +(assert_return (invoke "rem_s" (i64.const 0x8000000000000001) (i64.const 1000)) (i64.const -807)) +(assert_return (invoke "rem_s" (i64.const 5) (i64.const 2)) (i64.const 1)) +(assert_return (invoke "rem_s" (i64.const -5) (i64.const 2)) (i64.const -1)) +(assert_return (invoke "rem_s" (i64.const 5) (i64.const -2)) (i64.const 1)) +(assert_return (invoke "rem_s" (i64.const -5) (i64.const -2)) (i64.const -1)) +(assert_return (invoke "rem_s" (i64.const 7) (i64.const 3)) (i64.const 1)) +(assert_return (invoke "rem_s" (i64.const -7) (i64.const 3)) (i64.const -1)) +(assert_return (invoke "rem_s" (i64.const 7) (i64.const -3)) (i64.const 1)) +(assert_return (invoke "rem_s" (i64.const -7) (i64.const -3)) (i64.const -1)) +(assert_return (invoke "rem_s" (i64.const 11) (i64.const 5)) (i64.const 1)) +(assert_return (invoke "rem_s" (i64.const 17) (i64.const 7)) (i64.const 3)) + +(assert_trap (invoke "rem_u" (i64.const 1) (i64.const 0)) "integer divide by zero") +(assert_trap (invoke "rem_u" (i64.const 0) (i64.const 0)) "integer divide by zero") +(assert_return (invoke "rem_u" (i64.const 1) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "rem_u" (i64.const 0) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "rem_u" (i64.const -1) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "rem_u" (i64.const 0x8000000000000000) (i64.const -1)) (i64.const 0x8000000000000000)) +(assert_return (invoke "rem_u" (i64.const 0x8000000000000000) (i64.const 2)) (i64.const 0)) +(assert_return (invoke "rem_u" (i64.const 0x8ff00ff00ff00ff0) (i64.const 0x100000001)) (i64.const 0x80000001)) +(assert_return (invoke "rem_u" (i64.const 0x8000000000000001) (i64.const 1000)) (i64.const 809)) +(assert_return (invoke "rem_u" (i64.const 5) (i64.const 2)) (i64.const 1)) +(assert_return (invoke "rem_u" (i64.const -5) (i64.const 2)) (i64.const 1)) +(assert_return (invoke "rem_u" (i64.const 5) (i64.const -2)) (i64.const 5)) +(assert_return (invoke "rem_u" (i64.const -5) (i64.const -2)) (i64.const -5)) +(assert_return (invoke "rem_u" (i64.const 7) (i64.const 3)) (i64.const 1)) +(assert_return (invoke "rem_u" (i64.const 11) (i64.const 5)) (i64.const 1)) +(assert_return (invoke "rem_u" (i64.const 17) (i64.const 7)) (i64.const 3)) + +(assert_return (invoke "and" (i64.const 1) (i64.const 0)) (i64.const 0)) +(assert_return (invoke "and" (i64.const 0) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "and" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "and" (i64.const 0) (i64.const 0)) (i64.const 0)) +(assert_return (invoke "and" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i64.const 0)) +(assert_return (invoke "and" (i64.const 0x7fffffffffffffff) (i64.const -1)) (i64.const 0x7fffffffffffffff)) +(assert_return (invoke "and" (i64.const 0xf0f0ffff) (i64.const 0xfffff0f0)) (i64.const 0xf0f0f0f0)) +(assert_return (invoke "and" (i64.const 0xffffffffffffffff) (i64.const 0xffffffffffffffff)) (i64.const 0xffffffffffffffff)) + +(assert_return (invoke "or" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "or" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "or" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "or" (i64.const 0) (i64.const 0)) (i64.const 0)) +(assert_return (invoke "or" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i64.const -1)) +(assert_return (invoke "or" (i64.const 0x8000000000000000) (i64.const 0)) (i64.const 0x8000000000000000)) +(assert_return (invoke "or" (i64.const 0xf0f0ffff) (i64.const 0xfffff0f0)) (i64.const 0xffffffff)) +(assert_return (invoke "or" (i64.const 0xffffffffffffffff) (i64.const 0xffffffffffffffff)) (i64.const 0xffffffffffffffff)) + +(assert_return (invoke "xor" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "xor" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "xor" (i64.const 1) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "xor" (i64.const 0) (i64.const 0)) (i64.const 0)) +(assert_return (invoke "xor" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i64.const -1)) +(assert_return (invoke "xor" (i64.const 0x8000000000000000) (i64.const 0)) (i64.const 0x8000000000000000)) +(assert_return (invoke "xor" (i64.const -1) (i64.const 0x8000000000000000)) (i64.const 0x7fffffffffffffff)) +(assert_return (invoke "xor" (i64.const -1) (i64.const 0x7fffffffffffffff)) (i64.const 0x8000000000000000)) +(assert_return (invoke "xor" (i64.const 0xf0f0ffff) (i64.const 0xfffff0f0)) (i64.const 0x0f0f0f0f)) +(assert_return (invoke "xor" (i64.const 0xffffffffffffffff) (i64.const 0xffffffffffffffff)) (i64.const 0)) + +(assert_return (invoke "shl" (i64.const 1) (i64.const 1)) (i64.const 2)) +(assert_return (invoke "shl" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "shl" (i64.const 0x7fffffffffffffff) (i64.const 1)) (i64.const 0xfffffffffffffffe)) +(assert_return (invoke "shl" (i64.const 0xffffffffffffffff) (i64.const 1)) (i64.const 0xfffffffffffffffe)) +(assert_return (invoke "shl" (i64.const 0x8000000000000000) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "shl" (i64.const 0x4000000000000000) (i64.const 1)) (i64.const 0x8000000000000000)) +(assert_return (invoke "shl" (i64.const 1) (i64.const 63)) (i64.const 0x8000000000000000)) +(assert_return (invoke "shl" (i64.const 1) (i64.const 64)) (i64.const 1)) +(assert_return (invoke "shl" (i64.const 1) (i64.const 65)) (i64.const 2)) +(assert_return (invoke "shl" (i64.const 1) (i64.const -1)) (i64.const 0x8000000000000000)) +(assert_return (invoke "shl" (i64.const 1) (i64.const 0x7fffffffffffffff)) (i64.const 0x8000000000000000)) + +(assert_return (invoke "shr_s" (i64.const 1) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "shr_s" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "shr_s" (i64.const -1) (i64.const 1)) (i64.const -1)) +(assert_return (invoke "shr_s" (i64.const 0x7fffffffffffffff) (i64.const 1)) (i64.const 0x3fffffffffffffff)) +(assert_return (invoke "shr_s" (i64.const 0x8000000000000000) (i64.const 1)) (i64.const 0xc000000000000000)) +(assert_return (invoke "shr_s" (i64.const 0x4000000000000000) (i64.const 1)) (i64.const 0x2000000000000000)) +(assert_return (invoke "shr_s" (i64.const 1) (i64.const 64)) (i64.const 1)) +(assert_return (invoke "shr_s" (i64.const 1) (i64.const 65)) (i64.const 0)) +(assert_return (invoke "shr_s" (i64.const 1) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "shr_s" (i64.const 1) (i64.const 0x7fffffffffffffff)) (i64.const 0)) +(assert_return (invoke "shr_s" (i64.const 1) (i64.const 0x8000000000000000)) (i64.const 1)) +(assert_return (invoke "shr_s" (i64.const 0x8000000000000000) (i64.const 63)) (i64.const -1)) +(assert_return (invoke "shr_s" (i64.const -1) (i64.const 64)) (i64.const -1)) +(assert_return (invoke "shr_s" (i64.const -1) (i64.const 65)) (i64.const -1)) +(assert_return (invoke "shr_s" (i64.const -1) (i64.const -1)) (i64.const -1)) +(assert_return (invoke "shr_s" (i64.const -1) (i64.const 0x7fffffffffffffff)) (i64.const -1)) +(assert_return (invoke "shr_s" (i64.const -1) (i64.const 0x8000000000000000)) (i64.const -1)) + +(assert_return (invoke "shr_u" (i64.const 1) (i64.const 1)) (i64.const 0)) +(assert_return (invoke "shr_u" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "shr_u" (i64.const -1) (i64.const 1)) (i64.const 0x7fffffffffffffff)) +(assert_return (invoke "shr_u" (i64.const 0x7fffffffffffffff) (i64.const 1)) (i64.const 0x3fffffffffffffff)) +(assert_return (invoke "shr_u" (i64.const 0x8000000000000000) (i64.const 1)) (i64.const 0x4000000000000000)) +(assert_return (invoke "shr_u" (i64.const 0x4000000000000000) (i64.const 1)) (i64.const 0x2000000000000000)) +(assert_return (invoke "shr_u" (i64.const 1) (i64.const 64)) (i64.const 1)) +(assert_return (invoke "shr_u" (i64.const 1) (i64.const 65)) (i64.const 0)) +(assert_return (invoke "shr_u" (i64.const 1) (i64.const -1)) (i64.const 0)) +(assert_return (invoke "shr_u" (i64.const 1) (i64.const 0x7fffffffffffffff)) (i64.const 0)) +(assert_return (invoke "shr_u" (i64.const 1) (i64.const 0x8000000000000000)) (i64.const 1)) +(assert_return (invoke "shr_u" (i64.const 0x8000000000000000) (i64.const 63)) (i64.const 1)) +(assert_return (invoke "shr_u" (i64.const -1) (i64.const 64)) (i64.const -1)) +(assert_return (invoke "shr_u" (i64.const -1) (i64.const 65)) (i64.const 0x7fffffffffffffff)) +(assert_return (invoke "shr_u" (i64.const -1) (i64.const -1)) (i64.const 1)) +(assert_return (invoke "shr_u" (i64.const -1) (i64.const 0x7fffffffffffffff)) (i64.const 1)) +(assert_return (invoke "shr_u" (i64.const -1) (i64.const 0x8000000000000000)) (i64.const -1)) + +(assert_return (invoke "rotl" (i64.const 1) (i64.const 1)) (i64.const 2)) +(assert_return (invoke "rotl" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "rotl" (i64.const -1) (i64.const 1)) (i64.const -1)) +(assert_return (invoke "rotl" (i64.const 1) (i64.const 64)) (i64.const 1)) +(assert_return (invoke "rotl" (i64.const 0xabcd987602468ace) (i64.const 1)) (i64.const 0x579b30ec048d159d)) +(assert_return (invoke "rotl" (i64.const 0xfe000000dc000000) (i64.const 4)) (i64.const 0xe000000dc000000f)) +(assert_return (invoke "rotl" (i64.const 0xabcd1234ef567809) (i64.const 53)) (i64.const 0x013579a2469deacf)) +(assert_return (invoke "rotl" (i64.const 0xabd1234ef567809c) (i64.const 63)) (i64.const 0x55e891a77ab3c04e)) +(assert_return (invoke "rotl" (i64.const 0xabcd1234ef567809) (i64.const 0xf5)) (i64.const 0x013579a2469deacf)) +(assert_return (invoke "rotl" (i64.const 0xabcd7294ef567809) (i64.const 0xffffffffffffffed)) (i64.const 0xcf013579ae529dea)) +(assert_return (invoke "rotl" (i64.const 0xabd1234ef567809c) (i64.const 0x800000000000003f)) (i64.const 0x55e891a77ab3c04e)) +(assert_return (invoke "rotl" (i64.const 1) (i64.const 63)) (i64.const 0x8000000000000000)) +(assert_return (invoke "rotl" (i64.const 0x8000000000000000) (i64.const 1)) (i64.const 1)) + +(assert_return (invoke "rotr" (i64.const 1) (i64.const 1)) (i64.const 0x8000000000000000)) +(assert_return (invoke "rotr" (i64.const 1) (i64.const 0)) (i64.const 1)) +(assert_return (invoke "rotr" (i64.const -1) (i64.const 1)) (i64.const -1)) +(assert_return (invoke "rotr" (i64.const 1) (i64.const 64)) (i64.const 1)) +(assert_return (invoke "rotr" (i64.const 0xabcd987602468ace) (i64.const 1)) (i64.const 0x55e6cc3b01234567)) +(assert_return (invoke "rotr" (i64.const 0xfe000000dc000000) (i64.const 4)) (i64.const 0x0fe000000dc00000)) +(assert_return (invoke "rotr" (i64.const 0xabcd1234ef567809) (i64.const 53)) (i64.const 0x6891a77ab3c04d5e)) +(assert_return (invoke "rotr" (i64.const 0xabd1234ef567809c) (i64.const 63)) (i64.const 0x57a2469deacf0139)) +(assert_return (invoke "rotr" (i64.const 0xabcd1234ef567809) (i64.const 0xf5)) (i64.const 0x6891a77ab3c04d5e)) +(assert_return (invoke "rotr" (i64.const 0xabcd7294ef567809) (i64.const 0xffffffffffffffed)) (i64.const 0x94a77ab3c04d5e6b)) +(assert_return (invoke "rotr" (i64.const 0xabd1234ef567809c) (i64.const 0x800000000000003f)) (i64.const 0x57a2469deacf0139)) +(assert_return (invoke "rotr" (i64.const 1) (i64.const 63)) (i64.const 2)) +(assert_return (invoke "rotr" (i64.const 0x8000000000000000) (i64.const 63)) (i64.const 1)) + +(assert_return (invoke "clz" (i64.const 0xffffffffffffffff)) (i64.const 0)) +(assert_return (invoke "clz" (i64.const 0)) (i64.const 64)) +(assert_return (invoke "clz" (i64.const 0x00008000)) (i64.const 48)) +(assert_return (invoke "clz" (i64.const 0xff)) (i64.const 56)) +(assert_return (invoke "clz" (i64.const 0x8000000000000000)) (i64.const 0)) +(assert_return (invoke "clz" (i64.const 1)) (i64.const 63)) +(assert_return (invoke "clz" (i64.const 2)) (i64.const 62)) +(assert_return (invoke "clz" (i64.const 0x7fffffffffffffff)) (i64.const 1)) + +(assert_return (invoke "ctz" (i64.const -1)) (i64.const 0)) +(assert_return (invoke "ctz" (i64.const 0)) (i64.const 64)) +(assert_return (invoke "ctz" (i64.const 0x00008000)) (i64.const 15)) +(assert_return (invoke "ctz" (i64.const 0x00010000)) (i64.const 16)) +(assert_return (invoke "ctz" (i64.const 0x8000000000000000)) (i64.const 63)) +(assert_return (invoke "ctz" (i64.const 0x7fffffffffffffff)) (i64.const 0)) + +(assert_return (invoke "popcnt" (i64.const -1)) (i64.const 64)) +(assert_return (invoke "popcnt" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "popcnt" (i64.const 0x00008000)) (i64.const 1)) +(assert_return (invoke "popcnt" (i64.const 0x8000800080008000)) (i64.const 4)) +(assert_return (invoke "popcnt" (i64.const 0x7fffffffffffffff)) (i64.const 63)) +(assert_return (invoke "popcnt" (i64.const 0xAAAAAAAA55555555)) (i64.const 32)) +(assert_return (invoke "popcnt" (i64.const 0x99999999AAAAAAAA)) (i64.const 32)) +(assert_return (invoke "popcnt" (i64.const 0xDEADBEEFDEADBEEF)) (i64.const 48)) + +(assert_return (invoke "eqz" (i64.const 0)) (i32.const 1)) +(assert_return (invoke "eqz" (i64.const 1)) (i32.const 0)) +(assert_return (invoke "eqz" (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "eqz" (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "eqz" (i64.const 0xffffffffffffffff)) (i32.const 0)) + +(assert_return (invoke "eq" (i64.const 0) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "eq" (i64.const 1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "eq" (i64.const -1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "eq" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "eq" (i64.const -1) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "eq" (i64.const 1) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const 0) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "eq" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 0)) + +(assert_return (invoke "ne" (i64.const 0) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "ne" (i64.const 1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "ne" (i64.const -1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "ne" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "ne" (i64.const -1) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "ne" (i64.const 1) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const 0) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "ne" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 1)) + +(assert_return (invoke "lt_s" (i64.const 0) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const 1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const -1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "lt_s" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const -1) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const 1) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const 0) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "lt_s" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "lt_s" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "lt_s" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "lt_s" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "lt_s" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 0)) + +(assert_return (invoke "lt_u" (i64.const 0) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const -1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const -1) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 1) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 0) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "lt_u" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "lt_u" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "lt_u" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "lt_u" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 1)) + +(assert_return (invoke "le_s" (i64.const 0) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const 1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const -1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const -1) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const 1) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "le_s" (i64.const 0) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "le_s" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "le_s" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "le_s" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 0)) + +(assert_return (invoke "le_u" (i64.const 0) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const 1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const -1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "le_u" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const -1) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const 1) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "le_u" (i64.const 0) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "le_u" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "le_u" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "le_u" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "le_u" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 1)) + +(assert_return (invoke "gt_s" (i64.const 0) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const 1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const -1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const -1) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const 1) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "gt_s" (i64.const 0) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "gt_s" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "gt_s" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "gt_s" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 1)) + +(assert_return (invoke "gt_u" (i64.const 0) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const 1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const -1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "gt_u" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const -1) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const 1) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "gt_u" (i64.const 0) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "gt_u" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "gt_u" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "gt_u" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "gt_u" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 0)) + +(assert_return (invoke "ge_s" (i64.const 0) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const 1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const -1) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "ge_s" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const -1) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const 1) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const 0) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "ge_s" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 0)) +(assert_return (invoke "ge_s" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "ge_s" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "ge_s" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 0)) +(assert_return (invoke "ge_s" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 1)) + +(assert_return (invoke "ge_u" (i64.const 0) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const -1) (i64.const 1)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 0x7fffffffffffffff) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const -1) (i64.const -1)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 1) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 0) (i64.const 1)) (i32.const 0)) +(assert_return (invoke "ge_u" (i64.const 0x8000000000000000) (i64.const 0)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 0) (i64.const 0x8000000000000000)) (i32.const 0)) +(assert_return (invoke "ge_u" (i64.const 0x8000000000000000) (i64.const -1)) (i32.const 0)) +(assert_return (invoke "ge_u" (i64.const -1) (i64.const 0x8000000000000000)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 0x8000000000000000) (i64.const 0x7fffffffffffffff)) (i32.const 1)) +(assert_return (invoke "ge_u" (i64.const 0x7fffffffffffffff) (i64.const 0x8000000000000000)) (i32.const 0)) diff --git a/tests/misc_testsuite/winch/if.wast b/tests/misc_testsuite/winch/if.wast new file mode 100644 index 000000000000..79e054cfc78f --- /dev/null +++ b/tests/misc_testsuite/winch/if.wast @@ -0,0 +1,264 @@ +;; Test `if` operator + +(module + ;; Auxiliary definition + (memory 1) + + (func $dummy) + + (func (export "empty") (param i32) + (if (local.get 0) (then)) + (if (local.get 0) (then) (else)) + (if $l (local.get 0) (then)) + (if $l (local.get 0) (then) (else)) + ) + + (func (export "singular") (param i32) (result i32) + (if (local.get 0) (then (nop))) + (if (local.get 0) (then (nop)) (else (nop))) + (if (result i32) (local.get 0) (then (i32.const 7)) (else (i32.const 8))) + ) + + (func (export "nested") (param i32 i32) (result i32) + (if (result i32) (local.get 0) + (then + (if (local.get 1) (then (call $dummy) (block) (nop))) + (if (local.get 1) (then) (else (call $dummy) (block) (nop))) + (if (result i32) (local.get 1) + (then (call $dummy) (i32.const 9)) + (else (call $dummy) (i32.const 10)) + ) + ) + (else + (if (local.get 1) (then (call $dummy) (block) (nop))) + (if (local.get 1) (then) (else (call $dummy) (block) (nop))) + (if (result i32) (local.get 1) + (then (call $dummy) (i32.const 10)) + (else (call $dummy) (i32.const 11)) + ) + ) + ) + ) + + (func (export "as-loop-first") (param i32) (result i32) + (loop (result i32) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (call $dummy) (call $dummy) + ) + ) + (func (export "as-loop-mid") (param i32) (result i32) + (loop (result i32) + (call $dummy) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (call $dummy) + ) + ) + (func (export "as-loop-last") (param i32) (result i32) + (loop (result i32) + (call $dummy) (call $dummy) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + ) + ) + + (func (export "as-if-condition") (param i32) (result i32) + (if (result i32) + (if (result i32) (local.get 0) + (then (i32.const 1)) (else (i32.const 0)) + ) + (then (call $dummy) (i32.const 2)) + (else (call $dummy) (i32.const 3)) + ) + ) + + (func (export "as-br_if-first") (param i32) (result i32) + (block (result i32) + (br_if 0 + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 2) + ) + (return (i32.const 3)) + ) + ) + (func (export "as-br_if-last") (param i32) (result i32) + (block (result i32) + (br_if 0 + (i32.const 2) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + ) + (return (i32.const 3)) + ) + ) + + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "as-call-value") (param i32) (result i32) + (call $f + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + (func (export "as-return-value") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0))) + (return) + ) + (func (export "as-br-value") (param i32) (result i32) + (block (result i32) + (br 0 + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + ) + (func (export "as-local.set-value") (param i32) (result i32) + (local i32) + (local.set 0 + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + (local.get 0) + ) + (func (export "as-unary-operand") (param i32) (result i32) + (i32.ctz + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 13)) + (else (call $dummy) (i32.const -13)) + ) + ) + ) + (func (export "as-binary-operand") (param i32 i32) (result i32) + (i32.mul + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 3)) + (else (call $dummy) (i32.const -3)) + ) + (if (result i32) (local.get 1) + (then (call $dummy) (i32.const 4)) + (else (call $dummy) (i32.const -5)) + ) + ) + ) + (func (export "as-test-operand") (param i32) (result i32) + (i32.eqz + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 13)) + (else (call $dummy) (i32.const 0)) + ) + ) + ) + + (func (export "break-value") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (br 0 (i32.const 18)) (i32.const 19)) + (else (br 0 (i32.const 21)) (i32.const 20)) + ) + ) + + (func (export "effects") (param i32) (result i32) + (local i32) + (if + (block (result i32) (local.set 1 (i32.const 1)) (local.get 0)) + (then + (local.set 1 (i32.mul (local.get 1) (i32.const 3))) + (local.set 1 (i32.sub (local.get 1) (i32.const 5))) + (local.set 1 (i32.mul (local.get 1) (i32.const 7))) + (br 0) + (local.set 1 (i32.mul (local.get 1) (i32.const 100))) + ) + (else + (local.set 1 (i32.mul (local.get 1) (i32.const 5))) + (local.set 1 (i32.sub (local.get 1) (i32.const 7))) + (local.set 1 (i32.mul (local.get 1) (i32.const 3))) + (br 0) + (local.set 1 (i32.mul (local.get 1) (i32.const 1000))) + ) + ) + (local.get 1) + ) +) + +(assert_return (invoke "empty" (i32.const 0))) +(assert_return (invoke "empty" (i32.const 1))) +(assert_return (invoke "empty" (i32.const 100))) +(assert_return (invoke "empty" (i32.const -2))) + +(assert_return (invoke "singular" (i32.const 0)) (i32.const 8)) +(assert_return (invoke "singular" (i32.const 1)) (i32.const 7)) +(assert_return (invoke "singular" (i32.const 10)) (i32.const 7)) +(assert_return (invoke "singular" (i32.const -10)) (i32.const 7)) + +(assert_return (invoke "nested" (i32.const 0) (i32.const 0)) (i32.const 11)) +(assert_return (invoke "nested" (i32.const 1) (i32.const 0)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const 0) (i32.const 1)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const 3) (i32.const 2)) (i32.const 9)) +(assert_return (invoke "nested" (i32.const 0) (i32.const -100)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const 10) (i32.const 10)) (i32.const 9)) +(assert_return (invoke "nested" (i32.const 0) (i32.const -1)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const -111) (i32.const -2)) (i32.const 9)) + +(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-loop-first" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-loop-mid" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-loop-last" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-loop-last" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-if-condition" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-if-condition" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-br_if-first" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-br_if-first" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-br_if-last" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-br_if-last" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-call-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-call-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-return-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-br-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-br-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-local.set-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-unary-operand" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-unary-operand" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "as-unary-operand" (i32.const -1)) (i32.const 0)) + +(assert_return (invoke "as-binary-operand" (i32.const 0) (i32.const 0)) (i32.const 15)) +(assert_return (invoke "as-binary-operand" (i32.const 0) (i32.const 1)) (i32.const -12)) +(assert_return (invoke "as-binary-operand" (i32.const 1) (i32.const 0)) (i32.const -15)) +(assert_return (invoke "as-binary-operand" (i32.const 1) (i32.const 1)) (i32.const 12)) + +(assert_return (invoke "as-test-operand" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-test-operand" (i32.const 1)) (i32.const 0)) + +(assert_return (invoke "break-value" (i32.const 1)) (i32.const 18)) +(assert_return (invoke "break-value" (i32.const 0)) (i32.const 21)) + +(assert_return (invoke "effects" (i32.const 1)) (i32.const -14)) +(assert_return (invoke "effects" (i32.const 0)) (i32.const -6)) diff --git a/tests/misc_testsuite/winch/local_tee.wast b/tests/misc_testsuite/winch/local_tee.wast new file mode 100644 index 000000000000..240d9f481d99 --- /dev/null +++ b/tests/misc_testsuite/winch/local_tee.wast @@ -0,0 +1,134 @@ +;; Test `local.tee` operator + +(module + ;; Typing + + (func (export "type-local-i32") (result i32) (local i32) (local.tee 0 (i32.const 0))) + (func (export "type-local-i64") (result i64) (local i64) (local.tee 0 (i64.const 0))) + + (func (export "type-param-i32") (param i32) (result i32) (local.tee 0 (i32.const 10))) + (func (export "type-param-i64") (param i64) (result i64) (local.tee 0 (i64.const 11))) + + (func $dummy) + + (func (export "as-block-first") (param i32) (result i32) + (block (result i32) (local.tee 0 (i32.const 1)) (call $dummy)) + ) + (func (export "as-block-mid") (param i32) (result i32) + (block (result i32) (call $dummy) (local.tee 0 (i32.const 1)) (call $dummy)) + ) + (func (export "as-block-last") (param i32) (result i32) + (block (result i32) (call $dummy) (call $dummy) (local.tee 0 (i32.const 1))) + ) + + (func (export "as-loop-first") (param i32) (result i32) + (loop (result i32) (local.tee 0 (i32.const 3)) (call $dummy)) + ) + (func (export "as-loop-mid") (param i32) (result i32) + (loop (result i32) (call $dummy) (local.tee 0 (i32.const 4)) (call $dummy)) + ) + (func (export "as-loop-last") (param i32) (result i32) + (loop (result i32) (call $dummy) (call $dummy) (local.tee 0 (i32.const 5))) + ) + + (func (export "as-br-value") (param i32) (result i32) + (block (result i32) (br 0 (local.tee 0 (i32.const 9)))) + ) + + (func (export "as-br_if-cond") (param i32) + (block (br_if 0 (local.tee 0 (i32.const 1)))) + ) + + (func (export "as-return-value") (param i32) (result i32) + (return (local.tee 0 (i32.const 7))) + ) + + (func (export "as-if-cond") (param i32) (result i32) + (if (result i32) (local.tee 0 (i32.const 2)) + (then (i32.const 0)) (else (i32.const 1)) + ) + ) + (func (export "as-if-then") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (local.tee 0 (i32.const 3))) (else (local.get 0)) + ) + ) + (func (export "as-if-else") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (local.get 0)) (else (local.tee 0 (i32.const 4))) + ) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (param i32) (result i32) + (call $f (local.tee 0 (i32.const 12)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-call-mid") (param i32) (result i32) + (call $f (i32.const 1) (local.tee 0 (i32.const 13)) (i32.const 3)) + ) + (func (export "as-call-last") (param i32) (result i32) + (call $f (i32.const 1) (i32.const 2) (local.tee 0 (i32.const 14))) + ) + + (func (export "as-local.set-value") (local i32) + (local.set 0 (local.tee 0 (i32.const 1))) + ) + (func (export "as-local.tee-value") (param i32) (result i32) + (local.tee 0 (local.tee 0 (i32.const 1))) + ) + + (func (export "as-binary-left") (param i32) (result i32) + (i32.add (local.tee 0 (i32.const 3)) (i32.const 10)) + ) + (func (export "as-binary-right") (param i32) (result i32) + (i32.sub (i32.const 10) (local.tee 0 (i32.const 4))) + ) + + (func (export "as-test-operand") (param i32) (result i32) + (i32.eqz (local.tee 0 (i32.const 0))) + ) + + (func (export "as-compare-left") (param i32) (result i32) + (i32.le_s (local.tee 0 (i32.const 43)) (i32.const 10)) + ) + (func (export "as-compare-right") (param i32) (result i32) + (i32.ne (i32.const 10) (local.tee 0 (i32.const 42))) + ) +) + +(assert_return (invoke "type-local-i32") (i32.const 0)) +(assert_return (invoke "type-local-i64") (i64.const 0)) + +(assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 10)) +(assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 11)) + +(assert_return (invoke "as-block-first" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-block-mid" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-block-last" (i32.const 0)) (i32.const 1)) + +(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 4)) +(assert_return (invoke "as-loop-last" (i32.const 0)) (i32.const 5)) + +(assert_return (invoke "as-br-value" (i32.const 0)) (i32.const 9)) + +(assert_return (invoke "as-br_if-cond" (i32.const 0))) + +(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 7)) + +(assert_return (invoke "as-if-cond" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-if-then" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-if-else" (i32.const 0)) (i32.const 4)) + +(assert_return (invoke "as-call-first" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-call-mid" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-call-last" (i32.const 0)) (i32.const -1)) + +(assert_return (invoke "as-local.set-value")) +(assert_return (invoke "as-local.tee-value" (i32.const 0)) (i32.const 1)) + +(assert_return (invoke "as-binary-left" (i32.const 0)) (i32.const 13)) +(assert_return (invoke "as-binary-right" (i32.const 0)) (i32.const 6)) +(assert_return (invoke "as-test-operand" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-compare-left" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-compare-right" (i32.const 0)) (i32.const 1)) diff --git a/tests/misc_testsuite/winch/loop.wast b/tests/misc_testsuite/winch/loop.wast new file mode 100644 index 000000000000..961488ec02f1 --- /dev/null +++ b/tests/misc_testsuite/winch/loop.wast @@ -0,0 +1,200 @@ +;; Test `loop` opcode + +(module + (memory 1) + + (func $dummy) + + (func (export "empty") + (loop) + (loop $l) + ) + + (func (export "singular") (result i32) + (loop (nop)) + (loop (result i32) (i32.const 7)) + ) + + + (func (export "nested") (result i32) + (loop (result i32) + (loop (call $dummy) (block) (nop)) + (loop (result i32) (call $dummy) (i32.const 9)) + ) + ) + + (func (export "deep") (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (loop (result i32) (block (result i32) + (call $dummy) (i32.const 150) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + )) + ) + + (func (export "as-if-condition") + (loop (result i32) (i32.const 1)) (if (then (call $dummy))) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) (then (loop (result i32) (i32.const 1))) (else (i32.const 2))) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 1) (then (i32.const 2)) (else (loop (result i32) (i32.const 1)))) + ) + + (func (export "as-br_if-first") (result i32) + (block (result i32) (br_if 0 (loop (result i32) (i32.const 1)) (i32.const 2))) + ) + (func (export "as-br_if-last") (result i32) + (block (result i32) (br_if 0 (i32.const 2) (loop (result i32) (i32.const 1)))) + ) + + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "as-call-value") (result i32) + (call $f (loop (result i32) (i32.const 1))) + ) + (func (export "as-return-value") (result i32) + (loop (result i32) (i32.const 1)) (return) + ) + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (loop (result i32) (i32.const 1)))) + ) + (func (export "as-local.set-value") (result i32) + (local i32) (local.set 0 (loop (result i32) (i32.const 1))) (local.get 0) + ) + + (func (export "as-unary-operand") (result i32) + (i32.ctz (loop (result i32) (call $dummy) (i32.const 13))) + ) + (func (export "as-binary-operand") (result i32) + (i32.mul + (loop (result i32) (call $dummy) (i32.const 3)) + (loop (result i32) (call $dummy) (i32.const 4)) + ) + ) + (func (export "as-test-operand") (result i32) + (i32.eqz (loop (result i32) (call $dummy) (i32.const 13))) + ) + + (func (export "break-inner") (result i32) + (local i32) + (local.set 0 (i32.const 0)) + (local.set 0 (i32.add (local.get 0) (block (result i32) (loop (result i32) (block (result i32) (br 2 (i32.const 0x1))))))) + (local.set 0 (i32.add (local.get 0) (block (result i32) (loop (result i32) (loop (result i32) (br 2 (i32.const 0x2))))))) + (local.set 0 (i32.add (local.get 0) (block (result i32) (loop (result i32) (block (result i32) (loop (result i32) (br 1 (i32.const 0x4)))))))) + (local.set 0 (i32.add (local.get 0) (block (result i32) (loop (result i32) (i32.ctz (br 1 (i32.const 0x8))))))) + (local.set 0 (i32.add (local.get 0) (block (result i32) (loop (result i32) (i32.ctz (loop (result i32) (br 2 (i32.const 0x10)))))))) + (local.get 0) + ) + + (func $fx (export "effects") (result i32) + (local i32) + (block + (loop + (local.set 0 (i32.const 1)) + (local.set 0 (i32.mul (local.get 0) (i32.const 3))) + (local.set 0 (i32.sub (local.get 0) (i32.const 5))) + (local.set 0 (i32.mul (local.get 0) (i32.const 7))) + (br 1) + (local.set 0 (i32.mul (local.get 0) (i32.const 100))) + ) + ) + (i32.eq (local.get 0) (i32.const -14)) + ) + + (func (export "while") (param i64) (result i64) + (local i64) + (local.set 1 (i64.const 1)) + (block + (loop + (br_if 1 (i64.eqz (local.get 0))) + (local.set 1 (i64.mul (local.get 0) (local.get 1))) + (local.set 0 (i64.sub (local.get 0) (i64.const 1))) + (br 0) + ) + ) + (local.get 1) + ) + + (func (export "for") (param i64) (result i64) + (local i64 i64) + (local.set 1 (i64.const 1)) + (local.set 2 (i64.const 2)) + (block + (loop + (br_if 1 (i64.gt_u (local.get 2) (local.get 0))) + (local.set 1 (i64.mul (local.get 1) (local.get 2))) + (local.set 2 (i64.add (local.get 2) (i64.const 1))) + (br 0) + ) + ) + (local.get 1) + ) +) + +(assert_return (invoke "empty")) +(assert_return (invoke "singular") (i32.const 7)) +(assert_return (invoke "nested") (i32.const 9)) +(assert_return (invoke "deep") (i32.const 150)) +(assert_return (invoke "as-if-condition")) +(assert_return (invoke "as-if-then") (i32.const 1)) +(assert_return (invoke "as-if-else") (i32.const 2)) +(assert_return (invoke "as-br_if-first") (i32.const 1)) +(assert_return (invoke "as-br_if-last") (i32.const 2)) +(assert_return (invoke "as-call-value") (i32.const 1)) +(assert_return (invoke "as-return-value") (i32.const 1)) +(assert_return (invoke "as-br-value") (i32.const 1)) +(assert_return (invoke "as-local.set-value") (i32.const 1)) +(assert_return (invoke "as-unary-operand") (i32.const 0)) +(assert_return (invoke "as-binary-operand") (i32.const 12)) +(assert_return (invoke "as-test-operand") (i32.const 0)) +(assert_return (invoke "break-inner") (i32.const 0x1f)) +(assert_return (invoke "effects") (i32.const 1)) +(assert_return (invoke "while" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "while" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "while" (i64.const 2)) (i64.const 2)) +(assert_return (invoke "while" (i64.const 3)) (i64.const 6)) +(assert_return (invoke "while" (i64.const 5)) (i64.const 120)) +(assert_return (invoke "while" (i64.const 20)) (i64.const 2432902008176640000)) +(assert_return (invoke "for" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "for" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "for" (i64.const 2)) (i64.const 2)) +(assert_return (invoke "for" (i64.const 3)) (i64.const 6)) +(assert_return (invoke "for" (i64.const 5)) (i64.const 120)) +(assert_return (invoke "for" (i64.const 20)) (i64.const 2432902008176640000)) diff --git a/winch/codegen/Cargo.toml b/winch/codegen/Cargo.toml index 5a9b5e7fd717..e9aa457acbde 100644 --- a/winch/codegen/Cargo.toml +++ b/winch/codegen/Cargo.toml @@ -4,7 +4,7 @@ name = "winch-codegen" description = "Winch code generation library" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" -version = "0.9.0" +version = "0.10.0" edition.workspace = true [dependencies] diff --git a/winch/codegen/src/codegen/context.rs b/winch/codegen/src/codegen/context.rs index 311778f5130c..788f09fd4403 100644 --- a/winch/codegen/src/codegen/context.rs +++ b/winch/codegen/src/codegen/context.rs @@ -1,5 +1,6 @@ +use super::ControlStackFrame; use crate::{ - abi::ABIResult, + abi::{ABIResult, ABI}, frame::Frame, masm::{MacroAssembler, OperandSize, RegImm}, reg::Reg, @@ -246,16 +247,40 @@ impl<'a> CodeGenContext<'a> { self.stack.inner_mut().truncate(truncate); } - /// Reset value and stack pointer to the given length - /// and stack pointer offset respectively. - pub fn reset_stack( + /// Pops the stack pointer to ensure that it is correctly placed according to the expectations + /// of the destination branch. + /// + /// This function must be used when performing unconditional jumps, as the machine stack might + /// be left unbalanced at the jump site, due to register spills. In this context unbalanced + /// refers to possible extra space created at the jump site, which might cause invaid memory + /// accesses. Note that in some cases the stack pointer offset might be already less than or + /// equal to the original stack pointer offset registered when entering the destination control + /// stack frame, which effectively means that when reaching the jump site no extra space was + /// allocated similar to what would happen in a fall through in which we assume that the + /// program has allocated and deallocated the right amount of stack space. + /// + /// More generally speaking the current stack pointer will be less than the original stack + /// pointer offset in cases in which the top value in the value stack is a memory entry which + /// needs to be popped into the return location according to the ABI (a register for single + /// value returns and a memory slot for 1+ returns). In short, this could happen given that we + /// handle return values preemptively when emitting unconditional branches, and push them back + /// to the value stack at control flow joins. + pub fn pop_sp_for_branch( &mut self, + destination: &ControlStackFrame, masm: &mut M, - stack_len: usize, - sp_offset: u32, ) { - masm.reset_stack_pointer(sp_offset); - self.drop_last(self.stack.len() - stack_len); + let (_, original_sp_offset) = destination.original_stack_len_and_sp_offset(); + let current_sp_offset = masm.sp_offset(); + + assert!( + current_sp_offset >= original_sp_offset + || (current_sp_offset + ::word_bytes()) == original_sp_offset + ); + + if current_sp_offset > original_sp_offset { + masm.free_stack(current_sp_offset - original_sp_offset); + } } /// Convenience wrapper around [`Self::spill_callback`]. @@ -295,6 +320,21 @@ impl<'a> CodeGenContext<'a> { } } + /// Pops the value at the stack top and assigns it to the local at the given + /// index, returning the register holding the source value. + pub fn set_local(&mut self, masm: &mut M, index: u32) -> Reg { + let slot = self + .frame + .get_local(index) + .unwrap_or_else(|| panic!("valid local at slot = {}", index)); + let size: OperandSize = slot.ty.into(); + let src = self.pop_to_reg(masm, None, size); + let addr = masm.local_address(&slot); + masm.store(RegImm::reg(src), addr, size); + + src + } + /// Spill locals and registers to memory. // TODO optimize the spill range; // diff --git a/winch/codegen/src/codegen/control.rs b/winch/codegen/src/codegen/control.rs index 7dd0bff324e0..108a373bb4cd 100644 --- a/winch/codegen/src/codegen/control.rs +++ b/winch/codegen/src/codegen/control.rs @@ -44,6 +44,8 @@ pub(crate) enum ControlStackFrame { If { /// The if continuation label. cont: MachLabel, + /// The exit label of the block. + exit: MachLabel, /// The return values of the block. result: ABIResult, /// The size of the value stack at the beginning of the If. @@ -54,8 +56,8 @@ pub(crate) enum ControlStackFrame { reachable: bool, }, Else { - /// The else continuation label. - cont: MachLabel, + /// The exit label of the block. + exit: MachLabel, /// The return values of the block. result: ABIResult, /// The size of the value stack at the beginning of the Else. @@ -103,6 +105,7 @@ impl ControlStackFrame { let result = ::result(&returns, &CallingConvention::Default); let mut control = Self::If { cont: masm.get_label(), + exit: masm.get_label(), result, reachable: context.reachable, original_stack_len: 0, @@ -228,6 +231,7 @@ impl ControlStackFrame { If { result, original_stack_len, + exit, .. } => { assert!((*original_stack_len + result.len()) == context.stack.len()); @@ -236,10 +240,9 @@ impl ControlStackFrame { context.pop_abi_results(&result, masm); // Before binding the else branch, we emit the jump to the end // label. - let exit_label = masm.get_label(); - masm.jmp(exit_label); + masm.jmp(*exit); // Bind the else branch. - self.bind_else(masm, Some(exit_label), context.reachable); + self.bind_else(masm, context.reachable); } _ => unreachable!(), } @@ -247,12 +250,7 @@ impl ControlStackFrame { /// Binds the else branch label and converts `self` to /// [`ControlStackFrame::Else`]. - pub fn bind_else( - &mut self, - masm: &mut M, - exit: Option, - reachable: bool, - ) { + pub fn bind_else(&mut self, masm: &mut M, reachable: bool) { use ControlStackFrame::*; match self { If { @@ -260,20 +258,15 @@ impl ControlStackFrame { result, original_stack_len, original_sp_offset, + exit, .. } => { // Bind the else branch. masm.bind(*cont); - let label = if let Some(cont) = exit { - cont - } else { - masm.get_label() - }; - // Update the stack control frame with an else control frame. *self = ControlStackFrame::Else { - cont: label, + exit: *exit, original_stack_len: *original_stack_len, result: *result, reachable, @@ -332,6 +325,15 @@ impl ControlStackFrame { /// Binds the exit label of the control stack frame. pub fn bind_exit_label(&self, masm: &mut M) { + use ControlStackFrame::*; + match self { + // We use an explicit label to track the exit of an if block. In case there's no + // else, we bind the if's continuation block to make sure that any jumps from the if + // condition are reachable and we bind the explicit exit label as well to ensure that any + // branching instructions are able to correctly reach the block's end. + If { cont, .. } => masm.bind(*cont), + _ => {} + } if let Some(label) = self.exit_label() { masm.bind(*label); } @@ -342,8 +344,7 @@ impl ControlStackFrame { use ControlStackFrame::*; match self { - If { cont, .. } | Else { cont, .. } => cont, - Block { exit, .. } => exit, + If { exit, .. } | Else { exit, .. } | Block { exit, .. } => exit, Loop { head, .. } => head, } } @@ -355,8 +356,7 @@ impl ControlStackFrame { use ControlStackFrame::*; match self { - If { cont, .. } | Else { cont, .. } => Some(cont), - Block { exit, .. } => Some(exit), + If { exit, .. } | Else { exit, .. } | Block { exit, .. } => Some(exit), Loop { .. } => None, } } diff --git a/winch/codegen/src/codegen/env.rs b/winch/codegen/src/codegen/env.rs index 78ceee2b47ad..c3451630a354 100644 --- a/winch/codegen/src/codegen/env.rs +++ b/winch/codegen/src/codegen/env.rs @@ -1,7 +1,8 @@ use smallvec::{smallvec, SmallVec}; use wasmparser::BlockType; use wasmtime_environ::{ - FuncIndex, ModuleTranslation, PtrSize, TypeConvert, VMOffsets, WasmFuncType, WasmType, + FuncIndex, GlobalIndex, ModuleTranslation, PtrSize, TypeConvert, VMOffsets, WasmFuncType, + WasmType, }; /// The function environment. @@ -50,6 +51,17 @@ impl<'a, P: PtrSize> FuncEnv<'a, P> { _ => unimplemented!("multi-value"), } } + + /// Resolves the type and offset of a global at the given index. + pub fn resolve_global_type_and_offset(&self, index: GlobalIndex) -> (WasmType, u32) { + let ty = self.translation.module.globals[index].wasm_ty; + let offset = match self.translation.module.defined_global_index(index) { + Some(defined_index) => self.vmoffsets.vmctx_vmglobal_definition(defined_index), + None => self.vmoffsets.vmctx_vmglobal_import_from(index), + }; + + (ty, offset) + } } /// Metadata about a function callee. Use by the code generation diff --git a/winch/codegen/src/codegen/mod.rs b/winch/codegen/src/codegen/mod.rs index 10861a3438d2..a4f69dd9c750 100644 --- a/winch/codegen/src/codegen/mod.rs +++ b/winch/codegen/src/codegen/mod.rs @@ -111,9 +111,13 @@ where // entry, the if-else branch will be reachable. self.context.reachable = true; // Reset the stack to the original length and offset. - self.context - .reset_stack(self.masm, *original_stack_len, *original_sp_offset); - frame.bind_else(self.masm, None, self.context.reachable); + Self::reset_stack( + &mut self.context, + self.masm, + *original_stack_len, + *original_sp_offset, + ); + frame.bind_else(self.masm, self.context.reachable); } } _ => unreachable!(), @@ -129,8 +133,7 @@ where let (value_stack_len, sp_offset) = frame.original_stack_len_and_sp_offset(); // Reset the stack to the original length and offset. - self.context - .reset_stack(self.masm, value_stack_len, sp_offset); + Self::reset_stack(&mut self.context, self.masm, value_stack_len, sp_offset); // If the current frame is the outermost frame, which corresponds to the // current function's body, only bind the exit label as we don't need to // push any more values to the value stack, else perform the entire `bind_end` @@ -143,6 +146,14 @@ where } } + /// Helper function to reset value and stack pointer to the given length and stack pointer + /// offset respectively. This function is only used when restoring the code generation's + /// reachabiliy state when handling an unreachable `end` or `else`. + fn reset_stack(context: &mut CodeGenContext, masm: &mut M, stack_len: usize, sp_offset: u32) { + masm.reset_stack_pointer(sp_offset); + context.drop_last(context.stack.len() - stack_len); + } + fn emit_body( &mut self, body: &mut BinaryReader<'a>, diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs index d5d7e6caace7..27bf2028f19b 100644 --- a/winch/codegen/src/visitor.rs +++ b/winch/codegen/src/visitor.rs @@ -4,12 +4,13 @@ //! which validates and dispatches to the corresponding //! machine code emitter. +use crate::abi::ABI; use crate::codegen::CodeGen; use crate::codegen::ControlStackFrame; use crate::masm::{CmpKind, DivKind, MacroAssembler, OperandSize, RegImm, RemKind, ShiftKind}; use crate::stack::Val; use wasmparser::{BlockType, VisitOperator}; -use wasmtime_environ::{FuncIndex, WasmType}; +use wasmtime_environ::{FuncIndex, GlobalIndex, WasmType}; /// A macro to define unsupported WebAssembly operators. /// @@ -105,6 +106,9 @@ macro_rules! def_unsupported { (emit BrIf $($rest:tt)*) => {}; (emit Return $($rest:tt)*) => {}; (emit Unreachable $($rest:tt)*) => {}; + (emit LocalTee $($rest:tt)*) => {}; + (emit GlobalGet $($rest:tt)*) => {}; + (emit GlobalSet $($rest:tt)*) => {}; (emit $unsupported:tt $($rest:tt)*) => {$($rest)*}; } @@ -493,15 +497,7 @@ where // TODO verify the case where the target local is on the stack. fn visit_local_set(&mut self, index: u32) { - let context = &mut self.context; - let frame = context.frame; - let slot = frame - .get_local(index) - .expect(&format!("vald local at slot = {}", index)); - let size: OperandSize = slot.ty.into(); - let src = self.context.pop_to_reg(self.masm, None, size); - let addr = self.masm.local_address(&slot); - self.masm.store(RegImm::reg(src), addr, size); + let src = self.context.set_local(self.masm, index); self.context.regalloc.free_gpr(src); } @@ -550,6 +546,7 @@ where fn visit_br(&mut self, depth: u32) { let frame = Self::control_at(&mut self.control_frames, depth); self.context.pop_abi_results(frame.result(), self.masm); + self.context.pop_sp_for_branch(&frame, self.masm); self.masm.jmp(*frame.label()); frame.set_as_target(); self.context.reachable = false; @@ -580,6 +577,8 @@ where // know that it should exist at index 0. let outermost = &mut self.control_frames[0]; self.context.pop_abi_results(outermost.result(), self.masm); + // Ensure that the stack pointer is correctly balanced. + self.context.pop_sp_for_branch(&outermost, self.masm); // The outermost should always be a block and therefore, // should always have an exit label. self.masm.jmp(*outermost.exit_label().unwrap()); @@ -598,6 +597,33 @@ where outermost.set_as_target(); } + fn visit_local_tee(&mut self, index: u32) { + let src = self.context.set_local(self.masm, index); + self.context.stack.push(Val::reg(src)); + } + + fn visit_global_get(&mut self, global_index: u32) { + let index = GlobalIndex::from_u32(global_index); + let (ty, offset) = self.env.resolve_global_type_and_offset(index); + let addr = self + .masm + .address_at_reg(::vmctx_reg(), offset); + let dst = self.context.any_gpr(self.masm); + self.masm.load(addr, dst, ty.into()); + self.context.stack.push(Val::reg(dst)); + } + + fn visit_global_set(&mut self, global_index: u32) { + let index = GlobalIndex::from_u32(global_index); + let (ty, offset) = self.env.resolve_global_type_and_offset(index); + let addr = self + .masm + .address_at_reg(::vmctx_reg(), offset); + let reg = self.context.pop_to_reg(self.masm, None, ty.into()); + self.context.free_gpr(reg); + self.masm.store(reg.into(), addr, ty.into()); + } + wasmparser::for_each_operator!(def_unsupported); } diff --git a/winch/filetests/filetests/x64/if/as_br_if_last.wat b/winch/filetests/filetests/x64/if/as_br_if_last.wat new file mode 100644 index 000000000000..d78bb01888c1 --- /dev/null +++ b/winch/filetests/filetests/x64/if/as_br_if_last.wat @@ -0,0 +1,48 @@ +;;! target = "x86_64" +(module + (func $dummy) + (func (export "as-br_if-last") (param i32) (result i32) + (block (result i32) + (br_if 0 + (i32.const 2) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + ) + (return (i32.const 3)) + ) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec08 sub rsp, 8 +;; 8: 4c893424 mov qword ptr [rsp], r14 +;; c: 4883c408 add rsp, 8 +;; 10: 5d pop rbp +;; 11: c3 ret +;; +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 897c240c mov dword ptr [rsp + 0xc], edi +;; c: 4c89742404 mov qword ptr [rsp + 4], r14 +;; 11: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 15: 85c0 test eax, eax +;; 17: 0f8411000000 je 0x2e +;; 1d: e800000000 call 0x22 +;; 22: 48c7c001000000 mov rax, 1 +;; 29: e90c000000 jmp 0x3a +;; 2e: e800000000 call 0x33 +;; 33: 48c7c000000000 mov rax, 0 +;; 3a: 50 push rax +;; 3b: 59 pop rcx +;; 3c: 48c7c002000000 mov rax, 2 +;; 43: 85c9 test ecx, ecx +;; 45: 0f850c000000 jne 0x57 +;; 4b: 50 push rax +;; 4c: 48c7c003000000 mov rax, 3 +;; 53: 4883c408 add rsp, 8 +;; 57: 4883c410 add rsp, 0x10 +;; 5b: 5d pop rbp +;; 5c: c3 ret diff --git a/winch/filetests/filetests/x64/if/break_value.wat b/winch/filetests/filetests/x64/if/break_value.wat new file mode 100644 index 000000000000..4c2adc533755 --- /dev/null +++ b/winch/filetests/filetests/x64/if/break_value.wat @@ -0,0 +1,24 @@ +;;! target = "x86_64" + +(module + (func (export "break-value") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (br 0 (i32.const 18)) (i32.const 19)) + (else (br 0 (i32.const 21)) (i32.const 20)) + ) + ) +) +;; 0: 55 push rbp +;; 1: 4889e5 mov rbp, rsp +;; 4: 4883ec10 sub rsp, 0x10 +;; 8: 897c240c mov dword ptr [rsp + 0xc], edi +;; c: 4c89742404 mov qword ptr [rsp + 4], r14 +;; 11: 8b44240c mov eax, dword ptr [rsp + 0xc] +;; 15: 85c0 test eax, eax +;; 17: 0f840c000000 je 0x29 +;; 1d: 48c7c012000000 mov rax, 0x12 +;; 24: e907000000 jmp 0x30 +;; 29: 48c7c015000000 mov rax, 0x15 +;; 30: 4883c410 add rsp, 0x10 +;; 34: 5d pop rbp +;; 35: c3 ret