diff --git a/.github/actions/install-rust/action.yml b/.github/actions/install-rust/action.yml index c5f40462ac58..e0ebe61c4f23 100644 --- a/.github/actions/install-rust/action.yml +++ b/.github/actions/install-rust/action.yml @@ -6,6 +6,18 @@ inputs: description: 'Default toolchan to install' required: false default: 'default' + msrv_range: + description: 'Versions later-than-latest-Rust the MSRV supports' + required: false + # Note that this is currently set to 3 as the MSRV is 1.78 and current + # stable is 1.81. Currently MSRV cannot be updated as it would break the + # build on OSS-Fuzz which hasn't updated its Rust compiler in quite some time. + # + # Updating OSS-Fuzz is being done in + # https://github.com/google/oss-fuzz/pull/12365 but it's taking some time, + # so for now this'll get bumped instead of MSRV while we wait for the update + # to happen. + default: '3' runs: using: composite @@ -17,13 +29,14 @@ runs: # Determine MSRV as N in `1.N.0` by looking at the `rust-version` # located in the root `Cargo.toml`. msrv=$(grep 'rust-version.*1' Cargo.toml | sed 's/.*\.\([0-9]*\)\..*/\1/') + range=${{ inputs.msrv_range }} if [ "${{ inputs.toolchain }}" = "default" ]; then - echo "version=1.$((msrv+2)).0" >> "$GITHUB_OUTPUT" + echo "version=1.$((msrv+range)).0" >> "$GITHUB_OUTPUT" elif [ "${{ inputs.toolchain }}" = "msrv" ]; then echo "version=1.$msrv.0" >> "$GITHUB_OUTPUT" elif [ "${{ inputs.toolchain }}" = "wasmtime-ci-pinned-nightly" ]; then - echo "version=nightly-2024-08-12" >> "$GITHUB_OUTPUT" + echo "version=nightly-2024-09-05" >> "$GITHUB_OUTPUT" else echo "version=${{ inputs.toolchain }}" >> "$GITHUB_OUTPUT" fi diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3a60ceb3c74f..52c87ee3bebd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -339,7 +339,6 @@ jobs: # here isn't to run tests, mostly just serve as a double-check that Rust code # compiles and is likely to work everywhere else. micro_checks: - needs: determine name: Check ${{matrix.name}} strategy: fail-fast: true @@ -420,12 +419,9 @@ jobs: env: GH_TOKEN: ${{ github.token }} - # Similar to `micro_checks` but where we need to install some more state - # (e.g. Android NDK) and we haven't factored support for those things out into - # a parallel jobs yet. - monolith_checks: - needs: determine - name: Monolith Checks + # Checks for no_std support, ensure that crates can build on a no_std target + no_std_checks: + name: no_std checks runs-on: ubuntu-latest env: CARGO_NDK_VERSION: 2.12.2 @@ -435,14 +431,53 @@ jobs: submodules: true - uses: ./.github/actions/install-rust - # Checks for no_std support, ensure that crates can build on a no_std - # target # NOTE(dhil): Currently, we only support x86_64 Linux. # - run: rustup target add x86_64-unknown-none # - run: cargo check --target x86_64-unknown-none -p wasmtime --no-default-features --features runtime,gc,component-model # - run: cargo check --target x86_64-unknown-none -p cranelift-control --no-default-features # - run: cargo check --target x86_64-unknown-none -p pulley-interpreter --features encode,decode,disas,interp + # common logic to cancel the entire run if this job fails + - run: gh run cancel ${{ github.run_id }} + if: failure() && github.event_name != 'pull_request' + env: + GH_TOKEN: ${{ github.token }} + + # Check that Clippy lints are passing. + clippy: + name: Clippy + runs-on: ubuntu-latest + env: + CARGO_NDK_VERSION: 2.12.2 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/actions/install-rust + + - run: rustup component add clippy + - run: cargo clippy --workspace --all-targets + + # common logic to cancel the entire run if this job fails + - run: gh run cancel ${{ github.run_id }} + if: failure() && github.event_name != 'pull_request' + env: + GH_TOKEN: ${{ github.token }} + + # Similar to `micro_checks` but where we need to install some more state + # (e.g. Android NDK) and we haven't factored support for those things out into + # a parallel jobs yet. + monolith_checks: + name: Monolith Checks + runs-on: ubuntu-latest + env: + CARGO_NDK_VERSION: 2.12.2 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: ./.github/actions/install-rust + # Check that wasmtime compiles with panic=abort since there's some `#[cfg]` # for specifically panic=abort there. - run: cargo check -p wasmtime @@ -469,10 +504,6 @@ jobs: - run: rustup target add x86_64-unknown-freebsd - run: cargo check -p wasmtime --no-default-features --features cranelift,wat,async,cache --target x86_64-unknown-freebsd - # Run clippy configuration - - run: rustup component add clippy - - run: cargo clippy --workspace --all-targets - # Re-vendor all WIT files and ensure that they're all up-to-date by ensuring # that there's no git changes. - name: Re-vendor WIT @@ -698,6 +729,11 @@ jobs: echo "::warning::This CI run will not test MPK; it has been detected as not available on this machine (\`cargo run --example mpk-available\`)." fi + # Install VTune, see `cli_tests::profile_with_vtune`. + - name: Install VTune + if: matrix.filter == 'linux-x64' && contains(matrix.bucket, 'wasmtime-cli') + uses: abrown/install-vtune-action@v1 + # Build and test all features - run: ./ci/run-tests.sh --locked ${{ matrix.bucket }} env: @@ -1161,6 +1197,8 @@ jobs: - cargo_vet - doc - micro_checks + - no_std_checks + - clippy - monolith_checks - checks_winarm64 - bench diff --git a/.github/workflows/release-process.yml b/.github/workflows/release-process.yml index 97f9417ab1fa..c8436ff2f8b5 100644 --- a/.github/workflows/release-process.yml +++ b/.github/workflows/release-process.yml @@ -32,6 +32,9 @@ on: required: false default: 'cut' +permissions: + contents: write + jobs: release_process: if: "github.repository == 'bytecodealliance/wasmtime' || !github.event.schedule" diff --git a/Cargo.lock b/Cargo.lock index 5f35e2e5eb3d..661230858d50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -222,7 +222,7 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byte-array-literals" -version = "25.0.0" +version = "26.0.0" [[package]] name = "byteorder" @@ -563,7 +563,7 @@ dependencies = [ [[package]] name = "cranelift" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-codegen", "cranelift-frontend", @@ -576,14 +576,14 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.112.0" +version = "0.113.0" dependencies = [ "arbitrary", "serde", @@ -592,7 +592,7 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.112.0" +version = "0.113.0" dependencies = [ "anyhow", "bumpalo", @@ -624,25 +624,25 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.112.0" +version = "0.113.0" [[package]] name = "cranelift-control" -version = "0.112.0" +version = "0.113.0" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-bitset", "serde", @@ -681,7 +681,7 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-codegen", "env_logger", @@ -706,7 +706,7 @@ dependencies = [ [[package]] name = "cranelift-interpreter" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -720,7 +720,7 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.112.0" +version = "0.113.0" dependencies = [ "codespan-reporting", "log", @@ -729,7 +729,7 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.112.0" +version = "0.113.0" dependencies = [ "anyhow", "cranelift", @@ -750,7 +750,7 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.112.0" +version = "0.113.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-codegen", "libc", @@ -771,7 +771,7 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.112.0" +version = "0.113.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "cranelift-reader" -version = "0.112.0" +version = "0.113.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -796,7 +796,7 @@ dependencies = [ [[package]] name = "cranelift-serde" -version = "0.112.0" +version = "0.113.0" dependencies = [ "clap", "cranelift-codegen", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.112.0" +version = "0.113.0" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -852,7 +852,7 @@ dependencies = [ "serde_derive", "smallvec", "target-lexicon", - "wasmparser 0.216.0", + "wasmparser", "wasmtime-types", "wat", ] @@ -1055,7 +1055,7 @@ checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" [[package]] name = "embedding" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "dlmalloc", @@ -1387,15 +1387,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.14.3" @@ -1874,7 +1865,7 @@ dependencies = [ [[package]] name = "min-platform-host" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "libloading", @@ -2161,7 +2152,7 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "0.1.0" +version = "0.2.0" dependencies = [ "arbitrary", "cranelift-bitset", @@ -2292,11 +2283,11 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" dependencies = [ - "hashbrown 0.13.2", + "hashbrown 0.14.3", "log", "rustc-hash", "serde", @@ -2382,9 +2373,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustix" @@ -2830,7 +2821,7 @@ dependencies = [ "cargo_metadata", "heck 0.4.0", "wasmtime", - "wit-component 0.216.0", + "wit-component", ] [[package]] @@ -3155,10 +3146,10 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "verify-component-adapter" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", - "wasmparser 0.216.0", + "wasmparser", "wat", ] @@ -3205,7 +3196,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-common" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "bitflags 2.4.1", @@ -3245,13 +3236,13 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter" -version = "25.0.0" +version = "26.0.0" dependencies = [ "bitflags 2.4.1", "byte-array-literals", "object", "wasi", - "wasm-encoder 0.216.0", + "wasm-encoder", "wit-bindgen-rust-macro", ] @@ -3311,26 +3302,17 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" -version = "0.215.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.215.0#9872d3f31aec1182705341d4a95fbde2ab0389d9" -dependencies = [ - "leb128", - "wasmparser 0.215.0", -] - -[[package]] -name = "wasm-encoder" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "leb128", - "wasmparser 0.216.0", + "wasmparser", ] [[package]] name = "wasm-metadata" -version = "0.215.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.215.0#9872d3f31aec1182705341d4a95fbde2ab0389d9" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "anyhow", "indexmap 2.2.6", @@ -3338,49 +3320,34 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.215.0", - "wasmparser 0.215.0", -] - -[[package]] -name = "wasm-metadata" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" -dependencies = [ - "anyhow", - "indexmap 2.2.6", - "serde", - "serde_derive", - "serde_json", - "spdx", - "wasm-encoder 0.216.0", - "wasmparser 0.216.0", + "wasm-encoder", + "wasmparser", ] [[package]] name = "wasm-mutate" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "egg", "log", "rand", "thiserror", - "wasm-encoder 0.216.0", - "wasmparser 0.216.0", + "wasm-encoder", + "wasmparser", ] [[package]] name = "wasm-smith" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "anyhow", "arbitrary", "flagset", "indexmap 2.2.6", "leb128", - "wasm-encoder 0.216.0", + "wasm-encoder", ] [[package]] @@ -3425,20 +3392,8 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.215.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.215.0#9872d3f31aec1182705341d4a95fbde2ab0389d9" -dependencies = [ - "ahash", - "bitflags 2.4.1", - "hashbrown 0.14.3", - "indexmap 2.2.6", - "semver", -] - -[[package]] -name = "wasmparser" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "ahash", "bitflags 2.4.1", @@ -3459,17 +3414,17 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "anyhow", "termcolor", - "wasmparser 0.216.0", + "wasmparser", ] [[package]] name = "wasmtime" -version = "25.0.0" +version = "26.0.0" dependencies = [ "addr2line", "anyhow", @@ -3496,6 +3451,7 @@ dependencies = [ "postcard", "proptest", "psm", + "pulley-interpreter", "rand", "rayon", "rustix 0.38.31", @@ -3508,8 +3464,8 @@ dependencies = [ "target-lexicon", "tempfile", "wasi-common", - "wasm-encoder 0.216.0", - "wasmparser 0.216.0", + "wasm-encoder", + "wasmparser", "wasmtime-asm-macros", "wasmtime-cache", "wasmtime-component-macro", @@ -3530,14 +3486,14 @@ dependencies = [ [[package]] name = "wasmtime-asm-macros" -version = "25.0.0" +version = "26.0.0" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-bench-api" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "cap-std", @@ -3553,14 +3509,14 @@ dependencies = [ [[package]] name = "wasmtime-c-api" -version = "25.0.0" +version = "26.0.0" dependencies = [ "wasmtime-c-api-impl", ] [[package]] name = "wasmtime-c-api-impl" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "cap-std", @@ -3578,7 +3534,7 @@ dependencies = [ [[package]] name = "wasmtime-c-api-macros" -version = "25.0.0" +version = "26.0.0" dependencies = [ "proc-macro2", "quote", @@ -3586,7 +3542,7 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "base64 0.21.0", @@ -3608,7 +3564,7 @@ dependencies = [ [[package]] name = "wasmtime-cli" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "async-trait", @@ -3638,6 +3594,7 @@ dependencies = [ "num_cpus", "object", "once_cell", + "pulley-interpreter", "rayon", "rustix 0.38.31", "serde", @@ -3652,7 +3609,7 @@ dependencies = [ "tracing", "walkdir", "wasi-common", - "wasmparser 0.216.0", + "wasmparser", "wasmtime", "wasmtime-cache", "wasmtime-cli-flags", @@ -3669,15 +3626,15 @@ dependencies = [ "wasmtime-wasi-runtime-config", "wasmtime-wasi-threads", "wasmtime-wast", - "wast 216.0.0", + "wast 217.0.0", "wat", "windows-sys 0.52.0", - "wit-component 0.216.0", + "wit-component", ] [[package]] name = "wasmtime-cli-flags" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "clap", @@ -3690,7 +3647,7 @@ dependencies = [ [[package]] name = "wasmtime-component-macro" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "component-macro-test-helpers", @@ -3705,23 +3662,23 @@ dependencies = [ "wasmtime", "wasmtime-component-util", "wasmtime-wit-bindgen", - "wit-parser 0.216.0", + "wit-parser", ] [[package]] name = "wasmtime-component-util" -version = "25.0.0" +version = "26.0.0" [[package]] name = "wasmtime-continuations" -version = "25.0.0" +version = "26.0.0" dependencies = [ "memoffset", ] [[package]] name = "wasmtime-cranelift" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "cfg-if", @@ -3737,7 +3694,7 @@ dependencies = [ "smallvec", "target-lexicon", "thiserror", - "wasmparser 0.216.0", + "wasmparser", "wasmtime-continuations", "wasmtime-environ", "wasmtime-versioned-export-macros", @@ -3745,7 +3702,7 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "clap", @@ -3763,8 +3720,8 @@ dependencies = [ "serde", "serde_derive", "target-lexicon", - "wasm-encoder 0.216.0", - "wasmparser 0.216.0", + "wasm-encoder", + "wasmparser", "wasmprinter", "wasmtime-component-util", "wasmtime-continuations", @@ -3780,7 +3737,7 @@ dependencies = [ "component-fuzz-util", "env_logger", "libfuzzer-sys", - "wasmparser 0.216.0", + "wasmparser", "wasmprinter", "wasmtime-environ", "wat", @@ -3788,7 +3745,7 @@ dependencies = [ [[package]] name = "wasmtime-explorer" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "capstone", @@ -3803,7 +3760,7 @@ dependencies = [ [[package]] name = "wasmtime-fiber" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "backtrace", @@ -3840,7 +3797,7 @@ dependencies = [ "rand", "smallvec", "target-lexicon", - "wasmparser 0.216.0", + "wasmparser", "wasmtime", "wasmtime-fuzzing", ] @@ -3861,12 +3818,12 @@ dependencies = [ "target-lexicon", "tempfile", "v8", - "wasm-encoder 0.216.0", + "wasm-encoder", "wasm-mutate", "wasm-smith", "wasm-spec-interpreter", "wasmi", - "wasmparser 0.216.0", + "wasmparser", "wasmprinter", "wasmtime", "wasmtime-wast", @@ -3875,7 +3832,7 @@ dependencies = [ [[package]] name = "wasmtime-jit-debug" -version = "25.0.0" +version = "26.0.0" dependencies = [ "object", "once_cell", @@ -3885,7 +3842,7 @@ dependencies = [ [[package]] name = "wasmtime-jit-icache-coherence" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "cfg-if", @@ -3895,7 +3852,7 @@ dependencies = [ [[package]] name = "wasmtime-slab" -version = "25.0.0" +version = "26.0.0" [[package]] name = "wasmtime-test-macros" @@ -3909,19 +3866,19 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "cranelift-entity", "serde", "serde_derive", "smallvec", - "wasmparser 0.216.0", + "wasmparser", ] [[package]] name = "wasmtime-versioned-export-macros" -version = "25.0.0" +version = "26.0.0" dependencies = [ "proc-macro2", "quote", @@ -3930,7 +3887,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "async-trait", @@ -3963,7 +3920,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-http" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "async-trait", @@ -3989,7 +3946,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-keyvalue" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "test-programs-artifacts", @@ -4000,7 +3957,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-nn" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "cap-std", @@ -4020,7 +3977,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-runtime-config" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "test-programs-artifacts", @@ -4031,7 +3988,7 @@ dependencies = [ [[package]] name = "wasmtime-wasi-threads" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "log", @@ -4043,24 +4000,24 @@ dependencies = [ [[package]] name = "wasmtime-wast" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "log", "wasmtime", - "wast 216.0.0", + "wast 217.0.0", ] [[package]] name = "wasmtime-winch" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "cranelift-codegen", "gimli", "object", "target-lexicon", - "wasmparser 0.216.0", + "wasmparser", "wasmtime-cranelift", "wasmtime-environ", "winch-codegen", @@ -4068,17 +4025,17 @@ dependencies = [ [[package]] name = "wasmtime-wit-bindgen" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "heck 0.4.0", "indexmap 2.2.6", - "wit-parser 0.216.0", + "wit-parser", ] [[package]] name = "wasmtime-wmemcheck" -version = "25.0.0" +version = "26.0.0" [[package]] name = "wast" @@ -4091,22 +4048,22 @@ dependencies = [ [[package]] name = "wast" -version = "216.0.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "217.0.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.216.0", + "wasm-encoder", ] [[package]] name = "wat" -version = "1.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "1.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ - "wast 216.0.0", + "wast 217.0.0", ] [[package]] @@ -4143,7 +4100,7 @@ dependencies = [ [[package]] name = "wiggle" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "async-trait", @@ -4160,7 +4117,7 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "25.0.0" +version = "26.0.0" dependencies = [ "anyhow", "heck 0.4.0", @@ -4173,7 +4130,7 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "25.0.0" +version = "26.0.0" dependencies = [ "proc-macro2", "quote", @@ -4228,7 +4185,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "0.23.0" +version = "0.24.0" dependencies = [ "anyhow", "cranelift-codegen", @@ -4236,7 +4193,7 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "wasmparser 0.216.0", + "wasmparser", "wasmtime-cranelift", "wasmtime-environ", ] @@ -4437,8 +4394,8 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.30.0" -source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.30.0#3f4883f42fd179145e47741539145d0198a88e68" +version = "0.32.0" +source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.32.0#5e266c01ab8c19fa0dd13fe741c0dff4d7c1aa24" dependencies = [ "wit-bindgen-rt", "wit-bindgen-rust-macro", @@ -4446,41 +4403,41 @@ dependencies = [ [[package]] name = "wit-bindgen-core" -version = "0.30.0" -source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.30.0#3f4883f42fd179145e47741539145d0198a88e68" +version = "0.32.0" +source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.32.0#5e266c01ab8c19fa0dd13fe741c0dff4d7c1aa24" dependencies = [ "anyhow", "heck 0.5.0", - "wit-parser 0.215.0", + "wit-parser", ] [[package]] name = "wit-bindgen-rt" -version = "0.30.0" -source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.30.0#3f4883f42fd179145e47741539145d0198a88e68" +version = "0.32.0" +source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.32.0#5e266c01ab8c19fa0dd13fe741c0dff4d7c1aa24" dependencies = [ "bitflags 2.4.1", ] [[package]] name = "wit-bindgen-rust" -version = "0.30.0" -source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.30.0#3f4883f42fd179145e47741539145d0198a88e68" +version = "0.32.0" +source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.32.0#5e266c01ab8c19fa0dd13fe741c0dff4d7c1aa24" dependencies = [ "anyhow", "heck 0.5.0", "indexmap 2.2.6", "prettyplease", "syn 2.0.60", - "wasm-metadata 0.215.0", + "wasm-metadata", "wit-bindgen-core", - "wit-component 0.215.0", + "wit-component", ] [[package]] name = "wit-bindgen-rust-macro" -version = "0.30.0" -source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.30.0#3f4883f42fd179145e47741539145d0198a88e68" +version = "0.32.0" +source = "git+https://github.com/wasmfx/wit-bindgenfx?tag=v0.32.0#5e266c01ab8c19fa0dd13fe741c0dff4d7c1aa24" dependencies = [ "anyhow", "prettyplease", @@ -4493,26 +4450,8 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.215.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.215.0#9872d3f31aec1182705341d4a95fbde2ab0389d9" -dependencies = [ - "anyhow", - "bitflags 2.4.1", - "indexmap 2.2.6", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder 0.215.0", - "wasm-metadata 0.215.0", - "wasmparser 0.215.0", - "wit-parser 0.215.0", -] - -[[package]] -name = "wit-component" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "anyhow", "bitflags 2.4.1", @@ -4521,33 +4460,16 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.216.0", - "wasm-metadata 0.216.0", - "wasmparser 0.216.0", - "wit-parser 0.216.0", -] - -[[package]] -name = "wit-parser" -version = "0.215.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.215.0#9872d3f31aec1182705341d4a95fbde2ab0389d9" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.2.6", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser 0.215.0", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", ] [[package]] name = "wit-parser" -version = "0.216.0" -source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.216.0#851cc632add67326b74a7c486fb535dd49a6c933" +version = "0.217.0" +source = "git+https://github.com/wasmfx/wasmfx-tools?tag=v1.217.0#8508865d216d089414d9a483546438ea37fc1e85" dependencies = [ "anyhow", "id-arena", @@ -4558,7 +4480,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.216.0", + "wasmparser", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f495286d1550..d120871ba076 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,7 +86,7 @@ rustix = { workspace = true, features = ["mm", "param", "process"] } [dev-dependencies] # depend again on wasmtime to activate its default features for tests -wasmtime = { workspace = true, features = ['default', 'winch', 'all-arch', 'call-hook', 'memory-protection-keys'] } +wasmtime = { workspace = true, features = ['default', 'winch', 'pulley', 'all-arch', 'call-hook', 'memory-protection-keys'] } env_logger = { workspace = true } log = { workspace = true } filecheck = { workspace = true } @@ -121,6 +121,7 @@ libtest-mimic = { workspace = true } capstone = { workspace = true } object = { workspace = true, features = ['std'] } wasmtime-test-macros = { path = "crates/test-macros" } +pulley-interpreter = { workspace = true, features = ["disas"] } [target.'cfg(windows)'.dev-dependencies] windows-sys = { workspace = true, features = ["Win32_System_Memory"] } @@ -158,7 +159,7 @@ exclude = [ ] [workspace.package] -version = "25.0.0" +version = "26.0.0" authors = ["The Wasmtime Project Developers"] edition = "2021" # Wasmtime's current policy is that this number can be no larger than the @@ -186,70 +187,70 @@ manual_strip = 'warn' [workspace.dependencies] arbitrary = { version = "1.3.1" } -wasmtime-wmemcheck = { path = "crates/wmemcheck", version = "=25.0.0" } -wasmtime = { path = "crates/wasmtime", version = "25.0.0", default-features = false } -wasmtime-c-api-macros = { path = "crates/c-api-macros", version = "=25.0.0" } -wasmtime-cache = { path = "crates/cache", version = "=25.0.0" } -wasmtime-cli-flags = { path = "crates/cli-flags", version = "=25.0.0" } -wasmtime-cranelift = { path = "crates/cranelift", version = "=25.0.0" } -wasmtime-continuations = { path = "crates/continuations", version = "=25.0.0" } -wasmtime-winch = { path = "crates/winch", version = "=25.0.0" } -wasmtime-environ = { path = "crates/environ", version = "=25.0.0" } -wasmtime-explorer = { path = "crates/explorer", version = "=25.0.0" } -wasmtime-fiber = { path = "crates/fiber", version = "=25.0.0" } -wasmtime-types = { path = "crates/types", version = "25.0.0" } -wasmtime-jit-debug = { path = "crates/jit-debug", version = "=25.0.0" } -wasmtime-wast = { path = "crates/wast", version = "=25.0.0" } -wasmtime-wasi = { path = "crates/wasi", version = "25.0.0", default-features = false } -wasmtime-wasi-http = { path = "crates/wasi-http", version = "=25.0.0", default-features = false } -wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "25.0.0" } -wasmtime-wasi-runtime-config = { path = "crates/wasi-runtime-config", version = "25.0.0" } -wasmtime-wasi-keyvalue = { path = "crates/wasi-keyvalue", version = "25.0.0" } -wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "25.0.0" } -wasmtime-component-util = { path = "crates/component-util", version = "=25.0.0" } -wasmtime-component-macro = { path = "crates/component-macro", version = "=25.0.0" } -wasmtime-asm-macros = { path = "crates/asm-macros", version = "=25.0.0" } -wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=25.0.0" } -wasmtime-slab = { path = "crates/slab", version = "=25.0.0" } +wasmtime-wmemcheck = { path = "crates/wmemcheck", version = "=26.0.0" } +wasmtime = { path = "crates/wasmtime", version = "26.0.0", default-features = false } +wasmtime-c-api-macros = { path = "crates/c-api-macros", version = "=26.0.0" } +wasmtime-cache = { path = "crates/cache", version = "=26.0.0" } +wasmtime-cli-flags = { path = "crates/cli-flags", version = "=26.0.0" } +wasmtime-cranelift = { path = "crates/cranelift", version = "=26.0.0" } +wasmtime-continuations = { path = "crates/continuations", version = "=26.0.0" } +wasmtime-winch = { path = "crates/winch", version = "=26.0.0" } +wasmtime-environ = { path = "crates/environ", version = "=26.0.0" } +wasmtime-explorer = { path = "crates/explorer", version = "=26.0.0" } +wasmtime-fiber = { path = "crates/fiber", version = "=26.0.0" } +wasmtime-types = { path = "crates/types", version = "26.0.0" } +wasmtime-jit-debug = { path = "crates/jit-debug", version = "=26.0.0" } +wasmtime-wast = { path = "crates/wast", version = "=26.0.0" } +wasmtime-wasi = { path = "crates/wasi", version = "26.0.0", default-features = false } +wasmtime-wasi-http = { path = "crates/wasi-http", version = "=26.0.0", default-features = false } +wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "26.0.0" } +wasmtime-wasi-runtime-config = { path = "crates/wasi-runtime-config", version = "26.0.0" } +wasmtime-wasi-keyvalue = { path = "crates/wasi-keyvalue", version = "26.0.0" } +wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "26.0.0" } +wasmtime-component-util = { path = "crates/component-util", version = "=26.0.0" } +wasmtime-component-macro = { path = "crates/component-macro", version = "=26.0.0" } +wasmtime-asm-macros = { path = "crates/asm-macros", version = "=26.0.0" } +wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=26.0.0" } +wasmtime-slab = { path = "crates/slab", version = "=26.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 = "=25.0.0", default-features = false } -wiggle-macro = { path = "crates/wiggle/macro", version = "=25.0.0" } -wiggle-generate = { path = "crates/wiggle/generate", version = "=25.0.0" } -wasi-common = { path = "crates/wasi-common", version = "=25.0.0", default-features = false } +wiggle = { path = "crates/wiggle", version = "=26.0.0", default-features = false } +wiggle-macro = { path = "crates/wiggle/macro", version = "=26.0.0" } +wiggle-generate = { path = "crates/wiggle/generate", version = "=26.0.0" } +wasi-common = { path = "crates/wasi-common", version = "=26.0.0", default-features = false } wasmtime-fuzzing = { path = "crates/fuzzing" } -wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=25.0.0" } -wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=25.0.0" } +wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=26.0.0" } +wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=26.0.0" } test-programs-artifacts = { path = 'crates/test-programs/artifacts' } -pulley-interpreter = { path = 'pulley', version = "=0.1.0" } +pulley-interpreter = { path = 'pulley', version = "=0.2.0" } pulley-interpreter-fuzz = { path = 'pulley/fuzz' } -cranelift-wasm = { path = "cranelift/wasm", version = "0.112.0" } -cranelift-codegen = { path = "cranelift/codegen", version = "0.112.0", default-features = false, features = ["std", "unwind"] } -cranelift-frontend = { path = "cranelift/frontend", version = "0.112.0" } -cranelift-entity = { path = "cranelift/entity", version = "0.112.0" } -cranelift-native = { path = "cranelift/native", version = "0.112.0" } -cranelift-module = { path = "cranelift/module", version = "0.112.0" } -cranelift-interpreter = { path = "cranelift/interpreter", version = "0.112.0" } -cranelift-reader = { path = "cranelift/reader", version = "0.112.0" } +cranelift-wasm = { path = "cranelift/wasm", version = "0.113.0" } +cranelift-codegen = { path = "cranelift/codegen", version = "0.113.0", default-features = false, features = ["std", "unwind"] } +cranelift-frontend = { path = "cranelift/frontend", version = "0.113.0" } +cranelift-entity = { path = "cranelift/entity", version = "0.113.0" } +cranelift-native = { path = "cranelift/native", version = "0.113.0" } +cranelift-module = { path = "cranelift/module", version = "0.113.0" } +cranelift-interpreter = { path = "cranelift/interpreter", version = "0.113.0" } +cranelift-reader = { path = "cranelift/reader", version = "0.113.0" } cranelift-filetests = { path = "cranelift/filetests" } -cranelift-object = { path = "cranelift/object", version = "0.112.0" } -cranelift-jit = { path = "cranelift/jit", version = "0.112.0" } +cranelift-object = { path = "cranelift/object", version = "0.113.0" } +cranelift-jit = { path = "cranelift/jit", version = "0.113.0" } cranelift-fuzzgen = { path = "cranelift/fuzzgen" } -cranelift-bforest = { path = "cranelift/bforest", version = "0.112.0" } -cranelift-bitset = { path = "cranelift/bitset", version = "0.112.0" } -cranelift-control = { path = "cranelift/control", version = "0.112.0" } -cranelift = { path = "cranelift/umbrella", version = "0.112.0" } +cranelift-bforest = { path = "cranelift/bforest", version = "0.113.0" } +cranelift-bitset = { path = "cranelift/bitset", version = "0.113.0" } +cranelift-control = { path = "cranelift/control", version = "0.113.0" } +cranelift = { path = "cranelift/umbrella", version = "0.113.0" } -winch-codegen = { path = "winch/codegen", version = "=0.23.0" } +winch-codegen = { path = "winch/codegen", version = "=0.24.0" } wasi-preview1-component-adapter = { path = "crates/wasi-preview1-component-adapter" } byte-array-literals = { path = "crates/wasi-preview1-component-adapter/byte-array-literals" } # Bytecode Alliance maintained dependencies: # --------------------------- -regalloc2 = "0.9.3" +regalloc2 = "0.10.2" # cap-std family: target-lexicon = "0.12.16" @@ -265,19 +266,19 @@ io-lifetimes = { version = "2.0.3", default-features = false } io-extras = "0.18.1" rustix = "0.38.31" # wit-bindgen: -wit-bindgen = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.30.0", default-features = false } -wit-bindgen-rust-macro = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.30.0", default-features = false } +wit-bindgen = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.32.0", default-features = false } +wit-bindgen-rust-macro = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.32.0", default-features = false } # wasm-tools family: -wasmparser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0", default-features = false } -wat = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } -wast = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } -wasmprinter = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } -wasm-encoder = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } -wasm-smith = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } -wasm-mutate = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } -wit-parser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } -wit-component = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.216.0" } +wasmparser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0", default-features = false } +wat = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } +wast = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } +wasmprinter = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } +wasm-encoder = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } +wasm-smith = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } +wasm-mutate = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } +wit-parser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } +wit-component = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.217.0" } # Non-Bytecode Alliance maintained dependencies: # -------------------------- @@ -335,7 +336,7 @@ url = "2.3.1" humantime = "2.0.0" postcard = { version = "1.0.8", default-features = false, features = ['alloc'] } criterion = { version = "0.5.0", default-features = false, features = ["html_reports", "rayon"] } -rustc-hash = "1.1.0" +rustc-hash = "2.0.0" libtest-mimic = "0.7.0" semver = { version = "1.0.17", default-features = false } @@ -400,6 +401,7 @@ default = [ # These features are off-by-default but may optionally be enabled. all-arch = ["wasmtime/all-arch"] winch = ["wasmtime/winch"] +pulley = ["wasmtime/pulley"] wmemcheck = ["wasmtime/wmemcheck"] memory-protection-keys = ["wasmtime-cli-flags/memory-protection-keys"] diff --git a/RELEASES.md b/RELEASES.md index b8b5e96fe415..0e87cd88ee1f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,4 +1,4 @@ -## 25.0.0 +## 26.0.0 Unreleased. @@ -12,6 +12,7 @@ Release notes for previous releases of Wasmtime can be found on the respective release branches of the Wasmtime repository. +* [25.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-25.0.0/RELEASES.md) * [24.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-24.0.0/RELEASES.md) * [23.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-23.0.0/RELEASES.md) * [22.0.x](https://github.com/bytecodealliance/wasmtime/blob/release-22.0.0/RELEASES.md) diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 74cff6db2e09..cb1dda5c0bc4 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -54,3 +54,4 @@ default = ["disas", "cranelift-codegen/all-arch", "cranelift-codegen/trace-log", disas = ["capstone"] souper-harvest = ["cranelift-codegen/souper-harvest", "rayon"] all-arch = ["cranelift-codegen/all-arch"] +all-native-arch = ["cranelift-codegen/all-native-arch"] diff --git a/cranelift/bforest/Cargo.toml b/cranelift/bforest/Cargo.toml index 41192317b9a2..17f7c6575914 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.112.0" +version = "0.113.0" description = "A forest of B+-trees" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-bforest" diff --git a/cranelift/bitset/Cargo.toml b/cranelift/bitset/Cargo.toml index 2e6d2dd06112..b72fda390380 100644 --- a/cranelift/bitset/Cargo.toml +++ b/cranelift/bitset/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["The Cranelift Project Developers"] name = "cranelift-bitset" -version = "0.112.0" +version = "0.113.0" description = "Various bitset stuff for use inside Cranelift" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-bitset" diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index 1126c2233631..e7ccb588243c 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.112.0" +version = "0.113.0" description = "Low-level code generator library" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://docs.rs/cranelift-codegen" @@ -20,7 +20,7 @@ workspace = true anyhow = { workspace = true, optional = true, features = ['std'] } bumpalo = "3" capstone = { workspace = true, optional = true } -cranelift-codegen-shared = { path = "./shared", version = "0.112.0" } +cranelift-codegen-shared = { path = "./shared", version = "0.113.0" } cranelift-entity = { workspace = true } cranelift-bforest = { workspace = true } cranelift-bitset = { workspace = true } @@ -49,8 +49,8 @@ similar = "2.1.0" env_logger = { workspace = true } [build-dependencies] -cranelift-codegen-meta = { path = "meta", version = "0.112.0" } -cranelift-isle = { path = "../isle/isle", version = "=0.112.0" } +cranelift-codegen-meta = { path = "meta", version = "0.113.0" } +cranelift-isle = { path = "../isle/isle", version = "=0.113.0" } [features] default = ["std", "unwind", "host-arch", "timing"] @@ -88,11 +88,17 @@ host-arch = [] # Option to enable all architectures. all-arch = [ + "all-native-arch", + "pulley", +] + +# Option to enable all architectures that correspond to an actual native target +# (that is, exclude Pulley). +all-native-arch = [ "x86", "arm64", "s390x", "riscv64", - "pulley", ] # For dependent crates that want to serialize some parts of cranelift diff --git a/cranelift/codegen/build.rs b/cranelift/codegen/build.rs index 4bfc8ca237e0..50f067e1cfd7 100644 --- a/cranelift/codegen/build.rs +++ b/cranelift/codegen/build.rs @@ -31,6 +31,7 @@ fn main() { let target_triple = env::var("TARGET").expect("The TARGET environment variable must be set"); let all_arch = env::var("CARGO_FEATURE_ALL_ARCH").is_ok(); + let all_native_arch = env::var("CARGO_FEATURE_ALL_NATIVE_ARCH").is_ok(); let mut isas = meta::isa::Isa::all() .iter() @@ -47,7 +48,7 @@ fn main() { .collect::>(); // Don't require host isa if under 'all-arch' feature. - let host_isa = env::var("CARGO_FEATURE_HOST_ARCH").is_ok() && !all_arch; + let host_isa = env::var("CARGO_FEATURE_HOST_ARCH").is_ok() && !all_native_arch; if isas.is_empty() || host_isa { // Try to match native target. diff --git a/cranelift/codegen/meta/Cargo.toml b/cranelift/codegen/meta/Cargo.toml index f6f039c08286..047f35e6cb87 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.112.0" +version = "0.113.0" description = "Metaprogram for cranelift-codegen code generator library" license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" @@ -16,4 +16,4 @@ workspace = true rustdoc-args = [ "--document-private-items" ] [dependencies] -cranelift-codegen-shared = { path = "../shared", version = "0.112.0" } +cranelift-codegen-shared = { path = "../shared", version = "0.113.0" } diff --git a/cranelift/codegen/meta/src/gen_inst.rs b/cranelift/codegen/meta/src/gen_inst.rs index 7609d060d671..e9a505933219 100644 --- a/cranelift/codegen/meta/src/gen_inst.rs +++ b/cranelift/codegen/meta/src/gen_inst.rs @@ -119,7 +119,7 @@ fn gen_arguments_method(formats: &[Rc], fmt: &mut Formatter, fmtln!( fmt, - "pub fn {}<'a>(&'a {}self, pool: &'a {}ir::ValueListPool) -> &{}[Value] {{", + "pub fn {}<'a>(&'a {}self, pool: &'a {}ir::ValueListPool) -> &'a {}[Value] {{", method, mut_, mut_, diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index bff8fe3bc46c..8030bed91e37 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -2034,18 +2034,12 @@ pub(crate) fn define( ig.push( Inst::new( - "iadd_cin", + "sadd_overflow_cin", r#" - Add integers with carry in. + Add signed integers with carry in and overflow out. - Same as `iadd` with an additional carry input. Computes: - - ```text - a = x + y + c_{in} \pmod 2^B - ``` - - Polymorphic over all scalar integer types, but does not support vector - types. + Same as `sadd_overflow` with an additional carry input. The `c_in` type + is interpreted as 1 if it's nonzero or 0 if it's zero. "#, &formats.ternary, ) @@ -2054,24 +2048,20 @@ pub(crate) fn define( Operand::new("y", iB), Operand::new("c_in", i8).with_doc("Input carry flag"), ]) - .operands_out(vec![Operand::new("a", iB)]), + .operands_out(vec![ + Operand::new("a", iB), + Operand::new("c_out", i8).with_doc("Output carry flag"), + ]), ); ig.push( Inst::new( - "iadd_carry", + "uadd_overflow_cin", r#" - Add integers with carry in and out. - - Same as `iadd` with an additional carry input and output. - - ```text - a &= x + y + c_{in} \pmod 2^B \\ - c_{out} &= x + y + c_{in} >= 2^B - ``` + Add unsigned integers with carry in and overflow out. - Polymorphic over all scalar integer types, but does not support vector - types. + Same as `uadd_overflow` with an additional carry input. The `c_in` type + is interpreted as 1 if it's nonzero or 0 if it's zero. "#, &formats.ternary, ) @@ -2233,18 +2223,13 @@ pub(crate) fn define( ig.push( Inst::new( - "isub_bin", + "ssub_overflow_bin", r#" - Subtract integers with borrow in. + Subtract signed integers with borrow in and overflow out. - Same as `isub` with an additional borrow flag input. Computes: - - ```text - a = x - (y + b_{in}) \pmod 2^B - ``` - - Polymorphic over all scalar integer types, but does not support vector - types. + Same as `ssub_overflow` with an additional borrow input. The `b_in` type + is interpreted as 1 if it's nonzero or 0 if it's zero. The computation + performed here is `x - (y + (b_in != 0))`. "#, &formats.ternary, ) @@ -2253,24 +2238,21 @@ pub(crate) fn define( Operand::new("y", iB), Operand::new("b_in", i8).with_doc("Input borrow flag"), ]) - .operands_out(vec![Operand::new("a", iB)]), + .operands_out(vec![ + Operand::new("a", iB), + Operand::new("b_out", i8).with_doc("Output borrow flag"), + ]), ); ig.push( Inst::new( - "isub_borrow", + "usub_overflow_bin", r#" - Subtract integers with borrow in and out. - - Same as `isub` with an additional borrow flag input and output. - - ```text - a &= x - (y + b_{in}) \pmod 2^B \\ - b_{out} &= x < y + b_{in} - ``` + Subtract unsigned integers with borrow in and overflow out. - Polymorphic over all scalar integer types, but does not support vector - types. + Same as `usub_overflow` with an additional borrow input. The `b_in` type + is interpreted as 1 if it's nonzero or 0 if it's zero. The computation + performed here is `x - (y + (b_in != 0))`. "#, &formats.ternary, ) diff --git a/cranelift/codegen/shared/Cargo.toml b/cranelift/codegen/shared/Cargo.toml index 7628ba46abb1..62f563d46ec5 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.112.0" +version = "0.113.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/ir/dfg.rs b/cranelift/codegen/src/ir/dfg.rs index c26c3d591e21..48c2dc2f2974 100644 --- a/cranelift/codegen/src/ir/dfg.rs +++ b/cranelift/codegen/src/ir/dfg.rs @@ -330,7 +330,7 @@ impl DataFlowGraph { } /// Get an iterator over all values. - pub fn values<'a>(&'a self) -> Values { + pub fn values<'a>(&'a self) -> Values<'a> { Values { inner: self.values.iter(), } diff --git a/cranelift/codegen/src/ir/instructions.rs b/cranelift/codegen/src/ir/instructions.rs index ab97327e4c69..f885083cc1bb 100644 --- a/cranelift/codegen/src/ir/instructions.rs +++ b/cranelift/codegen/src/ir/instructions.rs @@ -305,7 +305,7 @@ impl InstructionData { /// Get the destinations of this instruction, if it's a branch. /// /// `br_table` returns the empty slice. - pub fn branch_destination<'a>(&'a self, jump_tables: &'a ir::JumpTables) -> &[BlockCall] { + pub fn branch_destination<'a>(&'a self, jump_tables: &'a ir::JumpTables) -> &'a [BlockCall] { match self { Self::Jump { ref destination, .. @@ -325,7 +325,7 @@ impl InstructionData { pub fn branch_destination_mut<'a>( &'a mut self, jump_tables: &'a mut ir::JumpTables, - ) -> &mut [BlockCall] { + ) -> &'a mut [BlockCall] { match self { Self::Jump { ref mut destination, diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs index 59a493ea2b41..55aaeca33f52 100644 --- a/cranelift/codegen/src/isa/aarch64/abi.rs +++ b/cranelift/codegen/src/isa/aarch64/abi.rs @@ -8,6 +8,7 @@ use crate::ir::{dynamic_to_fixed, ExternalName, LibCall, Signature}; use crate::isa; use crate::isa::aarch64::{inst::*, settings as aarch64_settings}; use crate::isa::unwind::UnwindInst; +use crate::isa::winch; use crate::machinst::*; use crate::settings; use crate::{CodegenError, CodegenResult}; @@ -109,6 +110,7 @@ impl ABIMachineSpec for AArch64MachineDeps { mut args: ArgsAccumulator, ) -> CodegenResult<(u32, Option)> { let is_apple_cc = call_conv.extends_apple_aarch64(); + let is_winch_return = call_conv == isa::CallConv::Winch && args_or_rets == ArgsOrRets::Rets; // See AArch64 ABI (https://github.com/ARM-software/abi-aa/blob/2021Q1/aapcs64/aapcs64.rst#64parameter-passing), sections 6.4. // @@ -141,20 +143,15 @@ impl ABIMachineSpec for AArch64MachineDeps { let mut next_vreg = 0; let mut next_stack: u32 = 0; - let (max_per_class_reg_vals, mut remaining_reg_vals) = match args_or_rets { - ArgsOrRets::Args => (8, 16), // x0-x7 and v0-v7 + // Note on return values: on the regular ABI, we may return values + // in 8 registers for V128 and I64 registers independently of the + // number of register values returned in the other class. That is, + // we can return values in up to 8 integer and + // 8 vector registers at once. + let max_per_class_reg_vals = 8; // x0-x7 and v0-v7 + let mut remaining_reg_vals = 16; - // Note on return values: on the regular ABI, we may return values - // in 8 registers for V128 and I64 registers independently of the - // number of register values returned in the other class. That is, - // we can return values in up to 8 integer and - // 8 vector registers at once. - ArgsOrRets::Rets => { - (8, 16) // x0-x7 and v0-v7 - } - }; - - for param in params { + for (i, param) in params.into_iter().enumerate() { if is_apple_cc && param.value_type == types::F128 && !flags.enable_llvm_abi_extensions() { panic!( @@ -284,7 +281,15 @@ impl ABIMachineSpec for AArch64MachineDeps { RegClass::Vector => unreachable!(), }; - if *next_reg < max_per_class_reg_vals && remaining_reg_vals > 0 { + let push_to_reg = if is_winch_return { + // Winch uses the first registry to return the last result + i == params.len() - 1 + } else { + // Use max_per_class_reg_vals & remaining_reg_vals otherwise + *next_reg < max_per_class_reg_vals && remaining_reg_vals > 0 + }; + + if push_to_reg { let reg = match rc { RegClass::Int => xreg(*next_reg), RegClass::Float => vreg(*next_reg), @@ -313,8 +318,8 @@ impl ABIMachineSpec for AArch64MachineDeps { // Compute the stack slot's size. let size = (ty_bits(param.value_type) / 8) as u32; - let size = if is_apple_cc { - // MacOS aarch64 allows stack slots with + let size = if is_apple_cc || is_winch_return { + // MacOS and Winch aarch64 allows stack slots with // sizes less than 8 bytes. They still need to be // properly aligned on their natural data alignment, // though. @@ -325,9 +330,11 @@ impl ABIMachineSpec for AArch64MachineDeps { std::cmp::max(size, 8) }; - // Align the stack slot. - debug_assert!(size.is_power_of_two()); - next_stack = align_to(next_stack, size); + if !is_winch_return { + // Align the stack slot. + debug_assert!(size.is_power_of_two()); + next_stack = align_to(next_stack, size); + } let slots = reg_types .iter() @@ -386,6 +393,10 @@ impl ABIMachineSpec for AArch64MachineDeps { None }; + if is_winch_return { + winch::reverse_stack(args, next_stack, false); + } + next_stack = align_to(next_stack, 16); // To avoid overflow issues, limit the arg/return size to something @@ -1014,58 +1025,26 @@ impl ABIMachineSpec for AArch64MachineDeps { insts } - fn gen_call( - dest: &CallDest, - uses: CallArgList, - defs: CallRetList, - clobbers: PRegSet, - tmp: Writable, - callee_conv: isa::CallConv, - caller_conv: isa::CallConv, - callee_pop_size: u32, - ) -> SmallVec<[Inst; 2]> { + fn gen_call(dest: &CallDest, tmp: Writable, info: CallInfo<()>) -> SmallVec<[Inst; 2]> { let mut insts = SmallVec::new(); match &dest { - &CallDest::ExtName(ref name, RelocDistance::Near) => insts.push(Inst::Call { - info: Box::new(CallInfo { - dest: name.clone(), - uses, - defs, - clobbers, - caller_callconv: caller_conv, - callee_callconv: callee_conv, - callee_pop_size, - }), - }), + &CallDest::ExtName(ref name, RelocDistance::Near) => { + let info = Box::new(info.map(|()| name.clone())); + insts.push(Inst::Call { info }); + } &CallDest::ExtName(ref name, RelocDistance::Far) => { insts.push(Inst::LoadExtName { rd: tmp, name: Box::new(name.clone()), offset: 0, }); - insts.push(Inst::CallInd { - info: Box::new(CallIndInfo { - rn: tmp.to_reg(), - uses, - defs, - clobbers, - caller_callconv: caller_conv, - callee_callconv: callee_conv, - callee_pop_size, - }), - }); + let info = Box::new(info.map(|()| tmp.to_reg())); + insts.push(Inst::CallInd { info }); + } + &CallDest::Reg(reg) => { + let info = Box::new(info.map(|()| *reg)); + insts.push(Inst::CallInd { info }); } - &CallDest::Reg(reg) => insts.push(Inst::CallInd { - info: Box::new(CallIndInfo { - rn: *reg, - uses, - defs, - clobbers, - caller_callconv: caller_conv, - callee_callconv: callee_conv, - callee_pop_size, - }), - }), } insts @@ -1103,8 +1082,8 @@ impl ABIMachineSpec for AArch64MachineDeps { ], defs: smallvec![], clobbers: Self::get_regs_clobbered_by_call(call_conv), - caller_callconv: call_conv, - callee_callconv: call_conv, + caller_conv: call_conv, + callee_conv: call_conv, callee_pop_size: 0, }), }); @@ -1295,16 +1274,17 @@ impl AArch64CallSite { let dest = self.dest().clone(); let uses = self.take_uses(); - let info = Box::new(ReturnCallInfo { - uses, - new_stack_arg_size, - key: select_api_key(isa_flags, isa::CallConv::Tail, true), - }); + let key = select_api_key(isa_flags, isa::CallConv::Tail, true); match dest { CallDest::ExtName(callee, RelocDistance::Near) => { - let callee = Box::new(callee); - ctx.emit(Inst::ReturnCall { callee, info }); + let info = Box::new(ReturnCallInfo { + dest: callee, + uses, + key, + new_stack_arg_size, + }); + ctx.emit(Inst::ReturnCall { info }); } CallDest::ExtName(name, RelocDistance::Far) => { let callee = ctx.alloc_tmp(types::I64).only_reg().unwrap(); @@ -1313,12 +1293,23 @@ impl AArch64CallSite { name: Box::new(name), offset: 0, }); - ctx.emit(Inst::ReturnCallInd { - callee: callee.to_reg(), - info, + let info = Box::new(ReturnCallInfo { + dest: callee.to_reg(), + uses, + key, + new_stack_arg_size, + }); + ctx.emit(Inst::ReturnCallInd { info }); + } + CallDest::Reg(callee) => { + let info = Box::new(ReturnCallInfo { + dest: callee, + uses, + key, + new_stack_arg_size, }); + ctx.emit(Inst::ReturnCallInd { info }); } - CallDest::Reg(callee) => ctx.emit(Inst::ReturnCallInd { callee, info }), } } } diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index e55586a95f78..c19710376a3f 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -806,22 +806,16 @@ ;; of type `Reloc::Arm64Call`); if the destination distance is not `RelocDistance::Near`, the ;; code should use a `LoadExtName` / `CallInd` sequence instead, allowing an arbitrary 64-bit ;; target. - (Call - (info BoxCallInfo)) + (Call (info BoxCallInfo)) ;; A machine indirect-call instruction. - (CallInd - (info BoxCallIndInfo)) + (CallInd (info BoxCallIndInfo)) ;; A return-call macro instruction. - (ReturnCall - (callee BoxExternalName) - (info BoxReturnCallInfo)) + (ReturnCall (info BoxReturnCallInfo)) ;; An indirect return-call macro instruction. - (ReturnCallInd - (callee Reg) - (info BoxReturnCallInfo)) + (ReturnCallInd (info BoxReturnCallIndInfo)) ;; A pseudo-instruction that captures register arguments in vregs. (Args @@ -1073,6 +1067,7 @@ (type BoxCallInfo (primitive BoxCallInfo)) (type BoxCallIndInfo (primitive BoxCallIndInfo)) (type BoxReturnCallInfo (primitive BoxReturnCallInfo)) +(type BoxReturnCallIndInfo (primitive BoxReturnCallIndInfo)) (type CondBrKind (primitive CondBrKind)) (type BranchTarget (primitive BranchTarget)) (type BoxJTSequenceInfo (primitive BoxJTSequenceInfo)) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 8f76dd56a9f4..f96f22100bb0 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -2943,8 +2943,9 @@ impl MachInstEmit for Inst { } &Inst::CallInd { ref info } => { let user_stack_map = state.take_stack_map(); - let rn = info.rn; - sink.put4(0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(rn) << 5)); + sink.put4( + 0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(info.dest) << 5), + ); if let Some(s) = user_stack_map { let offset = sink.cur_offset(); sink.push_user_stack_map(state, offset, s); @@ -2959,16 +2960,13 @@ impl MachInstEmit for Inst { } } } - &Inst::ReturnCall { - ref callee, - ref info, - } => { + &Inst::ReturnCall { ref info } => { emit_return_call_common_sequence(sink, emit_info, state, info); // Note: this is not `Inst::Jump { .. }.emit(..)` because we // have different metadata in this case: we don't have a label // for the target, but rather a function relocation. - sink.add_reloc(Reloc::Arm64Call, &**callee, 0); + sink.add_reloc(Reloc::Arm64Call, &info.dest, 0); sink.put4(enc_jump26(0b000101, 0)); sink.add_call_site(); @@ -2977,11 +2975,11 @@ impl MachInstEmit for Inst { // in this case. start_off = sink.cur_offset(); } - &Inst::ReturnCallInd { callee, ref info } => { + &Inst::ReturnCallInd { ref info } => { emit_return_call_common_sequence(sink, emit_info, state, info); Inst::IndirectBr { - rn: callee, + rn: info.dest, targets: vec![], } .emit(sink, emit_info, state); @@ -3372,15 +3370,7 @@ impl MachInstEmit for Inst { // blr tmp sink.add_reloc(Reloc::Aarch64TlsDescCall, &**symbol, 0); Inst::CallInd { - info: crate::isa::Box::new(CallIndInfo { - rn: tmp.to_reg(), - uses: smallvec![], - defs: smallvec![], - clobbers: PRegSet::empty(), - caller_callconv: CallConv::SystemV, - callee_callconv: CallConv::SystemV, - callee_pop_size: 0, - }), + info: crate::isa::Box::new(CallInfo::empty(tmp.to_reg(), CallConv::SystemV)), } .emit(sink, emit_info, state); @@ -3432,15 +3422,10 @@ impl MachInstEmit for Inst { // call function pointer in temp register Inst::CallInd { - info: crate::isa::Box::new(CallIndInfo { - rn: rtmp.to_reg(), - uses: smallvec![], - defs: smallvec![], - clobbers: PRegSet::empty(), - caller_callconv: CallConv::AppleAarch64, - callee_callconv: CallConv::AppleAarch64, - callee_pop_size: 0, - }), + info: crate::isa::Box::new(CallInfo::empty( + rtmp.to_reg(), + CallConv::AppleAarch64, + )), } .emit(sink, emit_info, state); } @@ -3533,11 +3518,11 @@ impl MachInstEmit for Inst { } } -fn emit_return_call_common_sequence( +fn emit_return_call_common_sequence( sink: &mut MachBuffer, emit_info: &EmitInfo, state: &mut EmitState, - info: &ReturnCallInfo, + info: &ReturnCallInfo, ) { for inst in AArch64MachineDeps::gen_clobber_restore(CallConv::Tail, &emit_info.0, state.frame_layout()) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs index 0b50795ec39a..5cc26eab0c3c 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs @@ -1,5 +1,5 @@ use crate::ir::types::*; -use crate::ir::TrapCode; +use crate::ir::{ExternalName, TrapCode}; use crate::isa::aarch64::inst::*; use alloc::boxed::Box; @@ -6056,15 +6056,10 @@ fn test_aarch64_binemit() { insns.push(( Inst::Call { - info: Box::new(CallInfo { - dest: ExternalName::testcase("test0"), - uses: smallvec![], - defs: smallvec![], - clobbers: PRegSet::empty(), - caller_callconv: CallConv::SystemV, - callee_callconv: CallConv::SystemV, - callee_pop_size: 0, - }), + info: Box::new(CallInfo::empty( + ExternalName::testcase("test0"), + CallConv::SystemV, + )), }, "00000094", "bl 0", @@ -6072,15 +6067,7 @@ fn test_aarch64_binemit() { insns.push(( Inst::CallInd { - info: Box::new(CallIndInfo { - rn: xreg(10), - uses: smallvec![], - defs: smallvec![], - clobbers: PRegSet::empty(), - caller_callconv: CallConv::SystemV, - callee_callconv: CallConv::SystemV, - callee_pop_size: 0, - }), + info: Box::new(CallInfo::empty(xreg(10), CallConv::SystemV)), }, "40013FD6", "blr x10", diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index eff651e57694..8287eb6b0c35 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -2,7 +2,7 @@ use crate::binemit::{Addend, CodeOffset, Reloc}; use crate::ir::types::{F128, F16, F32, F64, I128, I16, I32, I64, I8, I8X16}; -use crate::ir::{types, ExternalName, MemFlags, Type}; +use crate::ir::{types, MemFlags, Type}; use crate::isa::{CallConv, FunctionAlignment}; use crate::machinst::*; use crate::{settings, CodegenError, CodegenResult}; @@ -10,7 +10,6 @@ use crate::{settings, CodegenError, CodegenResult}; use crate::machinst::{PrettyPrint, Reg, RegClass, Writable}; use alloc::vec::Vec; -use regalloc2::PRegSet; use smallvec::{smallvec, SmallVec}; use std::fmt::Write; use std::string::{String, ToString}; @@ -74,54 +73,12 @@ impl BitOp { } } -/// Additional information for (direct) Call instructions, left out of line to lower the size of -/// the Inst enum. -#[derive(Clone, Debug)] -pub struct CallInfo { - /// Call destination. - pub dest: ExternalName, - /// Arguments to the call instruction. - pub uses: CallArgList, - /// Return values from the call instruction. - pub defs: CallRetList, - /// Clobbers register set. - pub clobbers: PRegSet, - /// Caller calling convention. - pub caller_callconv: CallConv, - /// Callee calling convention. - pub callee_callconv: CallConv, - /// The number of bytes that the callee will pop from the stack for the - /// caller, if any. (Used for popping stack arguments with the `tail` - /// calling convention.) - pub callee_pop_size: u32, -} - -/// Additional information for CallInd instructions, left out of line to lower the size of the Inst -/// enum. -#[derive(Clone, Debug)] -pub struct CallIndInfo { - /// Function pointer for indirect call. - pub rn: Reg, - /// Arguments to the call instruction. - pub uses: SmallVec<[CallArgPair; 8]>, - /// Return values from the call instruction. - pub defs: SmallVec<[CallRetPair; 8]>, - /// Clobbers register set. - pub clobbers: PRegSet, - /// Caller calling convention. - pub caller_callconv: CallConv, - /// Callee calling convention. - pub callee_callconv: CallConv, - /// The number of bytes that the callee will pop from the stack for the - /// caller, if any. (Used for popping stack arguments with the `tail` - /// calling convention.) - pub callee_pop_size: u32, -} - /// Additional information for `return_call[_ind]` instructions, left out of /// line to lower the size of the `Inst` enum. #[derive(Clone, Debug)] -pub struct ReturnCallInfo { +pub struct ReturnCallInfo { + /// Where this call is going to + pub dest: T, /// Arguments to the call instruction. pub uses: CallArgList, /// The size of the new stack frame's stack arguments. This is necessary @@ -895,8 +852,10 @@ fn aarch64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_clobbers(info.clobbers); } Inst::CallInd { info, .. } => { - let CallIndInfo { rn, uses, defs, .. } = &mut **info; - collector.reg_use(rn); + let CallInfo { + dest, uses, defs, .. + } = &mut **info; + collector.reg_use(dest); for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); } @@ -905,17 +864,17 @@ fn aarch64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { } collector.reg_clobbers(info.clobbers); } - Inst::ReturnCall { info, callee: _ } => { + Inst::ReturnCall { info } => { for CallArgPair { vreg, preg } in &mut info.uses { collector.reg_fixed_use(vreg, *preg); } } - Inst::ReturnCallInd { info, callee } => { + Inst::ReturnCallInd { info } => { // TODO(https://github.com/bytecodealliance/regalloc2/issues/145): // This shouldn't be a fixed register constraint, but it's not clear how to pick a // register that won't be clobbered by the callee-save restore code emitted with a // return_call_indirect. - collector.reg_fixed_use(callee, xreg(1)); + collector.reg_fixed_use(&mut info.dest, xreg(1)); for CallArgPair { vreg, preg } in &mut info.uses { collector.reg_fixed_use(vreg, *preg); } @@ -1019,10 +978,10 @@ impl MachInst for Inst { } fn is_included_in_clobbers(&self) -> bool { - let (caller_callconv, callee_callconv) = match self { + let (caller, callee) = match self { Inst::Args { .. } => return false, - Inst::Call { info } => (info.caller_callconv, info.callee_callconv), - Inst::CallInd { info } => (info.caller_callconv, info.callee_callconv), + Inst::Call { info } => (info.caller_conv, info.callee_conv), + Inst::CallInd { info } => (info.caller_conv, info.callee_conv), _ => return true, }; @@ -1037,8 +996,8 @@ impl MachInst for Inst { // // See the note in [crate::isa::aarch64::abi::is_caller_save_reg] for // more information on this ABI-implementation hack. - let caller_clobbers = AArch64MachineDeps::get_regs_clobbered_by_call(caller_callconv); - let callee_clobbers = AArch64MachineDeps::get_regs_clobbered_by_call(callee_callconv); + let caller_clobbers = AArch64MachineDeps::get_regs_clobbered_by_call(caller); + let callee_clobbers = AArch64MachineDeps::get_regs_clobbered_by_call(callee); let mut all_clobbers = caller_clobbers; all_clobbers.union_from(callee_clobbers); @@ -2608,17 +2567,14 @@ impl Inst { } } &Inst::Call { .. } => format!("bl 0"), - &Inst::CallInd { ref info, .. } => { - let rn = pretty_print_reg(info.rn); + &Inst::CallInd { ref info } => { + let rn = pretty_print_reg(info.dest); format!("blr {rn}") } - &Inst::ReturnCall { - ref callee, - ref info, - } => { + &Inst::ReturnCall { ref info } => { let mut s = format!( - "return_call {callee:?} new_stack_arg_size:{}", - info.new_stack_arg_size + "return_call {:?} new_stack_arg_size:{}", + info.dest, info.new_stack_arg_size ); for ret in &info.uses { let preg = pretty_print_reg(ret.preg); @@ -2627,8 +2583,8 @@ impl Inst { } s } - &Inst::ReturnCallInd { callee, ref info } => { - let callee = pretty_print_reg(callee); + &Inst::ReturnCallInd { ref info } => { + let callee = pretty_print_reg(info.dest); let mut s = format!( "return_call_ind {callee} new_stack_arg_size:{}", info.new_stack_arg_size diff --git a/cranelift/codegen/src/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle index 415d408549b6..58188aee5d52 100644 --- a/cranelift/codegen/src/isa/aarch64/lower.isle +++ b/cranelift/codegen/src/isa/aarch64/lower.isle @@ -255,6 +255,21 @@ (x_hi ValueRegs (value_regs_get x_regs 1))) (output_pair x_lo x_hi))) +;; Special-case the lowering of an `isplit` of a 128-bit multiply where the +;; lower bits of the result are discarded and the operands are sign or zero +;; extended. This maps directly to `umulh` and `smulh`. +(rule 1 (lower i @ (isplit (has_type $I128 (imul (uextend x) (uextend y))))) + (if-let (first_result lo) i) + (if-let $true (value_is_unused lo)) + (output_pair (invalid_reg) + (umulh $I64 (put_in_reg_zext64 x) (put_in_reg_zext64 y)))) + +(rule 1 (lower i @ (isplit (has_type $I128 (imul (sextend x) (sextend y))))) + (if-let (first_result lo) i) + (if-let $true (value_is_unused lo)) + (output_pair (invalid_reg) + (smulh $I64 (put_in_reg_sext64 x) (put_in_reg_sext64 y)))) + ;;;; Rules for `iconcat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (has_type $I128 (iconcat lo hi))) @@ -820,6 +835,26 @@ (dst_lo Reg (madd $I64 x_lo y_lo (zero_reg)))) (value_regs dst_lo dst_hi))) +;; Special cases where the upper bits are sign-or-zero extended of the lower bits +;; so the calculation here is much simpler with just a `umulh` or `smulh` +;; instead of the additions above as well. +(rule (lower (has_type $I128 (imul (uextend x) (uextend y)))) + (let ( + (x Reg (put_in_reg_zext64 x)) + (y Reg (put_in_reg_zext64 y)) + ) + (value_regs + (madd $I64 x y (zero_reg)) + (umulh $I64 x y)))) +(rule (lower (has_type $I128 (imul (sextend x) (sextend y)))) + (let ( + (x Reg (put_in_reg_sext64 x)) + (y Reg (put_in_reg_sext64 y)) + ) + (value_regs + (madd $I64 x y (zero_reg)) + (smulh $I64 x y)))) + ;; Case for i8x16, i16x8, and i32x4. (rule -2 (lower (has_type (ty_vec128 ty @ (not_i64x2)) (imul x y))) (mul x y (vector_size ty))) diff --git a/cranelift/codegen/src/isa/aarch64/lower/isle.rs b/cranelift/codegen/src/isa/aarch64/lower/isle.rs index 29a3f1c68a4b..44e3b4d0d594 100644 --- a/cranelift/codegen/src/isa/aarch64/lower/isle.rs +++ b/cranelift/codegen/src/isa/aarch64/lower/isle.rs @@ -7,9 +7,9 @@ use generated_code::Context; // Types that the generated ISLE code uses via `use super::*`. use super::{ fp_reg, lower_condcode, lower_fp_condcode, stack_reg, writable_link_reg, writable_zero_reg, - zero_reg, ASIMDFPModImm, ASIMDMovModImm, BranchTarget, CallIndInfo, CallInfo, Cond, CondBrKind, - ExtendOp, FPUOpRI, FPUOpRIMod, FloatCC, Imm12, ImmLogic, ImmShift, Inst as MInst, IntCC, - MachLabel, MemLabel, MoveWideConst, MoveWideOp, Opcode, OperandSize, Reg, SImm9, ScalarSize, + zero_reg, ASIMDFPModImm, ASIMDMovModImm, BranchTarget, CallInfo, Cond, CondBrKind, ExtendOp, + FPUOpRI, FPUOpRIMod, FloatCC, Imm12, ImmLogic, ImmShift, Inst as MInst, IntCC, MachLabel, + MemLabel, MoveWideConst, MoveWideOp, Opcode, OperandSize, Reg, SImm9, ScalarSize, ShiftOpAndAmt, UImm12Scaled, UImm5, VecMisc2, VectorSize, NZCV, }; use crate::ir::{condcodes, ArgumentExtension}; @@ -34,9 +34,10 @@ use regalloc2::PReg; use std::boxed::Box; use std::vec::Vec; -type BoxCallInfo = Box; -type BoxCallIndInfo = Box; -type BoxReturnCallInfo = Box; +type BoxCallInfo = Box>; +type BoxCallIndInfo = Box>; +type BoxReturnCallInfo = Box>; +type BoxReturnCallIndInfo = Box>; type VecMachLabel = Vec; type BoxExternalName = Box; type VecArgPair = Vec; diff --git a/cranelift/codegen/src/isa/mod.rs b/cranelift/codegen/src/isa/mod.rs index 5ba1b8610c93..ebd457435b7f 100644 --- a/cranelift/codegen/src/isa/mod.rs +++ b/cranelift/codegen/src/isa/mod.rs @@ -85,6 +85,7 @@ mod pulley_shared; pub mod unwind; mod call_conv; +mod winch; /// Returns a builder that can create a corresponding `TargetIsa` /// or `Err(LookupError::SupportDisabled)` if not enabled. diff --git a/cranelift/codegen/src/isa/pulley_shared/abi.rs b/cranelift/codegen/src/isa/pulley_shared/abi.rs index a88fe2ac81c5..ec63d953e2b2 100644 --- a/cranelift/codegen/src/isa/pulley_shared/abi.rs +++ b/cranelift/codegen/src/isa/pulley_shared/abi.rs @@ -204,15 +204,35 @@ where fn gen_add_imm( _call_conv: isa::CallConv, - _into_reg: Writable, - _from_reg: Reg, - _imm: u32, + into_reg: Writable, + from_reg: Reg, + imm: u32, ) -> SmallInstVec { - todo!() + let dst = into_reg.try_into().unwrap(); + let imm = imm as i32; + smallvec![ + Inst::Xconst32 { dst, imm }.into(), + Inst::Xadd32 { + dst, + src1: from_reg.try_into().unwrap(), + src2: dst.to_reg(), + } + .into() + ] } - fn gen_stack_lower_bound_trap(_limit_reg: Reg) -> SmallInstVec { - todo!() + fn gen_stack_lower_bound_trap(limit_reg: Reg) -> SmallInstVec { + smallvec![Inst::TrapIf { + cond: ir::condcodes::IntCC::UnsignedLessThan, + size: match P::pointer_width() { + super::PointerWidth::PointerWidth32 => OperandSize::Size32, + super::PointerWidth::PointerWidth64 => OperandSize::Size64, + }, + src1: limit_reg.try_into().unwrap(), + src2: pulley_interpreter::regs::XReg::sp.into(), + code: ir::TrapCode::StackOverflow, + } + .into()] } fn gen_get_stack_addr(mem: StackAMode, dst: Writable) -> Self::I { @@ -522,26 +542,11 @@ where insts } - fn gen_call( - dest: &CallDest, - uses: CallArgList, - defs: CallRetList, - clobbers: PRegSet, - tmp: Writable, - callee_conv: isa::CallConv, - caller_conv: isa::CallConv, - callee_pop_size: u32, - ) -> SmallVec<[Self::I; 2]> { - if callee_conv == isa::CallConv::Tail || callee_conv == isa::CallConv::Fast { + fn gen_call(dest: &CallDest, tmp: Writable, info: CallInfo<()>) -> SmallVec<[Self::I; 2]> { + if info.callee_conv == isa::CallConv::Tail || info.callee_conv == isa::CallConv::Fast { match &dest { &CallDest::ExtName(ref name, RelocDistance::Near) => smallvec![Inst::Call { - callee: Box::new(name.clone()), - info: Box::new(CallInfo { - uses, - defs, - clobbers, - callee_pop_size, - }), + info: Box::new(info.map(|()| name.clone())) } .into()], &CallDest::ExtName(ref name, RelocDistance::Far) => smallvec![ @@ -552,29 +557,21 @@ where } .into(), Inst::IndirectCall { - callee: XReg::new(tmp.to_reg()).unwrap(), - info: Box::new(CallInfo { - uses, - defs, - clobbers, - callee_pop_size, - }), + info: Box::new(info.map(|()| XReg::new(tmp.to_reg()).unwrap())) } .into(), ], &CallDest::Reg(reg) => smallvec![Inst::IndirectCall { - callee: XReg::new(*reg).unwrap(), - info: Box::new(CallInfo { - uses, - defs, - clobbers, - callee_pop_size, - }), + info: Box::new(info.map(|()| XReg::new(*reg).unwrap())) } .into()], } } else { - todo!("host calls? callee_conv = {callee_conv:?}; caller_conv = {caller_conv:?}") + todo!( + "host calls? callee_conv = {:?}; caller_conv = {:?}", + info.callee_conv, + info.caller_conv, + ) } } diff --git a/cranelift/codegen/src/isa/pulley_shared/inst.isle b/cranelift/codegen/src/isa/pulley_shared/inst.isle index 6301353a70e0..7c39d42d7d49 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst.isle +++ b/cranelift/codegen/src/isa/pulley_shared/inst.isle @@ -1,5 +1,7 @@ ;;;; Instruction definition ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(type OperandSize extern (enum Size32 Size64)) + ;; Note: in the instructions below, we order destination registers first and ;; then source registers afterwards. (type MInst @@ -20,6 +22,9 @@ ;; Raise a trap. (Trap (code TrapCode)) + ;; Trap if `src1 cond src2`. + (TrapIf (cond IntCC) (size OperandSize) (src1 XReg) (src2 XReg) (code TrapCode)) + ;; Nothing. (Nop) @@ -35,12 +40,10 @@ (offset i64)) ;; A direct call to a known callee. - (Call (callee BoxExternalName) - (info BoxCallInfo)) + (Call (info BoxCallInfo)) ;; An indirect call to an unknown callee. - (IndirectCall (callee XReg) - (info BoxCallInfo)) + (IndirectCall (info BoxCallIndInfo)) ;; Unconditional jumps. (Jump (label MachLabel)) @@ -103,6 +106,7 @@ ) (type BoxCallInfo (primitive BoxCallInfo)) +(type BoxCallIndInfo (primitive BoxCallIndInfo)) ;;;; Address Modes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/args.rs b/cranelift/codegen/src/isa/pulley_shared/inst/args.rs index d74c2a7e010a..9713822ce6d1 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/args.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/args.rs @@ -10,7 +10,7 @@ macro_rules! newtype_of_reg { ( $newtype_reg:ident, $newtype_writable_reg:ident, - |$check_reg:ident| $check:expr + $class:expr ) => { /// A newtype wrapper around `Reg`. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -38,9 +38,9 @@ macro_rules! newtype_of_reg { impl $newtype_reg { /// Create this newtype from the given register, or return `None` if the register /// is not a valid instance of this newtype. - pub fn new($check_reg: Reg) -> Option { - if $check { - Some(Self($check_reg)) + pub fn new(reg: Reg) -> Option { + if reg.class() == $class { + Some(Self(reg)) } else { None } @@ -78,6 +78,11 @@ macro_rules! newtype_of_reg { /// Writable Reg. pub type $newtype_writable_reg = Writable<$newtype_reg>; + impl From for $newtype_reg { + fn from(r: pulley_interpreter::regs::$newtype_reg) -> Self { + Self::new(regalloc2::PReg::new(usize::from(r as u8), $class).into()).unwrap() + } + } impl From<$newtype_reg> for pulley_interpreter::regs::$newtype_reg { fn from(r: $newtype_reg) -> Self { Self::new(r.to_real_reg().unwrap().hw_enc()).unwrap() @@ -113,9 +118,9 @@ macro_rules! newtype_of_reg { } // Newtypes for registers classes. -newtype_of_reg!(XReg, WritableXReg, |reg| reg.class() == RegClass::Int); -newtype_of_reg!(FReg, WritableFReg, |reg| reg.class() == RegClass::Float); -newtype_of_reg!(VReg, WritableVReg, |reg| reg.class() == RegClass::Vector); +newtype_of_reg!(XReg, WritableXReg, RegClass::Int); +newtype_of_reg!(FReg, WritableFReg, RegClass::Float); +newtype_of_reg!(VReg, WritableVReg, RegClass::Vector); pub use super::super::lower::isle::generated_code::ExtKind; @@ -190,3 +195,12 @@ impl From for Amode { Amode::Stack { amode } } } + +/// The size of an operand or operation. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OperandSize { + /// 32 bits. + Size32, + /// 64 bits. + Size64, +} diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs index 7470bcad67e3..1c0556eb73ee 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs @@ -139,6 +139,53 @@ fn pulley_emit

( enc::trap(sink); } + Inst::TrapIf { + cond, + size, + src1, + src2, + code, + } => { + let label = sink.defer_trap(*code); + + let cur_off = sink.cur_offset(); + sink.use_label_at_offset(cur_off, label, LabelUse::Jump(3)); + + use ir::condcodes::IntCC::*; + use OperandSize::*; + match (cond, size) { + (Equal, Size32) => enc::br_if_xeq32(sink, src1, src2, 0), + (Equal, Size64) => enc::br_if_xeq64(sink, src1, src2, 0), + + (NotEqual, Size32) => enc::br_if_xneq32(sink, src1, src2, 0), + (NotEqual, Size64) => enc::br_if_xneq64(sink, src1, src2, 0), + + (SignedLessThan, Size32) => enc::br_if_xslt32(sink, src1, src2, 0), + (SignedLessThan, Size64) => enc::br_if_xslt64(sink, src1, src2, 0), + + (SignedLessThanOrEqual, Size32) => enc::br_if_xslteq32(sink, src1, src2, 0), + (SignedLessThanOrEqual, Size64) => enc::br_if_xslteq64(sink, src1, src2, 0), + + (UnsignedLessThan, Size32) => enc::br_if_xult32(sink, src1, src2, 0), + (UnsignedLessThan, Size64) => enc::br_if_xult64(sink, src1, src2, 0), + + (UnsignedLessThanOrEqual, Size32) => enc::br_if_xulteq32(sink, src1, src2, 0), + (UnsignedLessThanOrEqual, Size64) => enc::br_if_xulteq64(sink, src1, src2, 0), + + (SignedGreaterThan, Size32) => enc::br_if_xslt32(sink, src2, src1, 0), + (SignedGreaterThan, Size64) => enc::br_if_xslt64(sink, src2, src1, 0), + + (SignedGreaterThanOrEqual, Size32) => enc::br_if_xslteq32(sink, src2, src1, 0), + (SignedGreaterThanOrEqual, Size64) => enc::br_if_xslteq64(sink, src2, src1, 0), + + (UnsignedGreaterThan, Size32) => enc::br_if_xult32(sink, src2, src1, 0), + (UnsignedGreaterThan, Size64) => enc::br_if_xult64(sink, src2, src1, 0), + + (UnsignedGreaterThanOrEqual, Size32) => enc::br_if_xulteq32(sink, src2, src1, 0), + (UnsignedGreaterThanOrEqual, Size64) => enc::br_if_xulteq64(sink, src2, src1, 0), + } + } + Inst::Nop => todo!(), Inst::GetSp { dst } => enc::get_sp(sink, dst), @@ -147,12 +194,12 @@ fn pulley_emit

( Inst::LoadExtName { .. } => todo!(), - Inst::Call { callee, info } => { + Inst::Call { info } => { sink.put1(pulley_interpreter::Opcode::Call as u8); sink.add_reloc( // TODO: is it actually okay to reuse this reloc here? Reloc::X86CallPCRel4, - &**callee, + &info.dest, // This addend adjusts for the difference between the start of // the instruction and the beginning of the immediate field. -1, diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs index 8051ae9f3fc0..de8f681d2a24 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs @@ -10,7 +10,7 @@ use crate::isa::FunctionAlignment; use crate::{machinst::*, trace}; use crate::{settings, CodegenError, CodegenResult}; use alloc::string::{String, ToString}; -use regalloc2::{PRegSet, RegClass}; +use regalloc2::RegClass; use smallvec::SmallVec; pub mod regs; @@ -27,17 +27,6 @@ pub use crate::isa::pulley_shared::lower::isle::generated_code::MInst as Inst; use super::PulleyTargetKind; -/// Additional information for direct and indirect call instructions. -/// -/// Left out of line to lower the size of the `Inst` enum. -#[derive(Clone, Debug)] -pub struct CallInfo { - pub uses: CallArgList, - pub defs: CallRetList, - pub clobbers: PRegSet, - pub callee_pop_size: u32, -} - impl Inst { /// Generic constructor for a load (zero-extending where appropriate). pub fn gen_load(dst: Writable, mem: Amode, ty: Type, flags: MemFlags) -> Inst { @@ -79,6 +68,17 @@ fn pulley_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { Inst::Unwind { .. } | Inst::Trap { .. } | Inst::Nop => {} + Inst::TrapIf { + cond: _, + size: _, + src1, + src2, + code: _, + } => { + collector.reg_use(src1); + collector.reg_use(src2); + } + Inst::GetSp { dst } => { collector.reg_def(dst); } @@ -91,7 +91,7 @@ fn pulley_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_def(dst); } - Inst::Call { callee: _, info } => { + Inst::Call { info } => { let CallInfo { uses, defs, .. } = &mut **info; for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); @@ -101,8 +101,8 @@ fn pulley_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { } collector.reg_clobbers(info.clobbers); } - Inst::IndirectCall { callee, info } => { - collector.reg_use(callee); + Inst::IndirectCall { info } => { + collector.reg_use(&mut info.dest); let CallInfo { uses, defs, .. } = &mut **info; for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); @@ -534,6 +534,18 @@ impl Inst { Inst::Trap { code } => format!("trap // code = {code:?}"), + Inst::TrapIf { + cond, + size, + src1, + src2, + code, + } => { + let src1 = format_reg(**src1); + let src2 = format_reg(**src2); + format!("trap_if {cond}, {size:?}, {src1}, {src2} // code = {code:?}") + } + Inst::Nop => format!("nop"), Inst::Ret => format!("ret"), @@ -548,12 +560,12 @@ impl Inst { format!("{dst} = load_ext_name {name:?}, {offset}") } - Inst::Call { callee, info } => { - format!("call {callee:?}, {info:?}") + Inst::Call { info } => { + format!("call {info:?}") } - Inst::IndirectCall { callee, info } => { - let callee = format_reg(**callee); + Inst::IndirectCall { info } => { + let callee = format_reg(*info.dest); format!("indirect_call {callee}, {info:?}") } diff --git a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs index 51e17d29ce67..1f68650ef8f7 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs +++ b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs @@ -9,20 +9,21 @@ use inst::InstAndKind; use crate::ir::{condcodes::*, immediates::*, types::*, *}; use crate::isa::pulley_shared::{ abi::*, - inst::{CallInfo, FReg, VReg, WritableFReg, WritableVReg, WritableXReg, XReg}, + inst::{FReg, OperandSize, VReg, WritableFReg, WritableVReg, WritableXReg, XReg}, *, }; use crate::machinst::{ abi::{ArgPair, RetPair, StackAMode}, isle::*, - IsTailCall, MachInst, Reg, VCodeConstant, VCodeConstantData, + CallInfo, IsTailCall, MachInst, Reg, VCodeConstant, VCodeConstantData, }; use alloc::boxed::Box; use regalloc2::PReg; type Unit = (); type VecArgPair = Vec; type VecRetPair = Vec; -type BoxCallInfo = Box; +type BoxCallInfo = Box>; +type BoxCallIndInfo = Box>; type BoxExternalName = Box; pub(crate) struct PulleyIsleContext<'a, 'b, I, B> diff --git a/cranelift/codegen/src/isa/riscv64/abi.rs b/cranelift/codegen/src/isa/riscv64/abi.rs index 2a6b23f3af38..b90fa643c3ca 100644 --- a/cranelift/codegen/src/isa/riscv64/abi.rs +++ b/cranelift/codegen/src/isa/riscv64/abi.rs @@ -424,19 +424,16 @@ impl ABIMachineSpec for Riscv64MachineDeps { fn gen_probestack(insts: &mut SmallInstVec, frame_size: u32) { insts.extend(Inst::load_constant_u32(writable_a0(), frame_size as u64)); + let mut info = CallInfo::empty( + ExternalName::LibCall(LibCall::Probestack), + CallConv::SystemV, + ); + info.uses.push(CallArgPair { + vreg: a0(), + preg: a0(), + }); insts.push(Inst::Call { - info: Box::new(CallInfo { - dest: ExternalName::LibCall(LibCall::Probestack), - uses: smallvec![CallArgPair { - vreg: a0(), - preg: a0(), - }], - defs: smallvec![], - clobbers: PRegSet::empty(), - callee_callconv: CallConv::SystemV, - caller_callconv: CallConv::SystemV, - callee_pop_size: 0, - }), + info: Box::new(info), }); } @@ -567,58 +564,26 @@ impl ABIMachineSpec for Riscv64MachineDeps { insts } - fn gen_call( - dest: &CallDest, - uses: CallArgList, - defs: CallRetList, - clobbers: PRegSet, - tmp: Writable, - callee_conv: isa::CallConv, - caller_conv: isa::CallConv, - callee_pop_size: u32, - ) -> SmallVec<[Self::I; 2]> { + fn gen_call(dest: &CallDest, tmp: Writable, info: CallInfo<()>) -> SmallVec<[Self::I; 2]> { let mut insts = SmallVec::new(); match &dest { - &CallDest::ExtName(ref name, RelocDistance::Near) => insts.push(Inst::Call { - info: Box::new(CallInfo { - dest: name.clone(), - uses, - defs, - clobbers, - caller_callconv: caller_conv, - callee_callconv: callee_conv, - callee_pop_size, - }), - }), + &CallDest::ExtName(ref name, RelocDistance::Near) => { + let info = Box::new(info.map(|()| name.clone())); + insts.push(Inst::Call { info }) + } &CallDest::ExtName(ref name, RelocDistance::Far) => { insts.push(Inst::LoadExtName { rd: tmp, name: Box::new(name.clone()), offset: 0, }); - insts.push(Inst::CallInd { - info: Box::new(CallIndInfo { - rn: tmp.to_reg(), - uses, - defs, - clobbers, - caller_callconv: caller_conv, - callee_callconv: callee_conv, - callee_pop_size, - }), - }); + let info = Box::new(info.map(|()| tmp.to_reg())); + insts.push(Inst::CallInd { info }); + } + &CallDest::Reg(reg) => { + let info = Box::new(info.map(|()| *reg)); + insts.push(Inst::CallInd { info }); } - &CallDest::Reg(reg) => insts.push(Inst::CallInd { - info: Box::new(CallIndInfo { - rn: *reg, - uses, - defs, - clobbers, - caller_callconv: caller_conv, - callee_callconv: callee_conv, - callee_pop_size, - }), - }), } insts } @@ -655,8 +620,8 @@ impl ABIMachineSpec for Riscv64MachineDeps { ], defs: smallvec![], clobbers: Self::get_regs_clobbered_by_call(call_conv), - caller_callconv: call_conv, - callee_callconv: call_conv, + caller_conv: call_conv, + callee_conv: call_conv, callee_pop_size: 0, }), }); @@ -773,17 +738,15 @@ impl Riscv64ABICallSite { let dest = self.dest().clone(); let uses = self.take_uses(); - let info = Box::new(ReturnCallInfo { - uses, - new_stack_arg_size, - }); match dest { CallDest::ExtName(name, RelocDistance::Near) => { - ctx.emit(Inst::ReturnCall { - callee: Box::new(name), - info, + let info = Box::new(ReturnCallInfo { + dest: name, + uses, + new_stack_arg_size, }); + ctx.emit(Inst::ReturnCall { info }); } CallDest::ExtName(name, RelocDistance::Far) => { let callee = ctx.alloc_tmp(ir::types::I64).only_reg().unwrap(); @@ -792,12 +755,21 @@ impl Riscv64ABICallSite { name: Box::new(name), offset: 0, }); - ctx.emit(Inst::ReturnCallInd { - callee: callee.to_reg(), - info, + let info = Box::new(ReturnCallInfo { + dest: callee.to_reg(), + uses, + new_stack_arg_size, + }); + ctx.emit(Inst::ReturnCallInd { info }); + } + CallDest::Reg(callee) => { + let info = Box::new(ReturnCallInfo { + dest: callee, + uses, + new_stack_arg_size, }); + ctx.emit(Inst::ReturnCallInd { info }); } - CallDest::Reg(callee) => ctx.emit(Inst::ReturnCallInd { callee, info }), } } } diff --git a/cranelift/codegen/src/isa/riscv64/inst.isle b/cranelift/codegen/src/isa/riscv64/inst.isle index 1e9e004b35e9..f6e457094153 100644 --- a/cranelift/codegen/src/isa/riscv64/inst.isle +++ b/cranelift/codegen/src/isa/riscv64/inst.isle @@ -111,22 +111,16 @@ (from_bits u8) (to_bits u8)) - (Call - (info BoxCallInfo)) + (Call (info BoxCallInfo)) ;; A machine indirect-call instruction. - (CallInd - (info BoxCallIndInfo)) + (CallInd (info BoxCallIndInfo)) ;; A direct return-call macro instruction. - (ReturnCall - (callee BoxExternalName) - (info BoxReturnCallInfo)) + (ReturnCall (info BoxReturnCallInfo)) ;; An indirect return-call macro instruction. - (ReturnCallInd - (callee Reg) - (info BoxReturnCallInfo)) + (ReturnCallInd (info BoxReturnCallIndInfo)) ;; Emits a trap with the given trap code if the comparison succeeds (TrapIf @@ -780,6 +774,7 @@ (type BoxCallInfo (primitive BoxCallInfo)) (type BoxCallIndInfo (primitive BoxCallIndInfo)) (type BoxReturnCallInfo (primitive BoxReturnCallInfo)) +(type BoxReturnCallIndInfo (primitive BoxReturnCallIndInfo)) (type IntegerCompare (primitive IntegerCompare)) (type AMode (primitive AMode)) (type OptionReg (primitive OptionReg)) diff --git a/cranelift/codegen/src/isa/riscv64/inst/emit.rs b/cranelift/codegen/src/isa/riscv64/inst/emit.rs index bbce4ec90fdd..9282abb2e086 100644 --- a/cranelift/codegen/src/isa/riscv64/inst/emit.rs +++ b/cranelift/codegen/src/isa/riscv64/inst/emit.rs @@ -1137,7 +1137,7 @@ impl Inst { &Inst::CallInd { ref info } => { Inst::Jalr { rd: writable_link_reg(), - base: info.rn, + base: info.dest, offset: Imm12::ZERO, } .emit(sink, emit_info, state); @@ -1157,25 +1157,22 @@ impl Inst { } } - &Inst::ReturnCall { - ref callee, - ref info, - } => { + &Inst::ReturnCall { ref info } => { emit_return_call_common_sequence(sink, emit_info, state, info); sink.add_call_site(); - sink.add_reloc(Reloc::RiscvCallPlt, &**callee, 0); + sink.add_reloc(Reloc::RiscvCallPlt, &info.dest, 0); Inst::construct_auipc_and_jalr(None, writable_spilltmp_reg(), 0) .into_iter() .for_each(|i| i.emit_uncompressed(sink, emit_info, state, start_off)); } - &Inst::ReturnCallInd { callee, ref info } => { + &Inst::ReturnCallInd { ref info } => { emit_return_call_common_sequence(sink, emit_info, state, &info); Inst::Jalr { rd: writable_zero_reg(), - base: callee, + base: info.dest, offset: Imm12::ZERO, } .emit(sink, emit_info, state); @@ -1986,15 +1983,10 @@ impl Inst { .emit_uncompressed(sink, emit_info, state, start_off); Inst::Call { - info: Box::new(CallInfo { - dest: ExternalName::LibCall(LibCall::ElfTlsGetAddr), - uses: smallvec![], - defs: smallvec![], - caller_callconv: CallConv::SystemV, - callee_callconv: CallConv::SystemV, - callee_pop_size: 0, - clobbers: PRegSet::empty(), - }), + info: Box::new(CallInfo::empty( + ExternalName::LibCall(LibCall::ElfTlsGetAddr), + CallConv::SystemV, + )), } .emit_uncompressed(sink, emit_info, state, start_off); } @@ -2589,11 +2581,11 @@ impl Inst { } } -fn emit_return_call_common_sequence( +fn emit_return_call_common_sequence( sink: &mut MachBuffer, emit_info: &EmitInfo, state: &mut EmitState, - info: &ReturnCallInfo, + info: &ReturnCallInfo, ) { // The return call sequence can potentially emit a lot of instructions (up to 634 bytes!) // So lets emit an island here if we need it. @@ -2623,11 +2615,11 @@ fn emit_return_call_common_sequence( } /// This should not be called directly, Instead prefer to call [emit_return_call_common_sequence]. -fn return_call_emit_impl( +fn return_call_emit_impl( sink: &mut MachBuffer, emit_info: &EmitInfo, state: &mut EmitState, - info: &ReturnCallInfo, + info: &ReturnCallInfo, ) { let sp_to_fp_offset = { let frame_layout = state.frame_layout(); diff --git a/cranelift/codegen/src/isa/riscv64/inst/mod.rs b/cranelift/codegen/src/isa/riscv64/inst/mod.rs index 292892b9fe81..14d5fd4fc764 100644 --- a/cranelift/codegen/src/isa/riscv64/inst/mod.rs +++ b/cranelift/codegen/src/isa/riscv64/inst/mod.rs @@ -13,7 +13,7 @@ use crate::{settings, CodegenError, CodegenResult}; pub use crate::ir::condcodes::FloatCC; use alloc::vec::Vec; -use regalloc2::{PRegSet, RegClass}; +use regalloc2::RegClass; use smallvec::{smallvec, SmallVec}; use std::boxed::Box; use std::fmt::Write; @@ -51,36 +51,11 @@ pub use crate::isa::riscv64::lower::isle::generated_code::{ }; use crate::isa::riscv64::lower::isle::generated_code::{CjOp, MInst, VecAluOpRRImm5, VecAluOpRRR}; -/// Additional information for (direct) Call instructions, left out of line to lower the size of -/// the Inst enum. -#[derive(Clone, Debug)] -pub struct CallInfo { - pub dest: ExternalName, - pub uses: CallArgList, - pub defs: CallRetList, - pub caller_callconv: CallConv, - pub callee_callconv: CallConv, - pub clobbers: PRegSet, - pub callee_pop_size: u32, -} - -/// Additional information for CallInd instructions, left out of line to lower the size of the Inst -/// enum. -#[derive(Clone, Debug)] -pub struct CallIndInfo { - pub rn: Reg, - pub uses: CallArgList, - pub defs: CallRetList, - pub caller_callconv: CallConv, - pub callee_callconv: CallConv, - pub clobbers: PRegSet, - pub callee_pop_size: u32, -} - /// Additional information for `return_call[_ind]` instructions, left out of /// line to lower the size of the `Inst` enum. #[derive(Clone, Debug)] -pub struct ReturnCallInfo { +pub struct ReturnCallInfo { + pub dest: T, pub uses: CallArgList, pub new_stack_arg_size: u32, } @@ -355,7 +330,7 @@ fn riscv64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_use(rn); collector.reg_def(rd); } - Inst::Call { info } => { + Inst::Call { info, .. } => { let CallInfo { uses, defs, .. } = &mut **info; for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); @@ -366,8 +341,10 @@ fn riscv64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_clobbers(info.clobbers); } Inst::CallInd { info } => { - let CallIndInfo { rn, uses, defs, .. } = &mut **info; - collector.reg_use(rn); + let CallInfo { + dest, uses, defs, .. + } = &mut **info; + collector.reg_use(dest); for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); } @@ -376,15 +353,15 @@ fn riscv64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { } collector.reg_clobbers(info.clobbers); } - Inst::ReturnCall { info, .. } => { + Inst::ReturnCall { info } => { for CallArgPair { vreg, preg } in &mut info.uses { collector.reg_fixed_use(vreg, *preg); } } - Inst::ReturnCallInd { info, callee } => { + Inst::ReturnCallInd { info } => { // TODO(https://github.com/bytecodealliance/regalloc2/issues/145): // This shouldn't be a fixed register constraint. - collector.reg_fixed_use(callee, x_reg(5)); + collector.reg_fixed_use(&mut info.dest, x_reg(5)); for CallArgPair { vreg, preg } in &mut info.uses { collector.reg_fixed_use(vreg, *preg); @@ -1323,16 +1300,13 @@ impl Inst { } &MInst::Call { ref info } => format!("call {}", info.dest.display(None)), &MInst::CallInd { ref info } => { - let rd = format_reg(info.rn); + let rd = format_reg(info.dest); format!("callind {rd}") } - &MInst::ReturnCall { - ref callee, - ref info, - } => { + &MInst::ReturnCall { ref info } => { let mut s = format!( - "return_call {callee:?} new_stack_arg_size:{}", - info.new_stack_arg_size + "return_call {:?} new_stack_arg_size:{}", + info.dest, info.new_stack_arg_size ); for ret in &info.uses { let preg = format_reg(ret.preg); @@ -1341,8 +1315,8 @@ impl Inst { } s } - &MInst::ReturnCallInd { callee, ref info } => { - let callee = format_reg(callee); + &MInst::ReturnCallInd { ref info } => { + let callee = format_reg(info.dest); let mut s = format!( "return_call_ind {callee} new_stack_arg_size:{}", info.new_stack_arg_size diff --git a/cranelift/codegen/src/isa/riscv64/lower.isle b/cranelift/codegen/src/isa/riscv64/lower.isle index 41c07ae0068c..fff894e9985a 100644 --- a/cranelift/codegen/src/isa/riscv64/lower.isle +++ b/cranelift/codegen/src/isa/riscv64/lower.isle @@ -480,6 +480,20 @@ (dst_lo XReg (madd x_lo y_lo (zero_reg)))) (value_regs dst_lo dst_hi))) +;; Special case 128-bit multiplication where the operands are extended since +;; that maps directly to the `mulhu` and `mulh` instructions. +(rule 6 (lower (has_type $I128 (imul (uextend x) (uextend y)))) + (let ((x XReg (zext x)) + (y XReg (zext y))) + (value_regs (rv_mul x y) (rv_mulhu x y)))) + +(rule 6 (lower (has_type $I128 (imul (sextend x) (sextend y)))) + (let ((x XReg (sext x)) + (y XReg (sext y))) + (value_regs (rv_mul x y) (rv_mulh x y)))) + +;; Vector multiplication + (rule 3 (lower (has_type (ty_supported_vec ty) (imul x y))) (rv_vmul_vv x y (unmasked) ty)) @@ -1931,6 +1945,18 @@ (t2 XReg y)) (value_regs t1 t2))) +;; Special-case the lowering of an `isplit` of a 128-bit multiply where the +;; lower bits of the result are discarded and the operands are sign or zero +;; extended. This maps directly to `umulh` and `smulh`. +(rule 1 (lower i @ (isplit (has_type $I128 (imul (uextend x) (uextend y))))) + (if-let (first_result lo) i) + (if-let $true (value_is_unused lo)) + (output_pair (invalid_reg) (rv_mulhu (zext x) (zext y)))) + +(rule 1 (lower i @ (isplit (has_type $I128 (imul (sextend x) (sextend y))))) + (if-let (first_result lo) i) + (if-let $true (value_is_unused lo)) + (output_pair (invalid_reg) (rv_mulh (sext x) (sext y)))) ;;;;; Rules for `smax`;;;;;;;;; diff --git a/cranelift/codegen/src/isa/riscv64/lower/isle.rs b/cranelift/codegen/src/isa/riscv64/lower/isle.rs index 3c0090d0b2d2..28a0bd064667 100644 --- a/cranelift/codegen/src/isa/riscv64/lower/isle.rs +++ b/cranelift/codegen/src/isa/riscv64/lower/isle.rs @@ -14,7 +14,7 @@ use crate::isa::riscv64::lower::args::{ }; use crate::isa::riscv64::Riscv64Backend; use crate::machinst::Reg; -use crate::machinst::{isle::*, MachInst}; +use crate::machinst::{isle::*, CallInfo, MachInst}; use crate::machinst::{VCodeConstant, VCodeConstantData}; use crate::{ ir::{ @@ -28,9 +28,10 @@ use regalloc2::PReg; use std::boxed::Box; use std::vec::Vec; -type BoxCallInfo = Box; -type BoxCallIndInfo = Box; -type BoxReturnCallInfo = Box; +type BoxCallInfo = Box>; +type BoxCallIndInfo = Box>; +type BoxReturnCallInfo = Box>; +type BoxReturnCallIndInfo = Box>; type BoxExternalName = Box; type VecMachLabel = Vec; type VecArgPair = Vec; diff --git a/cranelift/codegen/src/isa/s390x/abi.rs b/cranelift/codegen/src/isa/s390x/abi.rs index 20082a80b758..f6de879b1a43 100644 --- a/cranelift/codegen/src/isa/s390x/abi.rs +++ b/cranelift/codegen/src/isa/s390x/abi.rs @@ -801,16 +801,7 @@ impl ABIMachineSpec for S390xMachineDeps { insts } - fn gen_call( - _dest: &CallDest, - _uses: CallArgList, - _defs: CallRetList, - _clobbers: PRegSet, - _tmp: Writable, - _callee_conv: isa::CallConv, - _caller_conv: isa::CallConv, - _callee_pop_size: u32, - ) -> SmallVec<[Inst; 2]> { + fn gen_call(_dest: &CallDest, _tmp: Writable, _info: CallInfo<()>) -> SmallVec<[Inst; 2]> { unreachable!(); } diff --git a/cranelift/codegen/src/isa/s390x/inst.isle b/cranelift/codegen/src/isa/s390x/inst.isle index f4a88a254343..36af4ba75cc5 100644 --- a/cranelift/codegen/src/isa/s390x/inst.isle +++ b/cranelift/codegen/src/isa/s390x/inst.isle @@ -1014,6 +1014,15 @@ ;; machine at this program point. (Unwind (inst UnwindInst)) + + ;; Pseudo-instruction used for `tls_value` to call the libcall of the same + ;; name. + (ElfTlsGetOffset + (tls_offset WritableReg) + (got Reg) + (got_offset Reg) + (link WritableReg) + (symbol BoxSymbolReloc)) )) ;; Primitive types used in instruction formats. @@ -2912,7 +2921,8 @@ (rule 1 (memcpy dst src (len_minus_one len)) (mvc (memarg_pair dst) (memarg_pair src) len)) (rule (memcpy dst src len) - (lib_call (lib_call_info_memcpy (load_addr dst) (load_addr src) (imm $I64 len)))) + (lib_call + (lib_call_info_memcpy (load_addr dst) (load_addr src) (imm $I64 len)))) ;; Prepare a stack copy of a single (oversized) argument. (decl copy_to_buffer (MemArg ABIArg Value) InstOutput) @@ -3605,18 +3615,12 @@ (type LibCallInfo extern (enum)) -(decl lib_call_info_memcpy (Reg Reg Reg) LibCallInfo) +(decl lib_call_info_memcpy (Reg Reg Reg) BoxCallInfo) (extern constructor lib_call_info_memcpy lib_call_info_memcpy) -(decl lib_call_info_tls_get_offset (WritableReg Reg Reg SymbolReloc) LibCallInfo) -(extern constructor lib_call_info_tls_get_offset lib_call_info_tls_get_offset) - -(decl lib_call_info (LibCallInfo) BoxCallInfo) -(extern constructor lib_call_info lib_call_info) - -(decl lib_call (LibCallInfo) SideEffectNoResult) -(rule (lib_call libcall) - (call_impl (writable_link_reg) (lib_call_info libcall))) +(decl lib_call (BoxCallInfo) SideEffectNoResult) +(rule (lib_call info) + (call_impl (writable_link_reg) info)) ;; Helpers for generating vector pack and unpack instructions ;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/s390x/inst/emit.rs b/cranelift/codegen/src/isa/s390x/inst/emit.rs index 7d9fcc3e7e02..9fe3fed81875 100644 --- a/cranelift/codegen/src/isa/s390x/inst/emit.rs +++ b/cranelift/codegen/src/isa/s390x/inst/emit.rs @@ -1,6 +1,6 @@ //! S390x ISA: binary code emission. -use crate::ir::{self, MemFlags, TrapCode}; +use crate::ir::{self, LibCall, MemFlags, TrapCode}; use crate::isa::s390x::inst::*; use crate::isa::s390x::settings as s390x_settings; use cranelift_control::ControlPlane; @@ -3267,15 +3267,6 @@ impl Inst { // works correctly. sink.add_reloc_at_offset(2, Reloc::S390xPLTRel32Dbl, &info.dest, 2); - // Add relocation for TLS libcalls to enable linker optimizations. - match &info.tls_symbol { - None => {} - Some(SymbolReloc::TlsGd { name }) => { - sink.add_reloc(Reloc::S390xTlsGdCall, name, 0) - } - _ => unreachable!(), - } - if let Some(s) = state.take_stack_map() { let offset = sink.cur_offset() + 6; sink.push_user_stack_map(state, offset, s); @@ -3288,7 +3279,6 @@ impl Inst { } &Inst::CallInd { link, ref info } => { debug_assert_eq!(link.to_reg(), gpr(14)); - let rn = info.rn; if let Some(s) = state.take_stack_map() { let offset = sink.cur_offset() + 2; @@ -3296,7 +3286,7 @@ impl Inst { } let opcode = 0x0d; // BASR - put(sink, &enc_rr(opcode, link.to_reg(), rn)); + put(sink, &enc_rr(opcode, link.to_reg(), info.dest)); sink.add_call_site(); state.nominal_sp_offset -= info.callee_pop_size; @@ -3316,7 +3306,7 @@ impl Inst { sink.add_call_site(); } &Inst::ReturnCallInd { ref info } => { - let mut rn = info.rn; + let mut rn = info.dest; for inst in S390xMachineDeps::gen_tail_epilogue( state.frame_layout(), info.callee_pop_size, @@ -3329,6 +3319,26 @@ impl Inst { put(sink, &enc_rr(opcode, gpr(15), rn)); sink.add_call_site(); } + &Inst::ElfTlsGetOffset { + ref symbol, link, .. + } => { + debug_assert_eq!(link.to_reg(), gpr(14)); + + let opcode = 0xc05; // BRASL + + // Add relocation for target function. This has to be done + // *before* the S390xTlsGdCall, to ensure linker relaxation + // works correctly. + let dest = ExternalName::LibCall(LibCall::ElfTlsGetOffset); + sink.add_reloc_at_offset(2, Reloc::S390xPLTRel32Dbl, &dest, 2); + match &**symbol { + SymbolReloc::TlsGd { name } => sink.add_reloc(Reloc::S390xTlsGdCall, name, 0), + _ => unreachable!(), + } + + put(sink, &enc_ril_b(opcode, gpr(14), 0)); + sink.add_call_site(); + } &Inst::Args { .. } => {} &Inst::Rets { .. } => {} &Inst::Ret { link } => { diff --git a/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs b/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs index 9108b1fc0e7c..159301f736b8 100644 --- a/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs @@ -1,7 +1,6 @@ use crate::ir::{MemFlags, TrapCode}; use crate::isa::s390x::inst::*; use crate::isa::s390x::settings as s390x_settings; -use smallvec::smallvec; #[cfg(test)] fn simm20_zero() -> SImm20 { @@ -6984,16 +6983,10 @@ fn test_s390x_binemit() { insns.push(( Inst::Call { link: writable_gpr(14), - info: Box::new(CallInfo { - dest: ExternalName::testcase("test0"), - uses: smallvec![], - defs: smallvec![], - clobbers: PRegSet::empty(), - callee_pop_size: 0, - caller_callconv: CallConv::SystemV, - callee_callconv: CallConv::SystemV, - tls_symbol: None, - }), + info: Box::new(CallInfo::empty( + ExternalName::testcase("test0"), + CallConv::SystemV, + )), }, "C0E500000000", "brasl %r14, %test0", @@ -7002,15 +6995,7 @@ fn test_s390x_binemit() { insns.push(( Inst::CallInd { link: writable_gpr(14), - info: Box::new(CallIndInfo { - rn: gpr(1), - uses: smallvec![], - defs: smallvec![], - clobbers: PRegSet::empty(), - callee_pop_size: 0, - caller_callconv: CallConv::SystemV, - callee_callconv: CallConv::SystemV, - }), + info: Box::new(CallInfo::empty(gpr(1), CallConv::SystemV)), }, "0DE1", "basr %r14, %r1", diff --git a/cranelift/codegen/src/isa/s390x/inst/mod.rs b/cranelift/codegen/src/isa/s390x/inst/mod.rs index 763c35a51ece..bccd0057bf62 100644 --- a/cranelift/codegen/src/isa/s390x/inst/mod.rs +++ b/cranelift/codegen/src/isa/s390x/inst/mod.rs @@ -34,47 +34,11 @@ pub use crate::isa::s390x::lower::isle::generated_code::{ VecUnaryOp, }; -/// Additional information for (direct) Call instructions, left out of line to lower the size of -/// the Inst enum. -#[derive(Clone, Debug)] -pub struct CallInfo { - pub dest: ExternalName, - pub uses: CallArgList, - pub defs: CallRetList, - pub clobbers: PRegSet, - pub callee_pop_size: u32, - pub caller_callconv: CallConv, - pub callee_callconv: CallConv, - pub tls_symbol: Option, -} - -/// Additional information for CallInd instructions, left out of line to lower the size of the Inst -/// enum. -#[derive(Clone, Debug)] -pub struct CallIndInfo { - pub rn: Reg, - pub uses: CallArgList, - pub defs: CallRetList, - pub clobbers: PRegSet, - pub callee_pop_size: u32, - pub caller_callconv: CallConv, - pub callee_callconv: CallConv, -} - /// Additional information for (direct) ReturnCall instructions, left out of line to lower the size of /// the Inst enum. #[derive(Clone, Debug)] -pub struct ReturnCallInfo { - pub dest: ExternalName, - pub uses: CallArgList, - pub callee_pop_size: u32, -} - -/// Additional information for ReturnCallInd instructions, left out of line to lower the size of the Inst -/// enum. -#[derive(Clone, Debug)] -pub struct ReturnCallIndInfo { - pub rn: Reg, +pub struct ReturnCallInfo { + pub dest: T, pub uses: CallArgList, pub callee_pop_size: u32, } @@ -267,7 +231,8 @@ impl Inst { | Inst::LoadAddr { .. } | Inst::Loop { .. } | Inst::CondBreak { .. } - | Inst::Unwind { .. } => InstructionSet::Base, + | Inst::Unwind { .. } + | Inst::ElfTlsGetOffset { .. } => InstructionSet::Base, // These depend on the opcode Inst::AluRRR { alu_op, .. } => match alu_op { @@ -908,7 +873,7 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor {} - Inst::Call { link, info } => { + Inst::Call { link, info, .. } => { let CallInfo { uses, defs, @@ -927,14 +892,14 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor { - let CallIndInfo { - rn, + let CallInfo { + dest, uses, defs, clobbers, .. } = &mut **info; - collector.reg_use(rn); + collector.reg_use(dest); for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); } @@ -953,12 +918,28 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor { - let ReturnCallIndInfo { rn, uses, .. } = &mut **info; - collector.reg_use(rn); + let ReturnCallInfo { dest, uses, .. } = &mut **info; + collector.reg_use(dest); for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); } } + Inst::ElfTlsGetOffset { + tls_offset, + got, + got_offset, + link, + .. + } => { + collector.reg_fixed_use(got, gpr(12)); + collector.reg_fixed_use(got_offset, gpr(2)); + collector.reg_fixed_def(tls_offset, gpr(2)); + + let mut clobbers = S390xMachineDeps::get_regs_clobbered_by_call(CallConv::SystemV); + clobbers.add(link.to_reg().to_real_reg().unwrap().into()); + clobbers.remove(gpr_preg(2)); + collector.reg_clobbers(clobbers); + } Inst::Args { args } => { for ArgPair { vreg, preg } in args { collector.reg_fixed_def(vreg, *preg); @@ -1082,8 +1063,9 @@ impl MachInst for Inst { // registers. match self { &Inst::Args { .. } => false, - &Inst::Call { ref info, .. } => info.caller_callconv != info.callee_callconv, - &Inst::CallInd { ref info, .. } => info.caller_callconv != info.callee_callconv, + &Inst::Call { ref info, .. } => info.caller_conv != info.callee_conv, + &Inst::CallInd { ref info, .. } => info.caller_conv != info.callee_conv, + &Inst::ElfTlsGetOffset { .. } => false, _ => true, } } @@ -3159,15 +3141,8 @@ impl Inst { format!("slgfi {}, {}", show_reg(stack_reg()), size) } } - &Inst::Call { link, ref info, .. } => { + &Inst::Call { link, ref info } => { let link = link.to_reg(); - let tls_symbol = match &info.tls_symbol { - None => "".to_string(), - Some(SymbolReloc::TlsGd { name }) => { - format!(":tls_gdcall:{}", name.display(None)) - } - _ => unreachable!(), - }; let callee_pop_size = if info.callee_pop_size > 0 { format!(" ; callee_pop_size {}", info.callee_pop_size) } else { @@ -3175,16 +3150,15 @@ impl Inst { }; debug_assert_eq!(link, gpr(14)); format!( - "brasl {}, {}{}{}", + "brasl {}, {}{}", show_reg(link), info.dest.display(None), - tls_symbol, callee_pop_size ) } &Inst::CallInd { link, ref info, .. } => { let link = link.to_reg(); - let rn = pretty_print_reg(info.rn); + let rn = pretty_print_reg(info.dest); let callee_pop_size = if info.callee_pop_size > 0 { format!(" ; callee_pop_size {}", info.callee_pop_size) } else { @@ -3193,7 +3167,7 @@ impl Inst { debug_assert_eq!(link, gpr(14)); format!("basr {}, {}{}", show_reg(link), rn, callee_pop_size) } - &Inst::ReturnCall { ref info, .. } => { + &Inst::ReturnCall { ref info } => { let callee_pop_size = if info.callee_pop_size > 0 { format!(" ; callee_pop_size {}", info.callee_pop_size) } else { @@ -3201,8 +3175,8 @@ impl Inst { }; format!("return_call {}{}", info.dest.display(None), callee_pop_size) } - &Inst::ReturnCallInd { ref info, .. } => { - let rn = pretty_print_reg(info.rn); + &Inst::ReturnCallInd { ref info } => { + let rn = pretty_print_reg(info.dest); let callee_pop_size = if info.callee_pop_size > 0 { format!(" ; callee_pop_size {}", info.callee_pop_size) } else { @@ -3210,6 +3184,21 @@ impl Inst { }; format!("return_call_ind {rn}{callee_pop_size}") } + &Inst::ElfTlsGetOffset { + ref symbol, + ref link, + .. + } => { + let link = link.to_reg(); + let dest = match &**symbol { + SymbolReloc::TlsGd { name } => { + format!("tls_gdcall:{}", name.display(None)) + } + _ => unreachable!(), + }; + debug_assert_eq!(link, gpr(14)); + format!("brasl {}, {}", show_reg(link), dest) + } &Inst::Args { ref args } => { let mut s = "args".to_string(); for arg in args { diff --git a/cranelift/codegen/src/isa/s390x/lower.isle b/cranelift/codegen/src/isa/s390x/lower.isle index d0efcd25fc1b..225918a22bac 100644 --- a/cranelift/codegen/src/isa/s390x/lower.isle +++ b/cranelift/codegen/src/isa/s390x/lower.isle @@ -409,6 +409,15 @@ (res_hi Reg (add_reg $I64 res_hi_3 (add_reg $I64 res_hi_2 res_hi_1)))) (mov_to_vec128 $I64X2 res_hi res_lo))) +;; Special-case the lowering of a 128-bit multiply where the operands are sign +;; or zero extended. This maps directly to `umul_wide` and `smul_wide`. +(rule 16 (lower (has_type $I128 (imul (uextend x) (uextend y)))) + (let ((pair RegPair (umul_wide (put_in_reg_zext64 x) (put_in_reg_zext64 y)))) + (mov_to_vec128 $I64X2 (regpair_hi pair) (regpair_lo pair)))) + +(rule 16 (lower (has_type $I128 (imul (sextend x) (sextend y)))) + (let ((pair RegPair (smul_wide (put_in_reg_sext64 x) (put_in_reg_sext64 y)))) + (mov_to_vec128 $I64X2 (regpair_hi pair) (regpair_lo pair)))) ;;;; Rules for `umulhi` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2269,10 +2278,13 @@ (decl lib_call_tls_get_offset (Reg Reg SymbolReloc) Reg) (rule (lib_call_tls_get_offset got got_offset symbol) (let ((tls_offset WritableReg (temp_writable_reg $I64)) - (libcall LibCallInfo (lib_call_info_tls_get_offset tls_offset got got_offset symbol)) - (_ InstOutput (side_effect (lib_call libcall)))) + (_ Unit (abi_for_elf_tls_get_offset)) + (_ Unit (emit (MInst.ElfTlsGetOffset tls_offset got got_offset (writable_link_reg) symbol)))) tls_offset)) +(decl abi_for_elf_tls_get_offset () Unit) +(extern constructor abi_for_elf_tls_get_offset abi_for_elf_tls_get_offset) + ;; Helper to extract the current thread pointer from %a0/%a1. (decl thread_pointer () Reg) (rule (thread_pointer) diff --git a/cranelift/codegen/src/isa/s390x/lower/isle.rs b/cranelift/codegen/src/isa/s390x/lower/isle.rs index 42c769536ca6..6d219da85e17 100644 --- a/cranelift/codegen/src/isa/s390x/lower/isle.rs +++ b/cranelift/codegen/src/isa/s390x/lower/isle.rs @@ -7,13 +7,12 @@ use crate::ir::ExternalName; // Types that the generated ISLE code uses via `use super::*`. use crate::isa::s390x::abi::{S390xMachineDeps, REG_SAVE_AREA_SIZE}; use crate::isa::s390x::inst::{ - gpr, stack_reg, writable_gpr, zero_reg, CallIndInfo, CallInfo, Cond, Inst as MInst, LaneOrder, - MemArg, MemArgPair, RegPair, ReturnCallIndInfo, ReturnCallInfo, SymbolReloc, UImm12, - UImm16Shifted, UImm32Shifted, WritableRegPair, + gpr, stack_reg, writable_gpr, zero_reg, Cond, Inst as MInst, LaneOrder, MemArg, MemArgPair, + RegPair, ReturnCallInfo, SymbolReloc, UImm12, UImm16Shifted, UImm32Shifted, WritableRegPair, }; use crate::isa::s390x::S390xBackend; use crate::machinst::isle::*; -use crate::machinst::{MachLabel, Reg}; +use crate::machinst::{CallInfo, MachLabel, Reg}; use crate::{ ir::{ condcodes::*, immediates::*, types::*, ArgumentExtension, ArgumentPurpose, AtomicRmwOp, @@ -33,18 +32,10 @@ use std::boxed::Box; use std::cell::Cell; use std::vec::Vec; -/// Information describing a library call to be emitted. -pub struct LibCallInfo { - libcall: LibCall, - uses: CallArgList, - defs: CallRetList, - tls_symbol: Option, -} - -type BoxCallInfo = Box; -type BoxCallIndInfo = Box; -type BoxReturnCallInfo = Box; -type BoxReturnCallIndInfo = Box; +type BoxCallInfo = Box>; +type BoxCallIndInfo = Box>; +type BoxReturnCallInfo = Box>; +type BoxReturnCallIndInfo = Box>; type VecMachLabel = Vec; type BoxExternalName = Box; type BoxSymbolReloc = Box; @@ -271,56 +262,21 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> { fn abi_call_info( &mut self, abi: Sig, - name: ExternalName, + dest: ExternalName, uses: &CallArgList, defs: &CallRetList, ) -> BoxCallInfo { - let sig_data = &self.lower_ctx.sigs()[abi]; - // Get clobbers: all caller-saves. These may include return value - // regs, which we will remove from the clobber set later. - let clobbers = S390xMachineDeps::get_regs_clobbered_by_call(sig_data.call_conv()); - let callee_pop_size = if sig_data.call_conv() == CallConv::Tail { - sig_data.sized_stack_arg_space() as u32 - } else { - 0 - }; - Box::new(CallInfo { - dest: name.clone(), - uses: uses.clone(), - defs: defs.clone(), - clobbers, - callee_pop_size, - caller_callconv: self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()), - callee_callconv: self.lower_ctx.sigs()[abi].call_conv(), - tls_symbol: None, - }) + Box::new(self.abi_call_info_no_dest(abi, uses, defs).map(|()| dest)) } fn abi_call_ind_info( &mut self, abi: Sig, - target: Reg, + dest: Reg, uses: &CallArgList, defs: &CallRetList, ) -> BoxCallIndInfo { - let sig_data = &self.lower_ctx.sigs()[abi]; - // Get clobbers: all caller-saves. These may include return value - // regs, which we will remove from the clobber set later. - let clobbers = S390xMachineDeps::get_regs_clobbered_by_call(sig_data.call_conv()); - let callee_pop_size = if sig_data.call_conv() == CallConv::Tail { - sig_data.sized_stack_arg_space() as u32 - } else { - 0 - }; - Box::new(CallIndInfo { - rn: target, - uses: uses.clone(), - defs: defs.clone(), - clobbers, - callee_pop_size, - caller_callconv: self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()), - callee_callconv: self.lower_ctx.sigs()[abi].call_conv(), - }) + Box::new(self.abi_call_info_no_dest(abi, uses, defs).map(|()| dest)) } fn abi_return_call_info( @@ -346,16 +302,32 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> { ) -> BoxReturnCallIndInfo { let sig_data = &self.lower_ctx.sigs()[abi]; let callee_pop_size = sig_data.sized_stack_arg_space() as u32; - Box::new(ReturnCallIndInfo { - rn: target, + Box::new(ReturnCallInfo { + dest: target, uses: uses.clone(), callee_pop_size, }) } - fn lib_call_info_memcpy(&mut self, dst: Reg, src: Reg, len: Reg) -> LibCallInfo { - LibCallInfo { - libcall: LibCall::Memcpy, + fn lib_call_info_memcpy( + &mut self, + dst: Reg, + src: Reg, + len: Reg, + ) -> Box> { + let caller_conv = self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()); + let callee_conv = CallConv::for_libcall(&self.backend.flags, caller_conv); + + // Clobbers are defined by the calling convention. We will remove return value regs later. + let clobbers = S390xMachineDeps::get_regs_clobbered_by_call(callee_conv); + + // Libcalls only require the register save area. + self.lower_ctx + .abi_mut() + .accumulate_outgoing_args_size(REG_SAVE_AREA_SIZE); + + Box::new(CallInfo { + dest: ExternalName::LibCall(LibCall::Memcpy), uses: smallvec![ CallArgPair { vreg: dst, @@ -371,59 +343,17 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> { }, ], defs: smallvec![], - tls_symbol: None, - } - } - - fn lib_call_info_tls_get_offset( - &mut self, - tls_offset: WritableReg, - got: Reg, - got_offset: Reg, - tls_symbol: &SymbolReloc, - ) -> LibCallInfo { - LibCallInfo { - libcall: LibCall::ElfTlsGetOffset, - uses: smallvec![ - CallArgPair { - vreg: got, - preg: gpr(12), - }, - CallArgPair { - vreg: got_offset, - preg: gpr(2), - }, - ], - defs: smallvec![CallRetPair { - vreg: tls_offset, - preg: gpr(2), - },], - tls_symbol: Some(tls_symbol.clone()), - } + clobbers, + caller_conv, + callee_conv, + callee_pop_size: 0, + }) } - fn lib_call_info(&mut self, info: &LibCallInfo) -> BoxCallInfo { - let caller_callconv = self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()); - let callee_callconv = CallConv::for_libcall(&self.backend.flags, caller_callconv); - - // Clobbers are defined by the calling convention. We will remove return value regs later. - let clobbers = S390xMachineDeps::get_regs_clobbered_by_call(callee_callconv); - - // Libcalls only require the register save area. + fn abi_for_elf_tls_get_offset(&mut self) { self.lower_ctx .abi_mut() .accumulate_outgoing_args_size(REG_SAVE_AREA_SIZE); - - Box::new(CallInfo { - dest: ExternalName::LibCall(info.libcall), - uses: info.uses.clone(), - defs: info.defs.clone(), - clobbers, - callee_pop_size: 0, - caller_callconv, - callee_callconv, - tls_symbol: info.tls_symbol.clone(), - }) } #[inline] @@ -1098,6 +1028,34 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> { } } +impl IsleContext<'_, '_, MInst, S390xBackend> { + fn abi_call_info_no_dest( + &mut self, + abi: Sig, + uses: &CallArgList, + defs: &CallRetList, + ) -> CallInfo<()> { + let sig_data = &self.lower_ctx.sigs()[abi]; + // Get clobbers: all caller-saves. These may include return value + // regs, which we will remove from the clobber set later. + let clobbers = S390xMachineDeps::get_regs_clobbered_by_call(sig_data.call_conv()); + let callee_pop_size = if sig_data.call_conv() == CallConv::Tail { + sig_data.sized_stack_arg_space() as u32 + } else { + 0 + }; + CallInfo { + dest: (), + uses: uses.clone(), + defs: defs.clone(), + clobbers, + callee_pop_size, + caller_conv: self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()), + callee_conv: self.lower_ctx.sigs()[abi].call_conv(), + } + } +} + /// Lane order to be used for a given calling convention. #[inline] fn lane_order_for_call_conv(call_conv: CallConv) -> LaneOrder { diff --git a/cranelift/codegen/src/isa/winch.rs b/cranelift/codegen/src/isa/winch.rs new file mode 100644 index 000000000000..c37ddd373ee0 --- /dev/null +++ b/cranelift/codegen/src/isa/winch.rs @@ -0,0 +1,22 @@ +use crate::machinst::{ABIArg, ABIArgSlot, ArgsAccumulator}; + +// Winch writes the first result to the highest offset, so we need to iterate through the +// args and adjust the offsets down. +pub(super) fn reverse_stack(mut args: ArgsAccumulator, next_stack: u32, uses_extension: bool) { + for arg in args.args_mut() { + if let ABIArg::Slots { slots, .. } = arg { + for slot in slots.iter_mut() { + if let ABIArgSlot::Stack { offset, ty, .. } = slot { + let size = if uses_extension { + i64::from(std::cmp::max(ty.bytes(), 8)) + } else { + i64::from(ty.bytes()) + }; + *offset = i64::from(next_stack) - *offset - size; + } + } + } else { + unreachable!("Winch cannot handle {arg:?}"); + } + } +} diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs index 9d3c9fd55b92..9fc741bfd853 100644 --- a/cranelift/codegen/src/isa/x64/abi.rs +++ b/cranelift/codegen/src/isa/x64/abi.rs @@ -3,6 +3,7 @@ use crate::ir::{self, types, LibCall, MemFlags, Signature, TrapCode}; use crate::ir::{types::*, ExternalName}; use crate::isa; +use crate::isa::winch; use crate::isa::{unwind::UnwindInst, x64::inst::*, x64::settings as x64_settings, CallConv}; use crate::machinst::abi::*; use crate::machinst::*; @@ -389,23 +390,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { // Winch writes the first result to the highest offset, so we need to iterate through the // args and adjust the offsets down. if call_conv == CallConv::Winch && args_or_rets == ArgsOrRets::Rets { - for arg in args.args_mut() { - if let ABIArg::Slots { slots, .. } = arg { - for slot in slots.iter_mut() { - if let ABIArgSlot::Stack { offset, ty, .. } = slot { - let size = if uses_extension { - i64::from(std::cmp::max(ty.bytes(), 8)) - } else { - i64::from(ty.bytes()) - }; - - *offset = i64::from(next_stack) - *offset - size; - } - } - } else { - unreachable!("Winch cannot handle {arg:?}"); - } - } + winch::reverse_stack(args, next_stack, uses_extension); } next_stack = align_to(next_stack, 16); @@ -617,16 +602,12 @@ impl ABIMachineSpec for X64ABIMachineSpec { Writable::from_reg(regs::rax()), )); insts.push(Inst::CallKnown { - dest: ExternalName::LibCall(LibCall::Probestack), - info: Some(Box::new(CallInfo { - // No need to include arg here: we are post-regalloc - // so no constraints will be seen anyway. - uses: smallvec![], - defs: smallvec![], - clobbers: PRegSet::empty(), - callee_pop_size: 0, - callee_conv: CallConv::Probestack, - })), + // No need to include arg here: we are post-regalloc + // so no constraints will be seen anyway. + info: Box::new(CallInfo::empty( + ExternalName::LibCall(LibCall::Probestack), + CallConv::Probestack, + )), }); } @@ -822,27 +803,12 @@ impl ABIMachineSpec for X64ABIMachineSpec { } /// Generate a call instruction/sequence. - fn gen_call( - dest: &CallDest, - uses: CallArgList, - defs: CallRetList, - clobbers: PRegSet, - tmp: Writable, - callee_conv: isa::CallConv, - _caller_conv: isa::CallConv, - callee_pop_size: u32, - ) -> SmallVec<[Self::I; 2]> { + fn gen_call(dest: &CallDest, tmp: Writable, info: CallInfo<()>) -> SmallVec<[Self::I; 2]> { let mut insts = SmallVec::new(); match dest { &CallDest::ExtName(ref name, RelocDistance::Near) => { - insts.push(Inst::call_known( - name.clone(), - uses, - defs, - clobbers, - callee_pop_size, - callee_conv, - )); + let info = Box::new(info.map(|()| name.clone())); + insts.push(Inst::call_known(info)); } &CallDest::ExtName(ref name, RelocDistance::Far) => { insts.push(Inst::LoadExtName { @@ -851,24 +817,12 @@ impl ABIMachineSpec for X64ABIMachineSpec { offset: 0, distance: RelocDistance::Far, }); - insts.push(Inst::call_unknown( - RegMem::reg(tmp.to_reg()), - uses, - defs, - clobbers, - callee_pop_size, - callee_conv, - )); + let info = Box::new(info.map(|()| RegMem::reg(tmp.to_reg()))); + insts.push(Inst::call_unknown(info)); } &CallDest::Reg(reg) => { - insts.push(Inst::call_unknown( - RegMem::reg(reg), - uses, - defs, - clobbers, - callee_pop_size, - callee_conv, - )); + let info = Box::new(info.map(|()| RegMem::reg(reg))); + insts.push(Inst::call_unknown(info)); } } insts @@ -898,10 +852,9 @@ impl ABIMachineSpec for X64ABIMachineSpec { distance: RelocDistance::Far, }); let callee_pop_size = 0; - insts.push(Inst::call_unknown( - RegMem::reg(temp2.to_reg()), - /* uses = */ - smallvec![ + insts.push(Inst::call_unknown(Box::new(CallInfo { + dest: RegMem::reg(temp2.to_reg()), + uses: smallvec![ CallArgPair { vreg: dst, preg: arg0 @@ -915,11 +868,12 @@ impl ABIMachineSpec for X64ABIMachineSpec { preg: arg2 }, ], - /* defs = */ smallvec![], - /* clobbers = */ Self::get_regs_clobbered_by_call(call_conv), + defs: smallvec![], + clobbers: Self::get_regs_clobbered_by_call(call_conv), callee_pop_size, - call_conv, - )); + callee_conv: call_conv, + caller_conv: call_conv, + }))); insts } @@ -1028,14 +982,17 @@ impl X64CallSite { // Finally, do the actual tail call! let dest = self.dest().clone(); - let info = Box::new(ReturnCallInfo { - new_stack_arg_size, - uses: self.take_uses(), - tmp: ctx.temp_writable_gpr(), - }); + let uses = self.take_uses(); + let tmp = ctx.temp_writable_gpr(); match dest { CallDest::ExtName(callee, RelocDistance::Near) => { - ctx.emit(Inst::ReturnCallKnown { callee, info }); + let info = Box::new(ReturnCallInfo { + dest: callee, + uses, + tmp, + new_stack_arg_size, + }); + ctx.emit(Inst::ReturnCallKnown { info }); } CallDest::ExtName(callee, RelocDistance::Far) => { let tmp2 = ctx.temp_writable_gpr(); @@ -1045,15 +1002,23 @@ impl X64CallSite { offset: 0, distance: RelocDistance::Far, }); - ctx.emit(Inst::ReturnCallUnknown { - callee: tmp2.to_reg().to_reg(), - info, + let info = Box::new(ReturnCallInfo { + dest: tmp2.to_reg().to_reg().into(), + uses, + tmp, + new_stack_arg_size, + }); + ctx.emit(Inst::ReturnCallUnknown { info }); + } + CallDest::Reg(callee) => { + let info = Box::new(ReturnCallInfo { + dest: callee.into(), + uses, + tmp, + new_stack_arg_size, }); + ctx.emit(Inst::ReturnCallUnknown { info }); } - CallDest::Reg(callee) => ctx.emit(Inst::ReturnCallUnknown { - callee: callee.into(), - info, - }), } } } diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index 8e42e5c5cbe3..6588221113eb 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -99,6 +99,21 @@ (dst_lo WritableGpr) (dst_hi WritableGpr)) + ;; Same as `Mul`, but for the BMI2 `mulx` instruction. This is different + ;; where the two `dst_*` registers can be arbitrary registers and it + ;; is always unsigned multiplication. Note that this instruction does + ;; not modify or read flags. + ;; + ;; Note that `dst_hi` here is always a valid register but `dst_lo` + ;; is allowed to be `invalid_reg` to indicate that only the high + ;; bits are desired. If `dst_lo` is invalid then the instruction itself + ;; will only define `dst_hi`. + (MulX (size OperandSize) + (src1 Gpr) + (src2 GprMem) + (dst_lo WritableGpr) + (dst_hi WritableGpr)) + ;; Same as `Mul` but the 16-bit multiplication result is stored in `AX`. (Mul8 (signed bool) (src1 Gpr) @@ -531,20 +546,16 @@ ;; Control flow instructions. ;; Direct call: call simm32. - (CallKnown (dest ExternalName) - (info BoxCallInfo)) + (CallKnown (info BoxCallInfo)) ;; Indirect call: callq (reg mem) - (CallUnknown (dest RegMem) - (info BoxCallInfo)) + (CallUnknown (info BoxCallIndInfo)) ;; Tail call to a direct destination. - (ReturnCallKnown (callee ExternalName) - (info BoxReturnCallInfo)) + (ReturnCallKnown (info BoxReturnCallInfo)) ;; Tail call to an indirect destination. - (ReturnCallUnknown (callee Reg) - (info BoxReturnCallInfo)) + (ReturnCallUnknown (info BoxReturnCallIndInfo)) ;; A pseudo-instruction that captures register arguments in vregs. (Args @@ -751,7 +762,9 @@ SFence)) (type BoxCallInfo extern (enum)) +(type BoxCallIndInfo extern (enum)) (type BoxReturnCallInfo extern (enum)) +(type BoxReturnCallIndInfo extern (enum)) ;; Get the `OperandSize` for a given `Type`, rounding smaller types up to 32 bits. (decl operand_size_of_type_32_64 (Type) OperandSize) @@ -2641,6 +2654,26 @@ (_ Unit (emit (MInst.Mul size signed src1 src2 dst_lo dst_hi)))) (value_gprs dst_lo dst_hi))) +;; Special case the `mulx` pattern with the BMI2 instruction set. +(rule 1 (x64_mul (ty_32_or_64 ty) $false src1 src2) + (if-let $true (use_bmi2)) + (let ((dst_lo WritableGpr (temp_writable_gpr)) + (dst_hi WritableGpr (temp_writable_gpr)) + (size OperandSize (raw_operand_size_of_type ty)) + (_ Unit (emit (MInst.MulX size src1 src2 dst_lo dst_hi)))) + (value_gprs dst_lo dst_hi))) + +(decl x64_mulx_hi (Type Gpr GprMem) Gpr) +(rule (x64_mulx_hi (ty_32_or_64 ty) src1 src2) + (let ((dst WritableGpr (temp_writable_gpr)) + (size OperandSize (raw_operand_size_of_type ty)) + (_ Unit (emit (MInst.MulX size src1 src2 (writable_invalid_gpr) dst)))) + dst)) + +;; Get the invalid register as writable +(decl writable_invalid_gpr () WritableGpr) +(extern constructor writable_invalid_gpr writable_invalid_gpr) + ;; Helper for creating `mul` instructions or `imul` instructions (depending ;; on `signed`) for 8-bit operands. (decl x64_mul8 (bool Gpr GprMem) Gpr) diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index a264dbd439a8..1bea0e560f93 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -682,6 +682,42 @@ pub(crate) fn emit( emit_simm(sink, imm_size, *src2 as u32); } + Inst::MulX { + size, + src1, + src2, + dst_lo, + dst_hi, + } => { + let src1 = src1.to_reg(); + let dst_lo = dst_lo.to_reg().to_reg(); + let dst_hi = dst_hi.to_reg().to_reg(); + debug_assert_eq!(src1, regs::rdx()); + let src2 = match src2.clone().to_reg_mem().clone() { + RegMem::Reg { reg } => { + RegisterOrAmode::Register(reg.to_real_reg().unwrap().hw_enc().into()) + } + RegMem::Mem { addr } => RegisterOrAmode::Amode(addr.finalize(state, sink)), + }; + + let dst_hi = dst_hi.to_real_reg().unwrap().hw_enc(); + let dst_lo = if dst_lo.is_invalid_sentinel() { + dst_hi + } else { + dst_lo.to_real_reg().unwrap().hw_enc() + }; + + VexInstruction::new() + .prefix(LegacyPrefixes::_F2) + .map(OpcodeMap::_0F38) + .w(*size == OperandSize::Size64) + .opcode(0xf6) + .reg(dst_hi) + .vvvv(dst_lo) + .rm(src2) + .encode(sink); + } + Inst::SignExtendData { size, src, dst } => { let src = src.to_reg(); let dst = dst.to_reg().to_reg(); @@ -1593,11 +1629,7 @@ pub(crate) fn emit( inst.emit(sink, info, state); } - Inst::CallKnown { - dest, - info: call_info, - .. - } => { + Inst::CallKnown { info: call_info } => { if let Some(s) = state.take_stack_map() { let offset = sink.cur_offset() + 5; sink.push_user_stack_map(state, offset, s); @@ -1606,29 +1638,24 @@ pub(crate) fn emit( sink.put1(0xE8); // The addend adjusts for the difference between the end of the instruction and the // beginning of the immediate field. - emit_reloc(sink, Reloc::X86CallPCRel4, &dest, -4); + emit_reloc(sink, Reloc::X86CallPCRel4, &call_info.dest, -4); sink.put4(0); sink.add_call_site(); // Reclaim the outgoing argument area that was released by the callee, to ensure that // StackAMode values are always computed from a consistent SP. - if let Some(call_info) = call_info { - if call_info.callee_pop_size > 0 { - Inst::alu_rmi_r( - OperandSize::Size64, - AluRmiROpcode::Sub, - RegMemImm::imm(call_info.callee_pop_size), - Writable::from_reg(regs::rsp()), - ) - .emit(sink, info, state); - } + if call_info.callee_pop_size > 0 { + Inst::alu_rmi_r( + OperandSize::Size64, + AluRmiROpcode::Sub, + RegMemImm::imm(call_info.callee_pop_size), + Writable::from_reg(regs::rsp()), + ) + .emit(sink, info, state); } } - Inst::ReturnCallKnown { - callee, - info: call_info, - } => { + Inst::ReturnCallKnown { info: call_info } => { emit_return_call_common_sequence(sink, info, state, &call_info); // Finally, jump to the callee! @@ -1639,16 +1666,13 @@ pub(crate) fn emit( sink.put1(0xE9); // The addend adjusts for the difference between the end of the instruction and the // beginning of the immediate field. - emit_reloc(sink, Reloc::X86CallPCRel4, &callee, -4); + emit_reloc(sink, Reloc::X86CallPCRel4, &call_info.dest, -4); sink.put4(0); sink.add_call_site(); } - Inst::ReturnCallUnknown { - callee, - info: call_info, - } => { - let callee = *callee; + Inst::ReturnCallUnknown { info: call_info } => { + let callee = call_info.dest; emit_return_call_common_sequence(sink, info, state, &call_info); @@ -1660,11 +1684,9 @@ pub(crate) fn emit( } Inst::CallUnknown { - dest, - info: call_info, - .. + info: call_info, .. } => { - let dest = dest.clone(); + let dest = call_info.dest.clone(); match dest { RegMem::Reg { reg } => { @@ -1704,16 +1726,14 @@ pub(crate) fn emit( // Reclaim the outgoing argument area that was released by the callee, to ensure that // StackAMode values are always computed from a consistent SP. - if let Some(call_info) = call_info { - if call_info.callee_pop_size > 0 { - Inst::alu_rmi_r( - OperandSize::Size64, - AluRmiROpcode::Sub, - RegMemImm::imm(call_info.callee_pop_size), - Writable::from_reg(regs::rsp()), - ) - .emit(sink, info, state); - } + if call_info.callee_pop_size > 0 { + Inst::alu_rmi_r( + OperandSize::Size64, + AluRmiROpcode::Sub, + RegMemImm::imm(call_info.callee_pop_size), + Writable::from_reg(regs::rsp()), + ) + .emit(sink, info, state); } } @@ -4373,11 +4393,11 @@ pub(crate) fn emit( /// arguments). /// /// * Move the return address into its stack slot. -fn emit_return_call_common_sequence( +fn emit_return_call_common_sequence( sink: &mut MachBuffer, info: &EmitInfo, state: &mut EmitState, - call_info: &ReturnCallInfo, + call_info: &ReturnCallInfo, ) { assert!( info.flags.preserve_frame_pointers(), diff --git a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs index cf2150fc356c..777d85830485 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs @@ -3747,14 +3747,10 @@ fn test_x64_emit() { // ======================================================== // CallKnown insns.push(( - Inst::call_known( + Inst::call_known(Box::new(CallInfo::empty( ExternalName::User(UserExternalNameRef::new(0)), - smallvec![], - smallvec![], - PRegSet::default(), - 0, CallConv::SystemV, - ), + ))), "E800000000", "call User(userextname0)", )); @@ -3762,14 +3758,7 @@ fn test_x64_emit() { // ======================================================== // CallUnknown fn call_unknown(rm: RegMem) -> Inst { - Inst::call_unknown( - rm, - smallvec![], - smallvec![], - PRegSet::default(), - 0, - CallConv::SystemV, - ) + Inst::call_unknown(Box::new(CallInfo::empty(rm, CallConv::SystemV))) } insns.push((call_unknown(RegMem::reg(rbp)), "FFD5", "call *%rbp")); diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index 7ab0654e54b2..a999c938d871 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -11,7 +11,6 @@ use crate::isa::{CallConv, FunctionAlignment}; use crate::{machinst::*, trace}; use crate::{settings, CodegenError, CodegenResult}; use alloc::boxed::Box; -use regalloc2::PRegSet; use smallvec::{smallvec, SmallVec}; use std::fmt::{self, Write}; use std::string::{String, ToString}; @@ -33,26 +32,12 @@ use args::*; // `Inst` is defined inside ISLE as `MInst`. We publicly re-export it here. pub use super::lower::isle::generated_code::MInst as Inst; -/// Out-of-line data for calls, to keep the size of `Inst` down. -#[derive(Clone, Debug)] -pub struct CallInfo { - /// Register uses of this call. - pub uses: CallArgList, - /// Register defs of this call. - pub defs: CallRetList, - /// Registers clobbered by this call, as per its calling convention. - pub clobbers: PRegSet, - /// The number of bytes that the callee will pop from the stack for the - /// caller, if any. (Used for popping stack arguments with the `tail` - /// calling convention.) - pub callee_pop_size: u32, - /// The calling convention of the callee. - pub callee_conv: CallConv, -} - /// Out-of-line data for return-calls, to keep the size of `Inst` down. #[derive(Clone, Debug)] -pub struct ReturnCallInfo { +pub struct ReturnCallInfo { + /// Where this call is going. + pub dest: T, + /// The size of the argument area for this return-call, potentially smaller than that of the /// caller, but never larger. pub new_stack_arg_size: u32, @@ -195,6 +180,8 @@ impl Inst { | Inst::GprToXmmVex { op, .. } | Inst::CvtIntToFloatVex { op, .. } | Inst::XmmCmpRmRVex { op, .. } => op.available_from(), + + Inst::MulX { .. } => smallvec![InstructionSet::BMI2], } } } @@ -539,45 +526,13 @@ impl Inst { Inst::Pop64 { dst } } - pub(crate) fn call_known( - dest: ExternalName, - uses: CallArgList, - defs: CallRetList, - clobbers: PRegSet, - callee_pop_size: u32, - callee_conv: CallConv, - ) -> Inst { - Inst::CallKnown { - dest, - info: Some(Box::new(CallInfo { - uses, - defs, - clobbers, - callee_pop_size, - callee_conv, - })), - } + pub(crate) fn call_known(info: Box>) -> Inst { + Inst::CallKnown { info } } - pub(crate) fn call_unknown( - dest: RegMem, - uses: CallArgList, - defs: CallRetList, - clobbers: PRegSet, - callee_pop_size: u32, - callee_conv: CallConv, - ) -> Inst { - dest.assert_regclass_is(RegClass::Int); - Inst::CallUnknown { - dest, - info: Some(Box::new(CallInfo { - uses, - defs, - clobbers, - callee_pop_size, - callee_conv, - })), - } + pub(crate) fn call_unknown(info: Box>) -> Inst { + info.dest.assert_regclass_is(RegClass::Int); + Inst::CallUnknown { info } } pub(crate) fn ret(stack_bytes_to_pop: u32) -> Inst { @@ -871,6 +826,26 @@ impl PrettyPrint for Inst { format!("{op} {src1}, {src2}, {dst_lo}, {dst_hi}") } + Inst::MulX { + size, + src1, + src2, + dst_lo, + dst_hi, + } => { + let src1 = pretty_print_reg(src1.to_reg(), size.to_bytes()); + let dst_hi = pretty_print_reg(dst_hi.to_reg().to_reg(), size.to_bytes()); + let dst_lo = if dst_lo.to_reg().is_invalid_sentinel() { + dst_hi.clone() + } else { + pretty_print_reg(dst_lo.to_reg().to_reg(), size.to_bytes()) + }; + let src2 = src2.pretty_print(size.to_bytes()); + let suffix = suffix_bwlq(*size); + let op = ljustify(format!("mulx{suffix}")); + format!("{op} {src1}, {src2}, {dst_lo}, {dst_hi}") + } + Inst::Mul8 { signed, src1, @@ -1661,26 +1636,26 @@ impl PrettyPrint for Inst { format!("{op} {dst}") } - Inst::CallKnown { dest, .. } => { + Inst::CallKnown { info } => { let op = ljustify("call".to_string()); - format!("{op} {dest:?}") + format!("{op} {:?}", info.dest) } - Inst::CallUnknown { dest, .. } => { - let dest = dest.pretty_print(8); + Inst::CallUnknown { info } => { + let dest = info.dest.pretty_print(8); let op = ljustify("call".to_string()); format!("{op} *{dest}") } - Inst::ReturnCallKnown { callee, info } => { + Inst::ReturnCallKnown { info } => { let ReturnCallInfo { uses, new_stack_arg_size, tmp, + dest, } = &**info; let tmp = pretty_print_reg(tmp.to_reg().to_reg(), 8); - let mut s = - format!("return_call_known {callee:?} ({new_stack_arg_size}) tmp={tmp}"); + let mut s = format!("return_call_known {dest:?} ({new_stack_arg_size}) tmp={tmp}"); for ret in uses { let preg = regs::show_reg(ret.preg); let vreg = pretty_print_reg(ret.vreg, 8); @@ -1689,13 +1664,14 @@ impl PrettyPrint for Inst { s } - Inst::ReturnCallUnknown { callee, info } => { + Inst::ReturnCallUnknown { info } => { let ReturnCallInfo { uses, new_stack_arg_size, tmp, + dest, } = &**info; - let callee = pretty_print_reg(*callee, 8); + let callee = pretty_print_reg(*dest, 8); let tmp = pretty_print_reg(tmp.to_reg().to_reg(), 8); let mut s = format!("return_call_unknown {callee} ({new_stack_arg_size}) tmp={tmp}"); @@ -2020,6 +1996,20 @@ fn x64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_def(dst); src1.get_operands(collector); } + Inst::MulX { + src1, + src2, + dst_lo, + dst_hi, + .. + } => { + if !dst_lo.to_reg().is_invalid_sentinel() { + collector.reg_def(dst_lo); + } + collector.reg_def(dst_hi); + collector.reg_fixed_use(src1, regs::rdx()); + src2.get_operands(collector); + } Inst::SignExtendData { size, src, dst } => { match size { OperandSize::Size8 => { @@ -2345,7 +2335,7 @@ fn x64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_early_def(tmp); } - Inst::CallKnown { dest, info, .. } => { + Inst::CallKnown { info } => { // Probestack is special and is only inserted after // regalloc, so we do not need to represent its ABI to the // register allocator. Assert that we don't alter that @@ -2354,8 +2344,9 @@ fn x64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { uses, defs, clobbers, + dest, .. - } = &mut **info.as_mut().expect("CallInfo is expected in this path"); + } = &mut **info; debug_assert_ne!(*dest, ExternalName::LibCall(LibCall::Probestack)); for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); @@ -2366,14 +2357,15 @@ fn x64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_clobbers(*clobbers); } - Inst::CallUnknown { info, dest, .. } => { + Inst::CallUnknown { info } => { let CallInfo { uses, defs, clobbers, callee_conv, + dest, .. - } = &mut **info.as_mut().expect("CallInfo is expected in this path"); + } = &mut **info; match dest { RegMem::Reg { reg } if *callee_conv == CallConv::Winch => { // TODO(https://github.com/bytecodealliance/regalloc2/issues/145): @@ -2413,25 +2405,29 @@ fn x64_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_clobbers(clobbers); } - Inst::ReturnCallKnown { callee, info } => { - let ReturnCallInfo { uses, tmp, .. } = &mut **info; + Inst::ReturnCallKnown { info } => { + let ReturnCallInfo { + dest, uses, tmp, .. + } = &mut **info; collector.reg_fixed_def(tmp, regs::r11()); // Same as in the `Inst::CallKnown` branch. - debug_assert_ne!(*callee, ExternalName::LibCall(LibCall::Probestack)); + debug_assert_ne!(*dest, ExternalName::LibCall(LibCall::Probestack)); for CallArgPair { vreg, preg } in uses { collector.reg_fixed_use(vreg, *preg); } } - Inst::ReturnCallUnknown { callee, info } => { - let ReturnCallInfo { uses, tmp, .. } = &mut **info; + Inst::ReturnCallUnknown { info } => { + let ReturnCallInfo { + dest, uses, tmp, .. + } = &mut **info; // TODO(https://github.com/bytecodealliance/regalloc2/issues/145): // This shouldn't be a fixed register constraint, but it's not clear how to // pick a register that won't be clobbered by the callee-save restore code // emitted with a return_call_indirect. r10 is caller-saved, so this should be // safe to use. - collector.reg_fixed_use(callee, regs::r10()); + collector.reg_fixed_use(dest, regs::r10()); collector.reg_fixed_def(tmp, regs::r11()); for CallArgPair { vreg, preg } in uses { diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle index c4a47e15c39b..7338e1cb3161 100644 --- a/cranelift/codegen/src/isa/x64/lower.isle +++ b/cranelift/codegen/src/isa/x64/lower.isle @@ -1001,21 +1001,29 @@ ;; 8-bit base case, needs a special instruction encoding and additionally ;; move sinkable loads to the right. -(rule -7 (lower (has_type $I8 (imul x y))) (x64_mul8 $false x y)) -(rule -6 (lower (has_type $I8 (imul (sinkable_load x) y))) (x64_mul8 $false y x)) +(rule -8 (lower (has_type $I8 (imul x y))) (x64_mul8 $false x y)) +(rule -7 (lower (has_type $I8 (imul (sinkable_load x) y))) (x64_mul8 $false y x)) ;; 16-to-64-bit base cases, same as above by moving sinkable loads to the right. -(rule -5 (lower (has_type (ty_int_ref_16_to_64 ty) (imul x y))) +(rule -6 (lower (has_type (ty_int_ref_16_to_64 ty) (imul x y))) (x64_imul ty x y)) -(rule -4 (lower (has_type (ty_int_ref_16_to_64 ty) (imul (sinkable_load x) y))) +(rule -5 (lower (has_type (ty_int_ref_16_to_64 ty) (imul (sinkable_load x) y))) (x64_imul ty y x)) ;; lift out constants to use 3-operand form -(rule -3 (lower (has_type (ty_int_ref_16_to_64 ty) (imul x (i32_from_iconst y)))) +(rule -4 (lower (has_type (ty_int_ref_16_to_64 ty) (imul x (i32_from_iconst y)))) (x64_imul_imm ty x y)) -(rule -2 (lower (has_type (ty_int_ref_16_to_64 ty) (imul (i32_from_iconst x) y))) +(rule -3 (lower (has_type (ty_int_ref_16_to_64 ty) (imul (i32_from_iconst x) y))) (x64_imul_imm ty y x)) +;; Special case widening multiplication from 8-to-16-bits with a single +;; instruction since the 8-bit-multiply places both the high and low halves in +;; the same register +(rule -2 (lower (has_type $I16 (imul (sextend x) (sextend y)))) + (x64_mul8 $true x y)) +(rule -2 (lower (has_type $I16 (imul (uextend x) (uextend y)))) + (x64_mul8 $false x y)) + ;; `i128`. (rule 2 (lower (has_type $I128 (imul x y))) @@ -4351,6 +4359,14 @@ (rule 1 (lower (umulhi a @ (value_type (ty_int_ref_16_to_64 ty)) b)) (value_regs_get_gpr (x64_mul ty $false a b) 1)) +;; The BMI2 instruction set introduced `mulx` which defines two registers but +;; if the two registers are the same then it only defines the upper bits. This +;; helps slightly reduce register pressure by ensuring only one register here is +;; clobbered. +(rule 2 (lower (umulhi a @ (value_type (ty_32_or_64 ty)) b)) + (if-let $true (use_bmi2)) + (x64_mulx_hi ty a b)) + ;; Rules for `smulhi` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule 0 (lower (smulhi a @ (value_type $I8) b)) diff --git a/cranelift/codegen/src/isa/x64/lower/isle.rs b/cranelift/codegen/src/isa/x64/lower/isle.rs index 54a5ad518519..3ed4e4cb4ccc 100644 --- a/cranelift/codegen/src/isa/x64/lower/isle.rs +++ b/cranelift/codegen/src/isa/x64/lower/isle.rs @@ -19,10 +19,10 @@ use crate::{ }, isa::x64::{ abi::X64CallSite, - inst::{args::*, regs, CallInfo, ReturnCallInfo}, + inst::{args::*, regs, ReturnCallInfo}, }, machinst::{ - isle::*, ArgPair, InsnInput, InstOutput, IsTailCall, MachAtomicRmwOp, MachInst, + isle::*, ArgPair, CallInfo, InsnInput, InstOutput, IsTailCall, MachAtomicRmwOp, MachInst, VCodeConstant, VCodeConstantData, }, }; @@ -34,8 +34,10 @@ use std::boxed::Box; /// call instruction is also used by Winch to emit calls, but the /// `Box` field is not used, it's only used by Cranelift. By making it /// optional, we reduce the number of heap allocations in Winch. -type BoxCallInfo = Option>; -type BoxReturnCallInfo = Box; +type BoxCallInfo = Box>; +type BoxCallIndInfo = Box>; +type BoxReturnCallInfo = Box>; +type BoxReturnCallIndInfo = Box>; type VecArgPair = Vec; pub struct SinkableLoad { @@ -988,6 +990,11 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> { let mask = -1i128 as u128; self.emit_u128_le_const(mask ^ (0xff << (hole_idx * 8))) } + + fn writable_invalid_gpr(&mut self) -> WritableGpr { + let reg = Gpr::new(self.invalid_reg()).unwrap(); + WritableGpr::from_reg(reg) + } } impl IsleContext<'_, '_, MInst, X64Backend> { diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs index 0b6371582b43..7545a6f14835 100644 --- a/cranelift/codegen/src/isa/x64/mod.rs +++ b/cranelift/codegen/src/isa/x64/mod.rs @@ -1,6 +1,6 @@ //! X86_64-bit Instruction Set Architecture. -pub use self::inst::{args, CallInfo, EmitInfo, EmitState, Inst}; +pub use self::inst::{args, EmitInfo, EmitState, Inst}; use super::{OwnedTargetIsa, TargetIsa}; use crate::dominator_tree::DominatorTree; diff --git a/cranelift/codegen/src/isa/x64/pcc.rs b/cranelift/codegen/src/isa/x64/pcc.rs index 6d9db277f309..51c599799a6e 100644 --- a/cranelift/codegen/src/isa/x64/pcc.rs +++ b/cranelift/codegen/src/isa/x64/pcc.rs @@ -252,6 +252,13 @@ pub(crate) fn check( dst_hi, ref src2, .. + } + | Inst::MulX { + size, + dst_lo, + dst_hi, + ref src2, + .. } => { match <&RegMem>::from(src2) { RegMem::Mem { ref addr } => { @@ -843,8 +850,14 @@ pub(crate) fn check( Inst::ReturnCallUnknown { .. } => Ok(()), - Inst::CallUnknown { ref dest, .. } - | Inst::JmpUnknown { + Inst::CallUnknown { ref info } => match <&RegMem>::from(&info.dest) { + RegMem::Mem { ref addr } => { + check_load(ctx, None, addr, vcode, I64, 64)?; + Ok(()) + } + RegMem::Reg { .. } => Ok(()), + }, + Inst::JmpUnknown { target: ref dest, .. } => match <&RegMem>::from(dest) { RegMem::Mem { ref addr } => { diff --git a/cranelift/codegen/src/lib.rs b/cranelift/codegen/src/lib.rs index 1c78ac9a3752..475014e0f550 100644 --- a/cranelift/codegen/src/lib.rs +++ b/cranelift/codegen/src/lib.rs @@ -60,7 +60,7 @@ pub use crate::machinst::buffer::{ MachTrap, OpenPatchRegion, PatchRegion, }; pub use crate::machinst::{ - CompiledCode, Final, MachBuffer, MachBufferFinalized, MachInst, MachInstEmit, + CallInfo, CompiledCode, Final, MachBuffer, MachBufferFinalized, MachInst, MachInstEmit, MachInstEmitState, MachLabel, RealReg, Reg, RelocDistance, TextSectionBuilder, VCodeConstantData, VCodeConstants, Writable, }; diff --git a/cranelift/codegen/src/machinst/abi.rs b/cranelift/codegen/src/machinst/abi.rs index 7760aef208dd..475f7c466f91 100644 --- a/cranelift/codegen/src/machinst/abi.rs +++ b/cranelift/codegen/src/machinst/abi.rs @@ -541,16 +541,7 @@ pub trait ABIMachineSpec { /// Generate a call instruction/sequence. This method is provided one /// temporary register to use to synthesize the called address, if needed. - fn gen_call( - dest: &CallDest, - uses: CallArgList, - defs: CallRetList, - clobbers: PRegSet, - tmp: Writable, - callee_conv: isa::CallConv, - caller_conv: isa::CallConv, - callee_pop_size: u32, - ) -> SmallVec<[Self::I; 2]>; + fn gen_call(dest: &CallDest, tmp: Writable, info: CallInfo<()>) -> SmallVec<[Self::I; 2]>; /// Generate a memcpy invocation. Used to set up struct /// args. Takes `src`, `dst` as read-only inputs and passes a temporary @@ -588,6 +579,56 @@ pub trait ABIMachineSpec { ) -> ir::ArgumentExtension; } +/// Out-of-line data for calls, to keep the size of `Inst` down. +#[derive(Clone, Debug)] +pub struct CallInfo { + /// Receiver of this call + pub dest: T, + /// Register uses of this call. + pub uses: CallArgList, + /// Register defs of this call. + pub defs: CallRetList, + /// Registers clobbered by this call, as per its calling convention. + pub clobbers: PRegSet, + /// The calling convention of the callee. + pub callee_conv: isa::CallConv, + /// The calling convention of the caller. + pub caller_conv: isa::CallConv, + /// The number of bytes that the callee will pop from the stack for the + /// caller, if any. (Used for popping stack arguments with the `tail` + /// calling convention.) + pub callee_pop_size: u32, +} + +impl CallInfo { + /// Creates an empty set of info with no clobbers/uses/etc with the + /// specified ABI + pub fn empty(dest: T, call_conv: isa::CallConv) -> CallInfo { + CallInfo { + dest, + uses: smallvec![], + defs: smallvec![], + clobbers: PRegSet::empty(), + caller_conv: call_conv, + callee_conv: call_conv, + callee_pop_size: 0, + } + } + + /// Change the `T` payload on this info to `U`. + pub fn map(self, f: impl FnOnce(T) -> U) -> CallInfo { + CallInfo { + dest: f(self.dest), + uses: self.uses, + defs: self.defs, + clobbers: self.clobbers, + caller_conv: self.caller_conv, + callee_conv: self.callee_conv, + callee_pop_size: self.callee_pop_size, + } + } +} + /// The id of an ABI signature within the `SigSet`. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Sig(u32); @@ -2345,13 +2386,16 @@ impl CallSite { // references to SP offsets.) for inst in M::gen_call( &self.dest, - uses, - defs, - clobbers, tmp, - call_conv, - self.caller_conv, - callee_pop_size, + CallInfo { + dest: (), + uses, + defs, + clobbers, + callee_conv: call_conv, + caller_conv: self.caller_conv, + callee_pop_size, + }, ) .into_iter() { diff --git a/cranelift/codegen/src/machinst/isle.rs b/cranelift/codegen/src/machinst/isle.rs index 3d5b2d96113b..7f12892a1ed4 100644 --- a/cranelift/codegen/src/machinst/isle.rs +++ b/cranelift/codegen/src/machinst/isle.rs @@ -724,6 +724,10 @@ macro_rules! isle_lower_prelude_methods { self.lower_ctx.add_range_fact(reg, bits, min, max); reg } + + fn value_is_unused(&mut self, val: Value) -> bool { + self.lower_ctx.value_is_unused(val) + } }; } diff --git a/cranelift/codegen/src/machinst/lower.rs b/cranelift/codegen/src/machinst/lower.rs index 86cda5d3e59b..17d384688aa6 100644 --- a/cranelift/codegen/src/machinst/lower.rs +++ b/cranelift/codegen/src/machinst/lower.rs @@ -13,6 +13,7 @@ use crate::ir::{ GlobalValue, GlobalValueData, Immediate, Inst, InstructionData, MemFlags, RelSourceLoc, Type, Value, ValueDef, ValueLabelAssignments, ValueLabelStart, }; +use crate::machinst::valueregs::InvalidSentinel; use crate::machinst::{ writable_value_regs, BackwardsInsnIndex, BlockIndex, BlockLoweringOrder, Callee, InsnIndex, LoweredBlock, MachLabel, Reg, SigSet, VCode, VCodeBuilder, VCodeConstant, VCodeConstantData, @@ -702,8 +703,9 @@ impl<'func, I: VCodeInst> Lower<'func, I> { debug_assert_eq!(temp_regs.len(), results.len()); for (regs, &result) in temp_regs.iter().zip(results) { let dsts = self.value_regs[result]; - debug_assert_eq!(regs.len(), dsts.len()); - for (&dst, &temp) in dsts.regs().iter().zip(regs.regs()) { + let mut regs = regs.regs().iter(); + for &dst in dsts.regs().iter() { + let temp = regs.next().copied().unwrap_or(Reg::invalid_sentinel()); trace!("set vreg alias: {result:?} = {dst:?}, lowering = {temp:?}"); self.vregs.set_vreg_alias(dst, temp); } @@ -1042,6 +1044,13 @@ impl<'func, I: VCodeInst> Lower<'func, I> { Ok(vcode) } + + pub fn value_is_unused(&self, val: Value) -> bool { + match self.value_ir_uses[val] { + ValueUseState::Unused => true, + _ => false, + } + } } /// Pre-analysis: compute `value_ir_uses`. See comment on diff --git a/cranelift/codegen/src/machinst/vcode.rs b/cranelift/codegen/src/machinst/vcode.rs index f2f9fe73b3ae..12c816530f04 100644 --- a/cranelift/codegen/src/machinst/vcode.rs +++ b/cranelift/codegen/src/machinst/vcode.rs @@ -884,30 +884,6 @@ impl VCode { // If this is a safepoint, compute a stack map // and pass it to the emit state. let stack_map_disasm = if self.insts[iix.index()].is_safepoint() { - let mut safepoint_slots: SmallVec<[SpillSlot; 8]> = smallvec![]; - // Find the contiguous range of - // (progpoint, allocation) safepoint slot - // records in `regalloc.safepoint_slots` - // for this instruction index. - let safepoint_slots_start = regalloc - .safepoint_slots - .binary_search_by(|(progpoint, _alloc)| { - if progpoint.inst() >= iix { - std::cmp::Ordering::Greater - } else { - std::cmp::Ordering::Less - } - }) - .unwrap_err(); - - for (_, alloc) in regalloc.safepoint_slots[safepoint_slots_start..] - .iter() - .take_while(|(progpoint, _)| progpoint.inst() == iix) - { - let slot = alloc.as_stack().unwrap(); - safepoint_slots.push(slot); - } - let (user_stack_map, user_stack_map_disasm) = { // The `user_stack_maps` is keyed by reverse // instruction index, so we must flip the @@ -1297,7 +1273,7 @@ impl RegallocFunction for VCode { fn block_insns(&self, block: BlockIndex) -> InstRange { let range = self.block_ranges.get(block.index()); - InstRange::forward(InsnIndex::new(range.start), InsnIndex::new(range.end)) + InstRange::new(InsnIndex::new(range.start), InsnIndex::new(range.end)) } fn block_succs(&self, block: BlockIndex) -> &[BlockIndex] { @@ -1344,10 +1320,6 @@ impl RegallocFunction for VCode { } } - fn requires_refs_on_stack(&self, _insn: InsnIndex) -> bool { - false - } - fn inst_operands(&self, insn: InsnIndex) -> &[Operand] { let range = self.operand_ranges.get(insn.index()); &self.operands[range] diff --git a/cranelift/codegen/src/prelude_lower.isle b/cranelift/codegen/src/prelude_lower.isle index 00c444576c87..b9c16d68ac06 100644 --- a/cranelift/codegen/src/prelude_lower.isle +++ b/cranelift/codegen/src/prelude_lower.isle @@ -255,6 +255,11 @@ (decl inst_results (ValueSlice) Inst) (extern extractor infallible inst_results inst_results) +;; Returns whether the given value is unused in this function and is a dead +;; result. +(decl pure value_is_unused (Value) bool) +(extern constructor value_is_unused value_is_unused) + ;; Extract the first result value of the given instruction. (decl first_result (Value) Inst) (extern extractor first_result first_result) diff --git a/cranelift/codegen/src/settings.rs b/cranelift/codegen/src/settings.rs index 39446528dbdf..fb57ecdc032d 100644 --- a/cranelift/codegen/src/settings.rs +++ b/cranelift/codegen/src/settings.rs @@ -482,13 +482,13 @@ pub struct FlagsOrIsa<'a> { } impl<'a> From<&'a Flags> for FlagsOrIsa<'a> { - fn from(flags: &'a Flags) -> FlagsOrIsa { + fn from(flags: &'a Flags) -> FlagsOrIsa<'a> { FlagsOrIsa { flags, isa: None } } } impl<'a> From<&'a dyn TargetIsa> for FlagsOrIsa<'a> { - fn from(isa: &'a dyn TargetIsa) -> FlagsOrIsa { + fn from(isa: &'a dyn TargetIsa) -> FlagsOrIsa<'a> { FlagsOrIsa { flags: isa.flags(), isa: Some(isa), diff --git a/cranelift/control/Cargo.toml b/cranelift/control/Cargo.toml index ebbc9447d58a..f6354051d18c 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.112.0" +version = "0.113.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 1c0c1bf0eb4d..6f30f6f23521 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.112.0" +version = "0.113.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/entity/src/lib.rs b/cranelift/entity/src/lib.rs index 4cbed9d0a7a8..5ad0014c3649 100644 --- a/cranelift/entity/src/lib.rs +++ b/cranelift/entity/src/lib.rs @@ -265,6 +265,7 @@ mod list; mod map; mod primary; mod set; +mod signed; mod sparse; mod unsigned; @@ -275,6 +276,7 @@ pub use self::list::{EntityList, ListPool}; pub use self::map::SecondaryMap; pub use self::primary::PrimaryMap; pub use self::set::EntitySet; +pub use self::signed::Signed; pub use self::sparse::{SparseMap, SparseMapValue, SparseSet}; pub use self::unsigned::Unsigned; diff --git a/cranelift/entity/src/signed.rs b/cranelift/entity/src/signed.rs new file mode 100644 index 000000000000..3c136d590157 --- /dev/null +++ b/cranelift/entity/src/signed.rs @@ -0,0 +1,40 @@ +/// Helper trait used to add `signed()` methods to primitive unsigned integer +/// types. +/// +/// The purpose of this trait is to signal the intent that the sign bit of an +/// unsigned integer is intended to be discarded and the value is instead +/// understood to be a "bag of bits" where the conversion to a signed number +/// is intended to be lossless bit-wise. This can be used for example when +/// converting an unsigned integer into a signed integer for constrained reasons +/// outside the scope of the code in question. +pub trait Signed { + /// The signed integer for this type which has the same width. + type Signed; + + /// View this unsigned integer as a signed integer of the same width. + /// + /// All bits are preserved. + fn signed(self) -> Self::Signed; +} + +macro_rules! impls { + ($($unsigned:ident => $signed:ident)*) => {$( + impl Signed for $unsigned { + type Signed = $signed; + + #[inline] + fn signed(self) -> $signed { + self as $signed + } + } + )*} +} + +impls! { + u8 => i8 + u16 => i16 + u32 => i32 + u64 => i64 + u128 => i128 + usize => isize +} diff --git a/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif b/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif index d919b28dace0..9b37ca1521b5 100644 --- a/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif +++ b/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif @@ -63,8 +63,8 @@ block0(v0: i64): ; stp fp, lr, [sp, #-16]! ; mov fp, sp ; block0: -; mov x0, x2 ; load_ext_name x3, TestCase(%g)+0 +; mov x0, x2 ; blr x3 ; mov x2, x0 ; ldp fp, lr, [sp], #16 @@ -76,11 +76,11 @@ block0(v0: i64): ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp ; block1: ; offset 0xc -; mov x0, x2 -; ldr x3, #0x18 -; b #0x20 +; ldr x3, #0x14 +; b #0x1c ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x0, x2 ; blr x3 ; mov x2, x0 ; ldp x29, x30, [sp], #0x10 diff --git a/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif b/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif index 5e11b77d4f21..736cafe2e0c3 100644 --- a/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif +++ b/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif @@ -64,8 +64,8 @@ block0(v0: i64): ; stp fp, lr, [sp, #-16]! ; mov fp, sp ; block0: -; mov x0, x2 ; load_ext_name x3, TestCase(%g)+0 +; mov x0, x2 ; blr x3 ; mov x2, x0 ; ldp fp, lr, [sp], #16 @@ -77,11 +77,11 @@ block0(v0: i64): ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp ; block1: ; offset 0xc -; mov x0, x2 -; ldr x3, #0x18 -; b #0x20 +; ldr x3, #0x14 +; b #0x1c ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x0, x2 ; blr x3 ; mov x2, x0 ; ldp x29, x30, [sp], #0x10 diff --git a/cranelift/filetests/filetests/isa/aarch64/call.clif b/cranelift/filetests/filetests/isa/aarch64/call.clif index 102dc4f4e021..ee69a6a2819a 100644 --- a/cranelift/filetests/filetests/isa/aarch64/call.clif +++ b/cranelift/filetests/filetests/isa/aarch64/call.clif @@ -529,9 +529,9 @@ block0(v0: i64): ; stp fp, lr, [sp, #-16]! ; mov fp, sp ; block0: -; mov x1, x0 ; movz x2, #42 ; load_ext_name x4, TestCase(%f11)+0 +; mov x1, x0 ; mov x0, x2 ; blr x4 ; ldp fp, lr, [sp], #16 @@ -542,12 +542,12 @@ block0(v0: i64): ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp ; block1: ; offset 0x8 -; mov x1, x0 ; mov x2, #0x2a -; ldr x4, #0x18 -; b #0x20 +; ldr x4, #0x14 +; b #0x1c ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f11 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x1, x0 ; mov x0, x2 ; blr x4 ; ldp x29, x30, [sp], #0x10 @@ -583,9 +583,9 @@ block0(v0: i64): ; stp fp, lr, [sp, #-16]! ; mov fp, sp ; block0: -; mov x2, x0 ; movz x3, #42 ; load_ext_name x4, TestCase(%f12)+0 +; mov x2, x0 ; mov x0, x3 ; blr x4 ; ldp fp, lr, [sp], #16 @@ -596,12 +596,12 @@ block0(v0: i64): ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp ; block1: ; offset 0x8 -; mov x2, x0 ; mov x3, #0x2a -; ldr x4, #0x18 -; b #0x20 +; ldr x4, #0x14 +; b #0x1c ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f12 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x2, x0 ; mov x0, x3 ; blr x4 ; ldp x29, x30, [sp], #0x10 @@ -637,9 +637,9 @@ block0(v0: i64): ; stp fp, lr, [sp, #-16]! ; mov fp, sp ; block0: -; mov x1, x0 ; movz x2, #42 ; load_ext_name x4, TestCase(%f13)+0 +; mov x1, x0 ; mov x0, x2 ; blr x4 ; ldp fp, lr, [sp], #16 @@ -650,12 +650,12 @@ block0(v0: i64): ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp ; block1: ; offset 0x8 -; mov x1, x0 ; mov x2, #0x2a -; ldr x4, #0x18 -; b #0x20 +; ldr x4, #0x14 +; b #0x1c ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f13 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x1, x0 ; mov x0, x2 ; blr x4 ; ldp x29, x30, [sp], #0x10 @@ -698,12 +698,12 @@ block0(v0: i128, v1: i64): ; mov fp, sp ; sub sp, sp, #16 ; block0: -; mov x6, x2 ; str x0, [sp] -; mov x4, x0 ; str x1, [sp, #8] -; mov x5, x1 ; load_ext_name x8, TestCase(%f14)+0 +; mov x4, x0 +; mov x5, x1 +; mov x6, x2 ; mov x2, x4 ; mov x3, x5 ; blr x8 @@ -717,15 +717,15 @@ block0(v0: i128, v1: i64): ; mov x29, sp ; sub sp, sp, #0x10 ; block1: ; offset 0xc -; mov x6, x2 ; stur x0, [sp] -; mov x4, x0 ; stur x1, [sp, #8] -; mov x5, x1 -; ldr x8, #0x28 -; b #0x30 +; ldr x8, #0x1c +; b #0x24 ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f14 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x4, x0 +; mov x5, x1 +; mov x6, x2 ; mov x2, x4 ; mov x3, x5 ; blr x8 @@ -770,12 +770,12 @@ block0(v0: i128, v1: i64): ; mov fp, sp ; sub sp, sp, #16 ; block0: -; mov x6, x2 ; str x0, [sp] -; mov x4, x0 ; str x1, [sp, #8] -; mov x5, x1 ; load_ext_name x8, TestCase(%f15)+0 +; mov x4, x0 +; mov x5, x1 +; mov x6, x2 ; mov x2, x4 ; mov x3, x5 ; blr x8 @@ -789,15 +789,15 @@ block0(v0: i128, v1: i64): ; mov x29, sp ; sub sp, sp, #0x10 ; block1: ; offset 0xc -; mov x6, x2 ; stur x0, [sp] -; mov x4, x0 ; stur x1, [sp, #8] -; mov x5, x1 -; ldr x8, #0x28 -; b #0x30 +; ldr x8, #0x1c +; b #0x24 ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f15 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x4, x0 +; mov x5, x1 +; mov x6, x2 ; mov x2, x4 ; mov x3, x5 ; blr x8 @@ -836,8 +836,8 @@ block0(v0: i64): ; stp fp, lr, [sp, #-16]! ; mov fp, sp ; block0: -; mov x8, x0 ; load_ext_name x3, TestCase(%g)+0 +; mov x8, x0 ; blr x3 ; ldp fp, lr, [sp], #16 ; ret @@ -847,11 +847,11 @@ block0(v0: i64): ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp ; block1: ; offset 0x8 -; mov x8, x0 -; ldr x3, #0x14 -; b #0x1c +; ldr x3, #0x10 +; b #0x18 ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mov x8, x0 ; blr x3 ; ldp x29, x30, [sp], #0x10 ; ret @@ -867,13 +867,13 @@ block0(v0: i64): ; VCode: ; stp fp, lr, [sp, #-16]! ; mov fp, sp -; str x23, [sp, #-16]! +; str x24, [sp, #-16]! ; block0: -; mov x23, x8 +; mov x24, x8 ; load_ext_name x2, TestCase(%g)+0 ; blr x2 -; mov x8, x23 -; ldr x23, [sp], #16 +; mov x8, x24 +; ldr x24, [sp], #16 ; ldp fp, lr, [sp], #16 ; ret ; @@ -881,16 +881,16 @@ block0(v0: i64): ; block0: ; offset 0x0 ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp -; str x23, [sp, #-0x10]! +; str x24, [sp, #-0x10]! ; block1: ; offset 0xc -; mov x23, x8 +; mov x24, x8 ; ldr x2, #0x18 ; b #0x20 ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g 0 ; .byte 0x00, 0x00, 0x00, 0x00 ; blr x2 -; mov x8, x23 -; ldr x23, [sp], #0x10 +; mov x8, x24 +; ldr x24, [sp], #0x10 ; ldp x29, x30, [sp], #0x10 ; ret diff --git a/cranelift/filetests/filetests/isa/aarch64/fma.clif b/cranelift/filetests/filetests/isa/aarch64/fma.clif index d44099cec743..a0b714d09d4b 100644 --- a/cranelift/filetests/filetests/isa/aarch64/fma.clif +++ b/cranelift/filetests/filetests/isa/aarch64/fma.clif @@ -358,28 +358,28 @@ block0(v0: f32x4, v1: f32x4, v2: f32x4): ; VCode: ; block0: -; mov v31.16b, v1.16b ; movz w6, #7452 ; movk w6, w6, #7966, LSL #16 ; dup v17.4s, w6 +; mov v31.16b, v1.16b ; mov v30.16b, v31.16b ; tbl v19.16b, { v30.16b, v31.16b }, v17.16b -; mov v23.16b, v0.16b +; mov v22.16b, v0.16b ; mov v0.16b, v2.16b -; fmla v0.4s, v0.4s, v23.4s, v19.4s +; fmla v0.4s, v0.4s, v22.4s, v19.4s ; ret ; ; Disassembled: ; block0: ; offset 0x0 -; mov v31.16b, v1.16b ; mov w6, #0x1d1c ; movk w6, #0x1f1e, lsl #16 ; dup v17.4s, w6 +; mov v31.16b, v1.16b ; mov v30.16b, v31.16b ; tbl v19.16b, {v30.16b, v31.16b}, v17.16b -; mov v23.16b, v0.16b +; mov v22.16b, v0.16b ; mov v0.16b, v2.16b -; fmla v0.4s, v23.4s, v19.4s +; fmla v0.4s, v22.4s, v19.4s ; ret function %f64x2_splat0(f64x2, f64x2, f64x2) -> f64x2 { diff --git a/cranelift/filetests/filetests/isa/aarch64/i128.clif b/cranelift/filetests/filetests/isa/aarch64/i128.clif new file mode 100644 index 000000000000..a07ca6a88faa --- /dev/null +++ b/cranelift/filetests/filetests/isa/aarch64/i128.clif @@ -0,0 +1,127 @@ +test compile precise-output +set enable_llvm_abi_extensions=true +set opt_level=speed +target aarch64 + +function %mul_uextend_i64(i64, i64) -> i128 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; block0: +; madd x3, x0, x1, xzr +; umulh x1, x0, x1 +; mov x0, x3 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mul x3, x0, x1 +; umulh x1, x0, x1 +; mov x0, x3 +; ret + +function %mul_sextend_i64(i64, i64) -> i128 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; block0: +; madd x3, x0, x1, xzr +; smulh x1, x0, x1 +; mov x0, x3 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mul x3, x0, x1 +; smulh x1, x0, x1 +; mov x0, x3 +; ret + +function %smul_high_i64_pattern(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + v5 = sshr_imm v4, 64 + v6 = ireduce.i64 v5 + return v6 +} + +; VCode: +; block0: +; smulh x0, x0, x1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; smulh x0, x0, x1 +; ret + +function %smul_high_i64_isplit(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + v5, v6 = isplit v4 + return v6 +} + +; VCode: +; block0: +; smulh x0, x0, x1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; smulh x0, x0, x1 +; ret + +function %umul_high_i64_pattern(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + v5 = ushr_imm v4, 64 + v6 = ireduce.i64 v5 + return v6 +} + +; VCode: +; block0: +; umulh x0, x0, x1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; umulh x0, x0, x1 +; ret + +function %umul_high_i64_isplit(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + v5, v6 = isplit v4 + return v6 +} + +; VCode: +; block0: +; umulh x0, x0, x1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; umulh x0, x0, x1 +; ret + diff --git a/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif b/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif index 319ea508ba06..ca0c1fcd48e7 100644 --- a/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif +++ b/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif @@ -228,8 +228,8 @@ block0: ; stp x19, x20, [sp, #-16]! ; sub sp, sp, #16 ; block0: -; movz x2, #10 -; str x2, [sp] +; movz x3, #10 +; str x3, [sp] ; movz x3, #15 ; movz x4, #20 ; movz x5, #25 @@ -295,8 +295,8 @@ block0: ; stp x19, x20, [sp, #-0x10]! ; sub sp, sp, #0x10 ; block1: ; offset 0x30 -; mov x2, #0xa -; stur x2, [sp] +; mov x3, #0xa +; stur x3, [sp] ; mov x3, #0xf ; mov x4, #0x14 ; mov x5, #0x19 diff --git a/cranelift/filetests/filetests/isa/aarch64/return-call.clif b/cranelift/filetests/filetests/isa/aarch64/return-call.clif index 1e018b3c4a84..46a9ce746ca3 100644 --- a/cranelift/filetests/filetests/isa/aarch64/return-call.clif +++ b/cranelift/filetests/filetests/isa/aarch64/return-call.clif @@ -463,18 +463,18 @@ block2: ; stp x19, x20, [sp, #-16]! ; sub sp, sp, #16 ; block0: -; movz x14, #10 -; str x14, [sp] +; movz x3, #10 +; str x3, [sp] ; movz x3, #15 ; movz x4, #20 ; movz x5, #25 ; movz x6, #30 ; movz x7, #35 -; movz x21, #40 -; movz x28, #45 -; movz x27, #50 -; movz x26, #55 -; movz x25, #60 +; movz x25, #40 +; movz x21, #45 +; movz x28, #50 +; movz x27, #55 +; movz x26, #60 ; movz x24, #65 ; movz x23, #70 ; movz x22, #75 @@ -493,11 +493,11 @@ block2: ; cbnz x2, label2 ; b label1 ; block1: ; movz x2, #140 -; str x21, [sp, #112] -; str x28, [sp, #120] -; str x27, [sp, #128] -; str x26, [sp, #136] -; str x25, [sp, #144] +; str x25, [sp, #112] +; str x21, [sp, #120] +; str x28, [sp, #128] +; str x27, [sp, #136] +; str x26, [sp, #144] ; str x24, [sp, #152] ; str x23, [sp, #160] ; str x22, [sp, #168] @@ -519,11 +519,11 @@ block2: ; return_call_ind x1 new_stack_arg_size:176 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 ; block2: ; ldr x2, [sp] -; str x21, [sp, #128] -; str x28, [sp, #136] -; str x27, [sp, #144] -; str x26, [sp, #152] -; str x25, [sp, #160] +; str x25, [sp, #128] +; str x21, [sp, #136] +; str x28, [sp, #144] +; str x27, [sp, #152] +; str x26, [sp, #160] ; str x24, [sp, #168] ; str x23, [sp, #176] ; str x22, [sp, #184] @@ -557,18 +557,18 @@ block2: ; stp x19, x20, [sp, #-0x10]! ; sub sp, sp, #0x10 ; block1: ; offset 0x30 -; mov x14, #0xa -; stur x14, [sp] +; mov x3, #0xa +; stur x3, [sp] ; mov x3, #0xf ; mov x4, #0x14 ; mov x5, #0x19 ; mov x6, #0x1e ; mov x7, #0x23 -; mov x21, #0x28 -; mov x28, #0x2d -; mov x27, #0x32 -; mov x26, #0x37 -; mov x25, #0x3c +; mov x25, #0x28 +; mov x21, #0x2d +; mov x28, #0x32 +; mov x27, #0x37 +; mov x26, #0x3c ; mov x24, #0x41 ; mov x23, #0x46 ; mov x22, #0x4b @@ -587,11 +587,11 @@ block2: ; cbnz x2, #0x12c ; block2: ; offset 0xa0 ; mov x2, #0x8c -; stur x21, [sp, #0x70] -; stur x28, [sp, #0x78] -; stur x27, [sp, #0x80] -; stur x26, [sp, #0x88] -; stur x25, [sp, #0x90] +; stur x25, [sp, #0x70] +; stur x21, [sp, #0x78] +; stur x28, [sp, #0x80] +; stur x27, [sp, #0x88] +; stur x26, [sp, #0x90] ; stur x24, [sp, #0x98] ; stur x23, [sp, #0xa0] ; stur x22, [sp, #0xa8] @@ -623,11 +623,11 @@ block2: ; br x1 ; block3: ; offset 0x12c ; ldur x2, [sp] -; stur x21, [sp, #0x80] -; stur x28, [sp, #0x88] -; stur x27, [sp, #0x90] -; stur x26, [sp, #0x98] -; stur x25, [sp, #0xa0] +; stur x25, [sp, #0x80] +; stur x21, [sp, #0x88] +; stur x28, [sp, #0x90] +; stur x27, [sp, #0x98] +; stur x26, [sp, #0xa0] ; stur x24, [sp, #0xa8] ; stur x23, [sp, #0xb0] ; stur x22, [sp, #0xb8] diff --git a/cranelift/filetests/filetests/isa/aarch64/shuffle.clif b/cranelift/filetests/filetests/isa/aarch64/shuffle.clif index d22518b02aeb..b20ceee6d052 100644 --- a/cranelift/filetests/filetests/isa/aarch64/shuffle.clif +++ b/cranelift/filetests/filetests/isa/aarch64/shuffle.clif @@ -10,17 +10,17 @@ block0(v0: i8x16, v1: i8x16): ; VCode: ; block0: +; ldr q3, [const(0)] ; mov v30.16b, v0.16b ; mov v31.16b, v1.16b -; ldr q3, [const(0)] ; tbl v0.16b, { v30.16b, v31.16b }, v3.16b ; ret ; ; Disassembled: ; block0: ; offset 0x0 +; ldr q3, #0x20 ; mov v30.16b, v0.16b ; mov v31.16b, v1.16b -; ldr q3, #0x20 ; tbl v0.16b, {v30.16b, v31.16b}, v3.16b ; ret ; .byte 0x00, 0x00, 0x00, 0x00 @@ -541,17 +541,17 @@ block0(v0: i8x16, v1: i8x16): ; VCode: ; block0: +; ldr q3, [const(0)] ; mov v30.16b, v0.16b ; mov v31.16b, v1.16b -; ldr q3, [const(0)] ; tbl v0.16b, { v30.16b, v31.16b }, v3.16b ; ret ; ; Disassembled: ; block0: ; offset 0x0 +; ldr q3, #0x20 ; mov v30.16b, v0.16b ; mov v31.16b, v1.16b -; ldr q3, #0x20 ; tbl v0.16b, {v30.16b, v31.16b}, v3.16b ; ret ; .byte 0x00, 0x00, 0x00, 0x00 diff --git a/cranelift/filetests/filetests/isa/aarch64/stack.clif b/cranelift/filetests/filetests/isa/aarch64/stack.clif index cd2fd150b9cb..12b9788ec195 100644 --- a/cranelift/filetests/filetests/isa/aarch64/stack.clif +++ b/cranelift/filetests/filetests/isa/aarch64/stack.clif @@ -463,28 +463,28 @@ block0(v0: i8): ; add x0, x0, #31 ; ldr x7, [sp, #1208] ; add x7, x7, #33 -; ldr x9, [sp, #1200] -; add x8, x9, #35 -; ldr x12, [sp, #1192] -; add x9, x12, #37 -; ldr x15, [sp, #1184] -; add x10, x15, #39 -; ldr x2, [sp, #1176] -; add x11, x2, #31 -; ldr x5, [sp, #1168] -; add x12, x5, #33 +; ldr x10, [sp, #1200] +; add x8, x10, #35 +; ldr x13, [sp, #1192] +; add x9, x13, #37 +; ldr x1, [sp, #1184] +; add x10, x1, #39 +; ldr x3, [sp, #1176] +; add x11, x3, #31 +; ldr x6, [sp, #1168] +; add x12, x6, #33 ; ldr x13, [sp, #1160] ; add x13, x13, #35 ; ldr x14, [sp, #1152] ; add x14, x14, #37 ; ldr x15, [sp, #1144] ; add x15, x15, #39 -; ldr x1, [sp, #1136] -; ldr x3, [sp, #1128] -; add x1, x1, x3 +; ldr x2, [sp, #1136] +; ldr x4, [sp, #1128] +; add x1, x2, x4 ; ldr x2, [sp, #1112] -; ldr x6, [sp, #1120] -; add x2, x6, x2 +; ldr x3, [sp, #1120] +; add x2, x3, x2 ; ldr x3, [sp, #1096] ; ldr x4, [sp, #1104] ; add x3, x4, x3 @@ -641,28 +641,28 @@ block0(v0: i8): ; add x0, x0, #0x1f ; ldr x7, [sp, #0x4b8] ; add x7, x7, #0x21 -; ldr x9, [sp, #0x4b0] -; add x8, x9, #0x23 -; ldr x12, [sp, #0x4a8] -; add x9, x12, #0x25 -; ldr x15, [sp, #0x4a0] -; add x10, x15, #0x27 -; ldr x2, [sp, #0x498] -; add x11, x2, #0x1f -; ldr x5, [sp, #0x490] -; add x12, x5, #0x21 +; ldr x10, [sp, #0x4b0] +; add x8, x10, #0x23 +; ldr x13, [sp, #0x4a8] +; add x9, x13, #0x25 +; ldr x1, [sp, #0x4a0] +; add x10, x1, #0x27 +; ldr x3, [sp, #0x498] +; add x11, x3, #0x1f +; ldr x6, [sp, #0x490] +; add x12, x6, #0x21 ; ldr x13, [sp, #0x488] ; add x13, x13, #0x23 ; ldr x14, [sp, #0x480] ; add x14, x14, #0x25 ; ldr x15, [sp, #0x478] ; add x15, x15, #0x27 -; ldr x1, [sp, #0x470] -; ldr x3, [sp, #0x468] -; add x1, x1, x3 +; ldr x2, [sp, #0x470] +; ldr x4, [sp, #0x468] +; add x1, x2, x4 ; ldr x2, [sp, #0x458] -; ldr x6, [sp, #0x460] -; add x2, x6, x2 +; ldr x3, [sp, #0x460] +; add x2, x3, x2 ; ldr x3, [sp, #0x448] ; ldr x4, [sp, #0x450] ; add x3, x4, x3 diff --git a/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif b/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif index 1f5dd3f61328..9a9da0b515c7 100644 --- a/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif +++ b/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif @@ -243,8 +243,8 @@ block0: ; stp x19, x20, [sp, #-16]! ; sub sp, sp, #16 ; block0: -; movz x2, #10 -; str x2, [sp] +; movz x3, #10 +; str x3, [sp] ; movz x3, #15 ; movz x4, #20 ; movz x5, #25 @@ -311,8 +311,8 @@ block0: ; stp x19, x20, [sp, #-0x10]! ; sub sp, sp, #0x10 ; block1: ; offset 0x20 -; mov x2, #0xa -; stur x2, [sp] +; mov x3, #0xa +; stur x3, [sp] ; mov x3, #0xf ; mov x4, #0x14 ; mov x5, #0x19 diff --git a/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif b/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif index e3761f258d74..7f185e4b2e81 100644 --- a/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif +++ b/cranelift/filetests/filetests/isa/aarch64/tls-elf-gd.clif @@ -14,10 +14,10 @@ block0(v0: i32): ; stp fp, lr, [sp, #-16]! ; mov fp, sp ; block0: -; mov x5, x0 +; mov x6, x0 ; elf_tls_get_addr x0, x3, userextname0 ; mov x1, x0 -; mov x0, x5 +; mov x0, x6 ; ldp fp, lr, [sp], #16 ; ret ; @@ -26,7 +26,7 @@ block0(v0: i32): ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp ; block1: ; offset 0x8 -; mov x5, x0 +; mov x6, x0 ; adrp x0, #0 ; reloc_external Aarch64TlsDescAdrPage21 u1:0 0 ; ldr x3, [x0] ; reloc_external Aarch64TlsDescLd64Lo12 u1:0 0 ; add x0, x0, #0 ; reloc_external Aarch64TlsDescAddLo12 u1:0 0 @@ -34,7 +34,7 @@ block0(v0: i32): ; mrs x3, tpidr_el0 ; add x0, x0, x3 ; mov x1, x0 -; mov x0, x5 +; mov x0, x6 ; ldp x29, x30, [sp], #0x10 ; ret diff --git a/cranelift/filetests/filetests/isa/aarch64/tls-macho.clif b/cranelift/filetests/filetests/isa/aarch64/tls-macho.clif index 5a74b0948444..23a20eb52ce1 100644 --- a/cranelift/filetests/filetests/isa/aarch64/tls-macho.clif +++ b/cranelift/filetests/filetests/isa/aarch64/tls-macho.clif @@ -13,21 +13,21 @@ block0(v0: i32): ; VCode: ; stp fp, lr, [sp, #-16]! ; mov fp, sp -; str x24, [sp, #-16]! +; str x25, [sp, #-16]! ; stp d14, d15, [sp, #-16]! ; stp d12, d13, [sp, #-16]! ; stp d10, d11, [sp, #-16]! ; stp d8, d9, [sp, #-16]! ; block0: -; mov x24, x0 +; mov x25, x0 ; macho_tls_get_addr x0, userextname0 ; mov x1, x0 -; mov x0, x24 +; mov x0, x25 ; ldp d8, d9, [sp], #16 ; ldp d10, d11, [sp], #16 ; ldp d12, d13, [sp], #16 ; ldp d14, d15, [sp], #16 -; ldr x24, [sp], #16 +; ldr x25, [sp], #16 ; ldp fp, lr, [sp], #16 ; ret ; @@ -35,24 +35,24 @@ block0(v0: i32): ; block0: ; offset 0x0 ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp -; str x24, [sp, #-0x10]! +; str x25, [sp, #-0x10]! ; stp d14, d15, [sp, #-0x10]! ; stp d12, d13, [sp, #-0x10]! ; stp d10, d11, [sp, #-0x10]! ; stp d8, d9, [sp, #-0x10]! ; block1: ; offset 0x1c -; mov x24, x0 +; mov x25, x0 ; adrp x0, #0 ; reloc_external MachOAarch64TlsAdrPage21 u1:0 0 ; ldr x0, [x0] ; reloc_external MachOAarch64TlsAdrPageOff12 u1:0 0 ; ldr x1, [x0] ; blr x1 ; mov x1, x0 -; mov x0, x24 +; mov x0, x25 ; ldp d8, d9, [sp], #0x10 ; ldp d10, d11, [sp], #0x10 ; ldp d12, d13, [sp], #0x10 ; ldp d14, d15, [sp], #0x10 -; ldr x24, [sp], #0x10 +; ldr x25, [sp], #0x10 ; ldp x29, x30, [sp], #0x10 ; ret diff --git a/cranelift/filetests/filetests/isa/aarch64/user_stack_maps.clif b/cranelift/filetests/filetests/isa/aarch64/user_stack_maps.clif index e51a2e507a72..531ecb748afe 100644 --- a/cranelift/filetests/filetests/isa/aarch64/user_stack_maps.clif +++ b/cranelift/filetests/filetests/isa/aarch64/user_stack_maps.clif @@ -34,45 +34,39 @@ block0: ; VCode: ; stp fp, lr, [sp, #-16]! ; mov fp, sp -; str x24, [sp, #-16]! -; stp x19, x22, [sp, #-16]! +; str x28, [sp, #-16]! +; stp x19, x21, [sp, #-16]! ; sub sp, sp, #16 ; block0: -; movz w9, #0 -; movz w8, #1 -; movz w0, #2 -; mov x10, sp -; str w9, [x10] -; mov x24, x9 +; movz w19, #0 +; movz w28, #1 +; movz w21, #2 +; mov x8, sp +; str w19, [x8] ; add x9, sp, #4 -; str w8, [x9] -; mov x19, x8 +; str w28, [x9] ; add x10, sp, #8 -; str w0, [x10] -; mov x22, x0 -; mov x0, x24 +; str w21, [x10] +; mov x0, x19 ; bl 0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4, 8})], sp_to_sized_stack_slots: None } ; mov x12, sp -; mov x0, x19 -; str w0, [x12] +; str w28, [x12] ; add x13, sp, #4 -; mov x0, x22 -; str w0, [x13] -; mov x0, x24 +; str w21, [x13] +; mov x0, x19 ; bl 0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4})], sp_to_sized_stack_slots: None } ; mov x15, sp -; mov x0, x22 -; str w0, [x15] -; mov x0, x19 +; str w21, [x15] +; mov x0, x28 ; bl 0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0})], sp_to_sized_stack_slots: None } -; mov x0, x22 +; mov x0, x21 ; bl 0 ; add sp, sp, #16 -; ldp x19, x22, [sp], #16 -; ldr x24, [sp], #16 +; ldp x19, x21, [sp], #16 +; ldr x28, [sp], #16 ; ldp fp, lr, [sp], #16 ; ret ; @@ -80,42 +74,36 @@ block0: ; block0: ; offset 0x0 ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp -; str x24, [sp, #-0x10]! -; stp x19, x22, [sp, #-0x10]! +; str x28, [sp, #-0x10]! +; stp x19, x21, [sp, #-0x10]! ; sub sp, sp, #0x10 ; block1: ; offset 0x14 -; mov w9, #0 -; mov w8, #1 -; mov w0, #2 -; mov x10, sp -; str w9, [x10] -; mov x24, x9 +; mov w19, #0 +; mov w28, #1 +; mov w21, #2 +; mov x8, sp +; str w19, [x8] ; add x9, sp, #4 -; str w8, [x9] -; mov x19, x8 +; str w28, [x9] ; add x10, sp, #8 -; str w0, [x10] -; mov x22, x0 -; mov x0, x24 -; bl #0x48 ; reloc_external Call u0:0 0 -; mov x12, sp +; str w21, [x10] ; mov x0, x19 -; str w0, [x12] +; bl #0x3c ; reloc_external Call u0:0 0 +; mov x12, sp +; str w28, [x12] ; add x13, sp, #4 -; mov x0, x22 -; str w0, [x13] -; mov x0, x24 -; bl #0x68 ; reloc_external Call u0:0 0 -; mov x15, sp -; mov x0, x22 -; str w0, [x15] +; str w21, [x13] ; mov x0, x19 -; bl #0x7c ; reloc_external Call u0:0 0 -; mov x0, x22 -; bl #0x84 ; reloc_external Call u0:0 0 +; bl #0x54 ; reloc_external Call u0:0 0 +; mov x15, sp +; str w21, [x15] +; mov x0, x28 +; bl #0x64 ; reloc_external Call u0:0 0 +; mov x0, x21 +; bl #0x6c ; reloc_external Call u0:0 0 ; add sp, sp, #0x10 -; ldp x19, x22, [sp], #0x10 -; ldr x24, [sp], #0x10 +; ldp x19, x21, [sp], #0x10 +; ldr x28, [sp], #0x10 ; ldp x29, x30, [sp], #0x10 ; ret @@ -142,39 +130,39 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; VCode: ; stp fp, lr, [sp, #-16]! ; mov fp, sp -; stp x23, x27, [sp, #-16]! -; stp x20, x21, [sp, #-16]! +; stp x23, x26, [sp, #-16]! +; stp x19, x21, [sp, #-16]! ; sub sp, sp, #128 ; block0: ; mov x12, sp ; strb w0, [x12] -; mov x23, x0 +; mov x21, x0 ; add x13, sp, #8 ; strh w1, [x13] -; mov x20, x1 +; mov x26, x1 ; add x14, sp, #16 ; str w2, [x14] -; mov x21, x2 +; mov x23, x2 ; add x15, sp, #20 ; str s0, [x15] ; str q0, [sp, #96] ; add x0, sp, #24 ; str x3, [x0] -; mov x27, x3 +; mov x19, x3 ; add x1, sp, #32 ; str d1, [x1] ; str q1, [sp, #112] ; bl 0 ; ; UserStackMap { by_type: [(types::I8, CompoundBitSet {0}), (types::I16, CompoundBitSet {8}), (types::I32, CompoundBitSet {16}), (types::F32, CompoundBitSet {20}), (types::I64, CompoundBitSet {24}), (types::F64, CompoundBitSet {32})], sp_to_sized_stack_slots: None } -; mov x0, x23 -; mov x1, x20 -; mov x2, x21 -; mov x3, x27 +; mov x0, x21 +; mov x1, x26 +; mov x2, x23 +; mov x3, x19 ; ldr q0, [sp, #96] ; ldr q1, [sp, #112] ; add sp, sp, #128 -; ldp x20, x21, [sp], #16 -; ldp x23, x27, [sp], #16 +; ldp x19, x21, [sp], #16 +; ldp x23, x26, [sp], #16 ; ldp fp, lr, [sp], #16 ; ret ; @@ -182,38 +170,38 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; block0: ; offset 0x0 ; stp x29, x30, [sp, #-0x10]! ; mov x29, sp -; stp x23, x27, [sp, #-0x10]! -; stp x20, x21, [sp, #-0x10]! +; stp x23, x26, [sp, #-0x10]! +; stp x19, x21, [sp, #-0x10]! ; sub sp, sp, #0x80 ; block1: ; offset 0x14 ; mov x12, sp ; strb w0, [x12] -; mov x23, x0 +; mov x21, x0 ; add x13, sp, #8 ; strh w1, [x13] -; mov x20, x1 +; mov x26, x1 ; add x14, sp, #0x10 ; str w2, [x14] -; mov x21, x2 +; mov x23, x2 ; add x15, sp, #0x14 ; str s0, [x15] ; stur q0, [sp, #0x60] ; add x0, sp, #0x18 ; str x3, [x0] -; mov x27, x3 +; mov x19, x3 ; add x1, sp, #0x20 ; str d1, [x1] ; stur q1, [sp, #0x70] ; bl #0x5c ; reloc_external Call u0:0 0 -; mov x0, x23 -; mov x1, x20 -; mov x2, x21 -; mov x3, x27 +; mov x0, x21 +; mov x1, x26 +; mov x2, x23 +; mov x3, x19 ; ldur q0, [sp, #0x60] ; ldur q1, [sp, #0x70] ; add sp, sp, #0x80 -; ldp x20, x21, [sp], #0x10 -; ldp x23, x27, [sp], #0x10 +; ldp x19, x21, [sp], #0x10 +; ldp x23, x26, [sp], #0x10 ; ldp x29, x30, [sp], #0x10 ; ret diff --git a/cranelift/filetests/filetests/isa/pulley32/brif-icmp.clif b/cranelift/filetests/filetests/isa/pulley32/brif-icmp.clif index e40370d9f24e..66c925120abc 100644 --- a/cranelift/filetests/filetests/isa/pulley32/brif-icmp.clif +++ b/cranelift/filetests/filetests/isa/pulley32/brif-icmp.clif @@ -27,9 +27,9 @@ block2: ; ; Disassembled: ; 0: 05 00 01 0b 00 00 00 br_if_xeq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ne(i32, i32) -> i32 { @@ -58,9 +58,9 @@ block2: ; ; Disassembled: ; 0: 06 00 01 0b 00 00 00 br_if_xneq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ult(i32, i32) -> i32 { @@ -89,9 +89,9 @@ block2: ; ; Disassembled: ; 0: 09 00 01 0b 00 00 00 br_if_xult32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ule(i32, i32) -> i32 { @@ -120,9 +120,9 @@ block2: ; ; Disassembled: ; 0: 0a 00 01 0b 00 00 00 br_if_xulteq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_slt(i32, i32) -> i32 { @@ -151,9 +151,9 @@ block2: ; ; Disassembled: ; 0: 07 00 01 0b 00 00 00 br_if_xslt32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_sle(i32, i32) -> i32 { @@ -182,9 +182,9 @@ block2: ; ; Disassembled: ; 0: 08 00 01 0b 00 00 00 br_if_xslteq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ugt(i32, i32) -> i32 { @@ -213,9 +213,9 @@ block2: ; ; Disassembled: ; 0: 09 01 00 0b 00 00 00 br_if_xult32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_uge(i32, i32) -> i32 { @@ -244,9 +244,9 @@ block2: ; ; Disassembled: ; 0: 0a 01 00 0b 00 00 00 br_if_xulteq32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_sgt(i32, i32) -> i32 { @@ -275,9 +275,9 @@ block2: ; ; Disassembled: ; 0: 07 01 00 0b 00 00 00 br_if_xslt32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_sge(i32, i32) -> i32 { @@ -306,9 +306,9 @@ block2: ; ; Disassembled: ; 0: 08 01 00 0b 00 00 00 br_if_xslteq32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_uextend_icmp_eq(i32, i32) -> i32 { @@ -338,8 +338,8 @@ block2: ; ; Disassembled: ; 0: 05 00 01 0b 00 00 00 br_if_xeq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/brif.clif b/cranelift/filetests/filetests/isa/pulley32/brif.clif index b2f943d7cb19..9dc2a45990dd 100644 --- a/cranelift/filetests/filetests/isa/pulley32/brif.clif +++ b/cranelift/filetests/filetests/isa/pulley32/brif.clif @@ -26,9 +26,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_i16(i16) -> i8 { @@ -56,9 +56,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_i32(i32) -> i8 { @@ -86,9 +86,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_i64(i64) -> i8 { @@ -116,9 +116,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_icmp_i8(i8, i8) -> i8 { @@ -147,11 +147,11 @@ block2: ; ret ; ; Disassembled: -; 0: 1a 05 04 xeq32 x5, x0, x1 +; 0: 20 05 04 xeq32 x5, x0, x1 ; 3: 03 05 0a 00 00 00 br_if x5, 0xa // target = 0xd -; 9: 0e 00 00 xconst8 x0, 0 +; 9: 14 00 00 xconst8 x0, 0 ; c: 00 ret -; d: 0e 00 01 xconst8 x0, 1 +; d: 14 00 01 xconst8 x0, 1 ; 10: 00 ret function %brif_icmp_i16(i16, i16) -> i8 { @@ -180,11 +180,11 @@ block2: ; ret ; ; Disassembled: -; 0: 1b 05 04 xneq32 x5, x0, x1 +; 0: 21 05 04 xneq32 x5, x0, x1 ; 3: 03 05 0a 00 00 00 br_if x5, 0xa // target = 0xd -; 9: 0e 00 00 xconst8 x0, 0 +; 9: 14 00 00 xconst8 x0, 0 ; c: 00 ret -; d: 0e 00 01 xconst8 x0, 1 +; d: 14 00 01 xconst8 x0, 1 ; 10: 00 ret function %brif_icmp_i32(i32, i32) -> i8 { @@ -213,9 +213,9 @@ block2: ; ; Disassembled: ; 0: 07 00 01 0b 00 00 00 br_if_xslt32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 00 xconst8 x0, 0 +; 7: 14 00 00 xconst8 x0, 0 ; a: 00 ret -; b: 0e 00 01 xconst8 x0, 1 +; b: 14 00 01 xconst8 x0, 1 ; e: 00 ret function %brif_icmp_i64(i64, i64) -> i8 { @@ -244,10 +244,10 @@ block2: ; ret ; ; Disassembled: -; 0: 19 25 00 xulteq64 x5, x1, x0 +; 0: 1f 25 00 xulteq64 x5, x1, x0 ; 3: 03 05 0a 00 00 00 br_if x5, 0xa // target = 0xd -; 9: 0e 00 00 xconst8 x0, 0 +; 9: 14 00 00 xconst8 x0, 0 ; c: 00 ret -; d: 0e 00 01 xconst8 x0, 1 +; d: 14 00 01 xconst8 x0, 1 ; 10: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/call.clif b/cranelift/filetests/filetests/isa/pulley32/call.clif index d1f2dfe9a61a..2839cf8ab02f 100644 --- a/cranelift/filetests/filetests/isa/pulley32/call.clif +++ b/cranelift/filetests/filetests/isa/pulley32/call.clif @@ -19,7 +19,7 @@ block0: ; x29 = xmov x27 ; block0: ; x0 = xconst8 0 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [1204185006387685820006398, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 ; x28 = load64_u sp+8 // flags = notrap aligned ; x29 = load64_u sp+0 // flags = notrap aligned @@ -28,18 +28,18 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 00 00 xconst8 x0, 0 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 00 00 xconst8 x0, 0 ; 13: 01 00 00 00 00 call 0x0 // target = 0x13 -; 18: 0e 00 01 xconst8 x0, 1 -; 1b: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 1f: 22 1d 1b load64 fp, sp -; 22: 0e 1e 10 xconst8 spilltmp0, 16 -; 25: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 18: 14 00 01 xconst8 x0, 1 +; 1b: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 1f: 28 1d 1b load64 fp, sp +; 22: 14 1e 10 xconst8 spilltmp0, 16 +; 25: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 28: 00 ret function %colocated_args_i32_rets_i32() -> i32 { @@ -60,7 +60,7 @@ block0: ; x29 = xmov x27 ; block0: ; x0 = xconst8 0 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [1204185006387685820006398, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 ; x28 = load64_u sp+8 // flags = notrap aligned ; x29 = load64_u sp+0 // flags = notrap aligned @@ -69,18 +69,18 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 00 00 xconst8 x0, 0 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 00 00 xconst8 x0, 0 ; 13: 01 00 00 00 00 call 0x0 // target = 0x13 -; 18: 0e 00 01 xconst8 x0, 1 -; 1b: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 1f: 22 1d 1b load64 fp, sp -; 22: 0e 1e 10 xconst8 spilltmp0, 16 -; 25: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 18: 14 00 01 xconst8 x0, 1 +; 1b: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 1f: 28 1d 1b load64 fp, sp +; 22: 14 1e 10 xconst8 spilltmp0, 16 +; 25: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 28: 00 ret function %colocated_args_i64_i32_i64_i32() { @@ -106,7 +106,7 @@ block0: ; x1 = xconst8 1 ; x2 = xconst8 2 ; x3 = xconst8 3 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [1204185006387685820006399, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x28 = load64_u sp+8 // flags = notrap aligned ; x29 = load64_u sp+0 // flags = notrap aligned ; x30 = xconst8 16 @@ -114,20 +114,20 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 00 00 xconst8 x0, 0 -; 13: 0e 01 01 xconst8 x1, 1 -; 16: 0e 02 02 xconst8 x2, 2 -; 19: 0e 03 03 xconst8 x3, 3 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 00 00 xconst8 x0, 0 +; 13: 14 01 01 xconst8 x1, 1 +; 16: 14 02 02 xconst8 x2, 2 +; 19: 14 03 03 xconst8 x3, 3 ; 1c: 01 00 00 00 00 call 0x0 // target = 0x1c -; 21: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 25: 22 1d 1b load64 fp, sp -; 28: 0e 1e 10 xconst8 spilltmp0, 16 -; 2b: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 21: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 25: 28 1d 1b load64 fp, sp +; 28: 14 1e 10 xconst8 spilltmp0, 16 +; 2b: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 2e: 00 ret function %colocated_rets_i64_i64_i64_i64() -> i64 { @@ -148,7 +148,7 @@ block0: ; store64 sp+0, x29 // flags = notrap aligned ; x29 = xmov x27 ; block0: -; call TestCase(%g), CallInfo { uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }], clobbers: PRegSet { bits: [1204185006387685820006384, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }], clobbers: PRegSet { bits: [65520, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x4 = xadd64 x0, x2 ; x3 = xadd64 x1, x3 ; x0 = xadd64 x4, x3 @@ -159,19 +159,19 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp ; 10: 01 00 00 00 00 call 0x0 // target = 0x10 -; 15: 13 04 08 xadd64 x4, x0, x2 -; 18: 13 23 0c xadd64 x3, x1, x3 -; 1b: 13 80 0c xadd64 x0, x4, x3 -; 1e: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 22: 22 1d 1b load64 fp, sp -; 25: 0e 1e 10 xconst8 spilltmp0, 16 -; 28: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 15: 19 04 08 xadd64 x4, x0, x2 +; 18: 19 23 0c xadd64 x3, x1, x3 +; 1b: 19 80 0c xadd64 x0, x4, x3 +; 1e: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 22: 28 1d 1b load64 fp, sp +; 25: 14 1e 10 xconst8 spilltmp0, 16 +; 28: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 2b: 00 ret function %colocated_stack_args() { @@ -214,7 +214,7 @@ block0: ; x12 = xmov x15 ; x13 = xmov x15 ; x14 = xmov x15 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [1204185006387685820006399, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x30 = xconst8 48 ; x27 = xadd32 x27, x30 ; x28 = load64_u sp+8 // flags = notrap aligned @@ -224,42 +224,42 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 1e d0 xconst8 spilltmp0, -48 -; 13: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 16: 0e 0f 00 xconst8 x15, 0 -; 19: 2a 1b 0f store64 sp, x15 -; 1c: 2c 1b 08 0f store64_offset8 sp, 8, x15 -; 20: 2c 1b 10 0f store64_offset8 sp, 16, x15 -; 24: 2c 1b 18 0f store64_offset8 sp, 24, x15 -; 28: 2c 1b 20 0f store64_offset8 sp, 32, x15 -; 2c: 2c 1b 28 0f store64_offset8 sp, 40, x15 -; 30: 0b 00 0f xmov x0, x15 -; 33: 0b 01 0f xmov x1, x15 -; 36: 0b 02 0f xmov x2, x15 -; 39: 0b 03 0f xmov x3, x15 -; 3c: 0b 04 0f xmov x4, x15 -; 3f: 0b 05 0f xmov x5, x15 -; 42: 0b 06 0f xmov x6, x15 -; 45: 0b 07 0f xmov x7, x15 -; 48: 0b 08 0f xmov x8, x15 -; 4b: 0b 09 0f xmov x9, x15 -; 4e: 0b 0a 0f xmov x10, x15 -; 51: 0b 0b 0f xmov x11, x15 -; 54: 0b 0c 0f xmov x12, x15 -; 57: 0b 0d 0f xmov x13, x15 -; 5a: 0b 0e 0f xmov x14, x15 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 1e d0 xconst8 spilltmp0, -48 +; 13: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 16: 14 0f 00 xconst8 x15, 0 +; 19: 30 1b 0f store64 sp, x15 +; 1c: 32 1b 08 0f store64_offset8 sp, 8, x15 +; 20: 32 1b 10 0f store64_offset8 sp, 16, x15 +; 24: 32 1b 18 0f store64_offset8 sp, 24, x15 +; 28: 32 1b 20 0f store64_offset8 sp, 32, x15 +; 2c: 32 1b 28 0f store64_offset8 sp, 40, x15 +; 30: 11 00 0f xmov x0, x15 +; 33: 11 01 0f xmov x1, x15 +; 36: 11 02 0f xmov x2, x15 +; 39: 11 03 0f xmov x3, x15 +; 3c: 11 04 0f xmov x4, x15 +; 3f: 11 05 0f xmov x5, x15 +; 42: 11 06 0f xmov x6, x15 +; 45: 11 07 0f xmov x7, x15 +; 48: 11 08 0f xmov x8, x15 +; 4b: 11 09 0f xmov x9, x15 +; 4e: 11 0a 0f xmov x10, x15 +; 51: 11 0b 0f xmov x11, x15 +; 54: 11 0c 0f xmov x12, x15 +; 57: 11 0d 0f xmov x13, x15 +; 5a: 11 0e 0f xmov x14, x15 ; 5d: 01 00 00 00 00 call 0x0 // target = 0x5d -; 62: 0e 1e 30 xconst8 spilltmp0, 48 -; 65: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 68: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 6c: 22 1d 1b load64 fp, sp -; 6f: 0e 1e 10 xconst8 spilltmp0, 16 -; 72: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 62: 14 1e 30 xconst8 spilltmp0, 48 +; 65: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 68: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 6c: 28 1d 1b load64 fp, sp +; 6f: 14 1e 10 xconst8 spilltmp0, 16 +; 72: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 75: 00 ret function %colocated_stack_rets() -> i64 { @@ -310,7 +310,7 @@ block0: ; store64 sp+48, x18 // flags = notrap aligned ; block0: ; x0 = load_addr OutgoingArg(0) -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }, CallRetPair { vreg: Writable { reg: p4i }, preg: p4i }, CallRetPair { vreg: Writable { reg: p5i }, preg: p5i }, CallRetPair { vreg: Writable { reg: p6i }, preg: p6i }, CallRetPair { vreg: Writable { reg: p7i }, preg: p7i }, CallRetPair { vreg: Writable { reg: p8i }, preg: p8i }, CallRetPair { vreg: Writable { reg: p9i }, preg: p9i }, CallRetPair { vreg: Writable { reg: p10i }, preg: p10i }, CallRetPair { vreg: Writable { reg: p11i }, preg: p11i }, CallRetPair { vreg: Writable { reg: p12i }, preg: p12i }, CallRetPair { vreg: Writable { reg: p13i }, preg: p13i }, CallRetPair { vreg: Writable { reg: p14i }, preg: p14i }, CallRetPair { vreg: Writable { reg: p15i }, preg: p15i }], clobbers: PRegSet { bits: [1204185006387685819940864, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }, CallRetPair { vreg: Writable { reg: p4i }, preg: p4i }, CallRetPair { vreg: Writable { reg: p5i }, preg: p5i }, CallRetPair { vreg: Writable { reg: p6i }, preg: p6i }, CallRetPair { vreg: Writable { reg: p7i }, preg: p7i }, CallRetPair { vreg: Writable { reg: p8i }, preg: p8i }, CallRetPair { vreg: Writable { reg: p9i }, preg: p9i }, CallRetPair { vreg: Writable { reg: p10i }, preg: p10i }, CallRetPair { vreg: Writable { reg: p11i }, preg: p11i }, CallRetPair { vreg: Writable { reg: p12i }, preg: p12i }, CallRetPair { vreg: Writable { reg: p13i }, preg: p13i }, CallRetPair { vreg: Writable { reg: p14i }, preg: p14i }, CallRetPair { vreg: Writable { reg: p15i }, preg: p15i }], clobbers: PRegSet { bits: [0, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x16 = xmov x13 ; x18 = xmov x11 ; x25 = load64_u OutgoingArg(0) // flags = notrap aligned @@ -354,56 +354,56 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 1e c0 xconst8 spilltmp0, -64 -; 13: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 16: 2c 1b 38 10 store64_offset8 sp, 56, x16 -; 1a: 2c 1b 30 12 store64_offset8 sp, 48, x18 -; 1e: 0b 00 1b xmov x0, sp +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 1e c0 xconst8 spilltmp0, -64 +; 13: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 16: 32 1b 38 10 store64_offset8 sp, 56, x16 +; 1a: 32 1b 30 12 store64_offset8 sp, 48, x18 +; 1e: 11 00 1b xmov x0, sp ; 21: 01 00 00 00 00 call 0x0 // target = 0x21 -; 26: 0b 10 0d xmov x16, x13 -; 29: 0b 12 0b xmov x18, x11 -; 2c: 22 19 1b load64 x25, sp -; 2f: 25 0b 1b 08 load64_offset8 x11, sp, 8 -; 33: 25 0d 1b 10 load64_offset8 x13, sp, 16 -; 37: 25 1f 1b 18 load64_offset8 spilltmp1, sp, 24 -; 3b: 25 11 1b 20 load64_offset8 x17, sp, 32 -; 3f: 13 1e 04 xadd64 spilltmp0, x0, x1 -; 42: 13 5d 0c xadd64 fp, x2, x3 -; 45: 13 85 14 xadd64 x5, x4, x5 -; 48: 13 c6 1c xadd64 x6, x6, x7 -; 4b: 13 07 25 xadd64 x7, x8, x9 -; 4e: 0b 00 12 xmov x0, x18 -; 51: 13 44 01 xadd64 x4, x10, x0 -; 54: 0b 0a 10 xmov x10, x16 -; 57: 13 88 29 xadd64 x8, x12, x10 -; 5a: 13 ce 3d xadd64 x14, x14, x15 -; 5d: 13 2f 2f xadd64 x15, x25, x11 -; 60: 13 6d 35 xadd64 x13, x11, x13 -; 63: 13 e0 47 xadd64 x0, spilltmp1, x17 -; 66: 13 c1 77 xadd64 x1, spilltmp0, fp -; 69: 13 a2 18 xadd64 x2, x5, x6 -; 6c: 13 e3 10 xadd64 x3, x7, x4 -; 6f: 13 0e 39 xadd64 x14, x8, x14 -; 72: 13 ed 35 xadd64 x13, x15, x13 -; 75: 13 0f 00 xadd64 x15, x0, x0 -; 78: 13 20 08 xadd64 x0, x1, x2 -; 7b: 13 6e 38 xadd64 x14, x3, x14 -; 7e: 13 ad 3d xadd64 x13, x13, x15 -; 81: 13 0e 38 xadd64 x14, x0, x14 -; 84: 13 ad 35 xadd64 x13, x13, x13 -; 87: 13 c0 35 xadd64 x0, x14, x13 -; 8a: 25 10 1b 38 load64_offset8 x16, sp, 56 -; 8e: 25 12 1b 30 load64_offset8 x18, sp, 48 -; 92: 0e 1e 40 xconst8 spilltmp0, 64 -; 95: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 98: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 9c: 22 1d 1b load64 fp, sp -; 9f: 0e 1e 10 xconst8 spilltmp0, 16 -; a2: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 26: 11 10 0d xmov x16, x13 +; 29: 11 12 0b xmov x18, x11 +; 2c: 28 19 1b load64 x25, sp +; 2f: 2b 0b 1b 08 load64_offset8 x11, sp, 8 +; 33: 2b 0d 1b 10 load64_offset8 x13, sp, 16 +; 37: 2b 1f 1b 18 load64_offset8 spilltmp1, sp, 24 +; 3b: 2b 11 1b 20 load64_offset8 x17, sp, 32 +; 3f: 19 1e 04 xadd64 spilltmp0, x0, x1 +; 42: 19 5d 0c xadd64 fp, x2, x3 +; 45: 19 85 14 xadd64 x5, x4, x5 +; 48: 19 c6 1c xadd64 x6, x6, x7 +; 4b: 19 07 25 xadd64 x7, x8, x9 +; 4e: 11 00 12 xmov x0, x18 +; 51: 19 44 01 xadd64 x4, x10, x0 +; 54: 11 0a 10 xmov x10, x16 +; 57: 19 88 29 xadd64 x8, x12, x10 +; 5a: 19 ce 3d xadd64 x14, x14, x15 +; 5d: 19 2f 2f xadd64 x15, x25, x11 +; 60: 19 6d 35 xadd64 x13, x11, x13 +; 63: 19 e0 47 xadd64 x0, spilltmp1, x17 +; 66: 19 c1 77 xadd64 x1, spilltmp0, fp +; 69: 19 a2 18 xadd64 x2, x5, x6 +; 6c: 19 e3 10 xadd64 x3, x7, x4 +; 6f: 19 0e 39 xadd64 x14, x8, x14 +; 72: 19 ed 35 xadd64 x13, x15, x13 +; 75: 19 0f 00 xadd64 x15, x0, x0 +; 78: 19 20 08 xadd64 x0, x1, x2 +; 7b: 19 6e 38 xadd64 x14, x3, x14 +; 7e: 19 ad 3d xadd64 x13, x13, x15 +; 81: 19 0e 38 xadd64 x14, x0, x14 +; 84: 19 ad 35 xadd64 x13, x13, x13 +; 87: 19 c0 35 xadd64 x0, x14, x13 +; 8a: 2b 10 1b 38 load64_offset8 x16, sp, 56 +; 8e: 2b 12 1b 30 load64_offset8 x18, sp, 48 +; 92: 14 1e 40 xconst8 spilltmp0, 64 +; 95: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 98: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 9c: 28 1d 1b load64 fp, sp +; 9f: 14 1e 10 xconst8 spilltmp0, 16 +; a2: 18 7b 7b xadd32 sp, sp, spilltmp0 ; a5: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif b/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif index 1bae8c297e72..d90bd5a66ca8 100644 --- a/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif +++ b/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif @@ -13,5 +13,6 @@ block0: ; ret ; ; Disassembled: -; 0: 3d 02 00 00 get_sp x0 +; 0: 43 02 00 00 get_sp x0 ; 4: 00 ret + diff --git a/cranelift/filetests/filetests/isa/pulley32/iadd.clif b/cranelift/filetests/filetests/isa/pulley32/iadd.clif index 68bfe902da4b..98c6acf13b10 100644 --- a/cranelift/filetests/filetests/isa/pulley32/iadd.clif +++ b/cranelift/filetests/filetests/isa/pulley32/iadd.clif @@ -13,7 +13,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 12 00 04 xadd32 x0, x0, x1 +; 0: 18 00 04 xadd32 x0, x0, x1 ; 3: 00 ret function %i16(i16, i16) -> i16 { @@ -28,7 +28,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 12 00 04 xadd32 x0, x0, x1 +; 0: 18 00 04 xadd32 x0, x0, x1 ; 3: 00 ret function %i32(i32, i32) -> i32 { @@ -43,7 +43,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 12 00 04 xadd32 x0, x0, x1 +; 0: 18 00 04 xadd32 x0, x0, x1 ; 3: 00 ret function %i64(i64, i64) -> i64 { @@ -58,6 +58,6 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 13 00 04 xadd64 x0, x0, x1 +; 0: 19 00 04 xadd64 x0, x0, x1 ; 3: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/icmp.clif b/cranelift/filetests/filetests/isa/pulley32/icmp.clif index d6f489e68c8c..1929123c2a5d 100644 --- a/cranelift/filetests/filetests/isa/pulley32/icmp.clif +++ b/cranelift/filetests/filetests/isa/pulley32/icmp.clif @@ -13,7 +13,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1a 00 04 xeq32 x0, x0, x1 +; 0: 20 00 04 xeq32 x0, x0, x1 ; 3: 00 ret function %i16_eq(i16, i16) -> i8 { @@ -28,7 +28,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1a 00 04 xeq32 x0, x0, x1 +; 0: 20 00 04 xeq32 x0, x0, x1 ; 3: 00 ret function %i32_eq(i32, i32) -> i8 { @@ -43,7 +43,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1a 00 04 xeq32 x0, x0, x1 +; 0: 20 00 04 xeq32 x0, x0, x1 ; 3: 00 ret function %i64_eq(i64, i64) -> i8 { @@ -58,7 +58,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 14 00 04 xeq64 x0, x0, x1 +; 0: 1a 00 04 xeq64 x0, x0, x1 ; 3: 00 ret function %i8_ne(i8, i8) -> i8 { @@ -73,7 +73,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1b 00 04 xneq32 x0, x0, x1 +; 0: 21 00 04 xneq32 x0, x0, x1 ; 3: 00 ret function %i16_ne(i16, i16) -> i8 { @@ -88,7 +88,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1b 00 04 xneq32 x0, x0, x1 +; 0: 21 00 04 xneq32 x0, x0, x1 ; 3: 00 ret function %i32_ne(i32, i32) -> i8 { @@ -103,7 +103,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1b 00 04 xneq32 x0, x0, x1 +; 0: 21 00 04 xneq32 x0, x0, x1 ; 3: 00 ret function %i64_ne(i64, i64) -> i8 { @@ -118,7 +118,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 15 00 04 xneq64 x0, x0, x1 +; 0: 1b 00 04 xneq64 x0, x0, x1 ; 3: 00 ret function %i8_ult(i8, i8) -> i8 { @@ -133,7 +133,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1e 00 04 xult32 x0, x0, x1 +; 0: 24 00 04 xult32 x0, x0, x1 ; 3: 00 ret function %i16_ult(i16, i16) -> i8 { @@ -148,7 +148,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1e 00 04 xult32 x0, x0, x1 +; 0: 24 00 04 xult32 x0, x0, x1 ; 3: 00 ret function %i32_ult(i32, i32) -> i8 { @@ -163,7 +163,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1e 00 04 xult32 x0, x0, x1 +; 0: 24 00 04 xult32 x0, x0, x1 ; 3: 00 ret function %i64_ult(i64, i64) -> i8 { @@ -178,7 +178,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 18 00 04 xult64 x0, x0, x1 +; 0: 1e 00 04 xult64 x0, x0, x1 ; 3: 00 ret function %i8_ule(i8, i8) -> i8 { @@ -193,7 +193,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1f 00 04 xulteq32 x0, x0, x1 +; 0: 25 00 04 xulteq32 x0, x0, x1 ; 3: 00 ret function %i16_ule(i16, i16) -> i8 { @@ -208,7 +208,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1f 00 04 xulteq32 x0, x0, x1 +; 0: 25 00 04 xulteq32 x0, x0, x1 ; 3: 00 ret function %i32_ule(i32, i32) -> i8 { @@ -223,7 +223,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1f 00 04 xulteq32 x0, x0, x1 +; 0: 25 00 04 xulteq32 x0, x0, x1 ; 3: 00 ret function %i64_ule(i64, i64) -> i8 { @@ -238,7 +238,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 19 00 04 xulteq64 x0, x0, x1 +; 0: 1f 00 04 xulteq64 x0, x0, x1 ; 3: 00 ret function %i8_slt(i8, i8) -> i8 { @@ -253,7 +253,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1c 00 04 xslt32 x0, x0, x1 +; 0: 22 00 04 xslt32 x0, x0, x1 ; 3: 00 ret function %i16_slt(i16, i16) -> i8 { @@ -268,7 +268,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1c 00 04 xslt32 x0, x0, x1 +; 0: 22 00 04 xslt32 x0, x0, x1 ; 3: 00 ret function %i32_slt(i32, i32) -> i8 { @@ -283,7 +283,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1c 00 04 xslt32 x0, x0, x1 +; 0: 22 00 04 xslt32 x0, x0, x1 ; 3: 00 ret function %i64_slt(i64, i64) -> i8 { @@ -298,7 +298,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 16 00 04 xslt64 x0, x0, x1 +; 0: 1c 00 04 xslt64 x0, x0, x1 ; 3: 00 ret function %i8_sle(i8, i8) -> i8 { @@ -313,7 +313,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1d 00 04 xslteq32 x0, x0, x1 +; 0: 23 00 04 xslteq32 x0, x0, x1 ; 3: 00 ret function %i16_sle(i16, i16) -> i8 { @@ -328,7 +328,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1d 00 04 xslteq32 x0, x0, x1 +; 0: 23 00 04 xslteq32 x0, x0, x1 ; 3: 00 ret function %i32_sle(i32, i32) -> i8 { @@ -343,7 +343,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1d 00 04 xslteq32 x0, x0, x1 +; 0: 23 00 04 xslteq32 x0, x0, x1 ; 3: 00 ret function %i64_sle(i64, i64) -> i8 { @@ -358,7 +358,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 17 00 04 xslteq64 x0, x0, x1 +; 0: 1d 00 04 xslteq64 x0, x0, x1 ; 3: 00 ret function %i8_ugt(i8, i8) -> i8 { @@ -373,7 +373,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1e 20 00 xult32 x0, x1, x0 +; 0: 24 20 00 xult32 x0, x1, x0 ; 3: 00 ret function %i16_ugt(i16, i16) -> i8 { @@ -388,7 +388,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1e 20 00 xult32 x0, x1, x0 +; 0: 24 20 00 xult32 x0, x1, x0 ; 3: 00 ret function %i32_ugt(i32, i32) -> i8 { @@ -403,7 +403,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1e 20 00 xult32 x0, x1, x0 +; 0: 24 20 00 xult32 x0, x1, x0 ; 3: 00 ret function %i64_ugt(i64, i64) -> i8 { @@ -418,7 +418,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 18 20 00 xult64 x0, x1, x0 +; 0: 1e 20 00 xult64 x0, x1, x0 ; 3: 00 ret function %i8_sgt(i8, i8) -> i8 { @@ -433,7 +433,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1c 20 00 xslt32 x0, x1, x0 +; 0: 22 20 00 xslt32 x0, x1, x0 ; 3: 00 ret function %i16_sgt(i16, i16) -> i8 { @@ -448,7 +448,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1c 20 00 xslt32 x0, x1, x0 +; 0: 22 20 00 xslt32 x0, x1, x0 ; 3: 00 ret function %i32_sgt(i32, i32) -> i8 { @@ -463,7 +463,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1c 20 00 xslt32 x0, x1, x0 +; 0: 22 20 00 xslt32 x0, x1, x0 ; 3: 00 ret function %i64_sgt(i64, i64) -> i8 { @@ -478,7 +478,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 16 20 00 xslt64 x0, x1, x0 +; 0: 1c 20 00 xslt64 x0, x1, x0 ; 3: 00 ret function %i8_uge(i8, i8) -> i8 { @@ -493,7 +493,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1f 20 00 xulteq32 x0, x1, x0 +; 0: 25 20 00 xulteq32 x0, x1, x0 ; 3: 00 ret function %i16_uge(i16, i16) -> i8 { @@ -508,7 +508,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1f 20 00 xulteq32 x0, x1, x0 +; 0: 25 20 00 xulteq32 x0, x1, x0 ; 3: 00 ret function %i32_uge(i32, i32) -> i8 { @@ -523,7 +523,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1f 20 00 xulteq32 x0, x1, x0 +; 0: 25 20 00 xulteq32 x0, x1, x0 ; 3: 00 ret function %i64_uge(i64, i64) -> i8 { @@ -538,7 +538,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 19 20 00 xulteq64 x0, x1, x0 +; 0: 1f 20 00 xulteq64 x0, x1, x0 ; 3: 00 ret function %i8_sge(i8, i8) -> i8 { @@ -553,7 +553,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1d 20 00 xslteq32 x0, x1, x0 +; 0: 23 20 00 xslteq32 x0, x1, x0 ; 3: 00 ret function %i16_sge(i16, i16) -> i8 { @@ -568,7 +568,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1d 20 00 xslteq32 x0, x1, x0 +; 0: 23 20 00 xslteq32 x0, x1, x0 ; 3: 00 ret function %i32_sge(i32, i32) -> i8 { @@ -583,7 +583,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1d 20 00 xslteq32 x0, x1, x0 +; 0: 23 20 00 xslteq32 x0, x1, x0 ; 3: 00 ret function %i64_sge(i64, i64) -> i8 { @@ -598,6 +598,6 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 17 20 00 xslteq64 x0, x1, x0 +; 0: 1d 20 00 xslteq64 x0, x1, x0 ; 3: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/iconst.clif b/cranelift/filetests/filetests/isa/pulley32/iconst.clif index f38de07e3ddf..7cf8f42f2d25 100644 --- a/cranelift/filetests/filetests/isa/pulley32/iconst.clif +++ b/cranelift/filetests/filetests/isa/pulley32/iconst.clif @@ -13,7 +13,7 @@ block0: ; ret ; ; Disassembled: -; 0: 0f 00 ff 00 xconst16 x0, 255 +; 0: 15 00 ff 00 xconst16 x0, 255 ; 4: 00 ret function %i16() -> i16 { @@ -28,7 +28,7 @@ block0: ; ret ; ; Disassembled: -; 0: 10 00 ff ff 00 00 xconst32 x0, 65535 +; 0: 16 00 ff ff 00 00 xconst32 x0, 65535 ; 6: 00 ret function %i32() -> i32 { @@ -43,7 +43,7 @@ block0: ; ret ; ; Disassembled: -; 0: 10 00 ff ff ff ff xconst32 x0, -1 +; 0: 16 00 ff ff ff ff xconst32 x0, -1 ; 6: 00 ret function %i64() -> i64 { @@ -58,6 +58,6 @@ block0: ; ret ; ; Disassembled: -; 0: 11 00 ff ff ff ff ff ff ff ff xconst64 x0, -1 +; 0: 17 00 ff ff ff ff ff ff ff ff xconst64 x0, -1 ; a: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/jump.clif b/cranelift/filetests/filetests/isa/pulley32/jump.clif index c216be08ed40..aa11556ef632 100644 --- a/cranelift/filetests/filetests/isa/pulley32/jump.clif +++ b/cranelift/filetests/filetests/isa/pulley32/jump.clif @@ -31,8 +31,8 @@ block3(v3: i8): ; ; Disassembled: ; 0: 03 00 0e 00 00 00 br_if x0, 0xe // target = 0xe -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 02 08 00 00 00 jump 0x8 // target = 0x11 -; e: 0e 00 01 xconst8 x0, 1 +; e: 14 00 01 xconst8 x0, 1 ; 11: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/load.clif b/cranelift/filetests/filetests/isa/pulley32/load.clif index 427d1a4a0d69..44ec74161c09 100644 --- a/cranelift/filetests/filetests/isa/pulley32/load.clif +++ b/cranelift/filetests/filetests/isa/pulley32/load.clif @@ -13,7 +13,7 @@ block0(v0: i32): ; ret ; ; Disassembled: -; 0: 20 00 00 load32_u x0, x0 +; 0: 26 00 00 load32_u x0, x0 ; 3: 00 ret function %load_i64(i32) -> i64 { @@ -28,7 +28,7 @@ block0(v0: i32): ; ret ; ; Disassembled: -; 0: 22 00 00 load64 x0, x0 +; 0: 28 00 00 load64 x0, x0 ; 3: 00 ret function %load_i32_with_offset(i32) -> i32 { @@ -43,7 +43,7 @@ block0(v0: i32): ; ret ; ; Disassembled: -; 0: 23 00 00 04 load32_u_offset8 x0, x0, 4 +; 0: 29 00 00 04 load32_u_offset8 x0, x0, 4 ; 4: 00 ret function %load_i64_with_offset(i32) -> i64 { @@ -58,6 +58,6 @@ block0(v0: i32): ; ret ; ; Disassembled: -; 0: 25 00 00 08 load64_offset8 x0, x0, 8 +; 0: 2b 00 00 08 load64_offset8 x0, x0, 8 ; 4: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/store.clif b/cranelift/filetests/filetests/isa/pulley32/store.clif index 57ec3de6f1c8..96e6afb6be2a 100644 --- a/cranelift/filetests/filetests/isa/pulley32/store.clif +++ b/cranelift/filetests/filetests/isa/pulley32/store.clif @@ -13,7 +13,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 29 01 00 store32 x1, x0 +; 0: 2f 01 00 store32 x1, x0 ; 3: 00 ret function %store_i64(i64, i32) { @@ -28,7 +28,7 @@ block0(v0: i64, v1: i32): ; ret ; ; Disassembled: -; 0: 2a 01 00 store64 x1, x0 +; 0: 30 01 00 store64 x1, x0 ; 3: 00 ret function %store_i32_with_offset(i32, i32) { @@ -43,7 +43,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 2b 01 04 00 store32_offset8 x1, 4, x0 +; 0: 31 01 04 00 store32_offset8 x1, 4, x0 ; 4: 00 ret function %store_i64_with_offset(i64, i32) { @@ -58,6 +58,6 @@ block0(v0: i64, v1: i32): ; ret ; ; Disassembled: -; 0: 2c 01 08 00 store64_offset8 x1, 8, x0 +; 0: 32 01 08 00 store64_offset8 x1, 8, x0 ; 4: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley32/trap.clif b/cranelift/filetests/filetests/isa/pulley32/trap.clif index 983c35ce4bf6..53ebb5ed911c 100644 --- a/cranelift/filetests/filetests/isa/pulley32/trap.clif +++ b/cranelift/filetests/filetests/isa/pulley32/trap.clif @@ -11,7 +11,7 @@ block0: ; trap // code = User(0) ; ; Disassembled: -; 0: 3d 00 00 trap +; 0: 43 00 00 trap function %trapnz(i64) { block0(v0: i64): @@ -32,11 +32,11 @@ block0(v0: i64): ; trap // code = User(0) ; ; Disassembled: -; 0: 0e 03 2a xconst8 x3, 42 -; 3: 14 03 0c xeq64 x3, x0, x3 +; 0: 14 03 2a xconst8 x3, 42 +; 3: 1a 03 0c xeq64 x3, x0, x3 ; 6: 03 03 07 00 00 00 br_if x3, 0x7 // target = 0xd ; c: 00 ret -; d: 3d 00 00 trap +; d: 43 00 00 trap function %trapz(i64) { block0(v0: i64): @@ -57,8 +57,9 @@ block0(v0: i64): ; trap // code = User(0) ; ; Disassembled: -; 0: 0e 03 2a xconst8 x3, 42 -; 3: 14 03 0c xeq64 x3, x0, x3 +; 0: 14 03 2a xconst8 x3, 42 +; 3: 1a 03 0c xeq64 x3, x0, x3 ; 6: 04 03 07 00 00 00 br_if_not x3, 0x7 // target = 0xd ; c: 00 ret -; d: 3d 00 00 trap +; d: 43 00 00 trap + diff --git a/cranelift/filetests/filetests/isa/pulley64/brif-icmp.clif b/cranelift/filetests/filetests/isa/pulley64/brif-icmp.clif index ba51bf4aa4ed..ca6357defc1a 100644 --- a/cranelift/filetests/filetests/isa/pulley64/brif-icmp.clif +++ b/cranelift/filetests/filetests/isa/pulley64/brif-icmp.clif @@ -27,9 +27,9 @@ block2: ; ; Disassembled: ; 0: 05 00 01 0b 00 00 00 br_if_xeq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ne(i32, i32) -> i32 { @@ -58,9 +58,9 @@ block2: ; ; Disassembled: ; 0: 06 00 01 0b 00 00 00 br_if_xneq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ult(i32, i32) -> i32 { @@ -89,9 +89,9 @@ block2: ; ; Disassembled: ; 0: 09 00 01 0b 00 00 00 br_if_xult32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ule(i32, i32) -> i32 { @@ -120,9 +120,9 @@ block2: ; ; Disassembled: ; 0: 0a 00 01 0b 00 00 00 br_if_xulteq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_slt(i32, i32) -> i32 { @@ -151,9 +151,9 @@ block2: ; ; Disassembled: ; 0: 07 00 01 0b 00 00 00 br_if_xslt32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_sle(i32, i32) -> i32 { @@ -182,9 +182,9 @@ block2: ; ; Disassembled: ; 0: 08 00 01 0b 00 00 00 br_if_xslteq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_ugt(i32, i32) -> i32 { @@ -213,9 +213,9 @@ block2: ; ; Disassembled: ; 0: 09 01 00 0b 00 00 00 br_if_xult32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_uge(i32, i32) -> i32 { @@ -244,9 +244,9 @@ block2: ; ; Disassembled: ; 0: 0a 01 00 0b 00 00 00 br_if_xulteq32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_sgt(i32, i32) -> i32 { @@ -275,9 +275,9 @@ block2: ; ; Disassembled: ; 0: 07 01 00 0b 00 00 00 br_if_xslt32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_icmp_sge(i32, i32) -> i32 { @@ -306,9 +306,9 @@ block2: ; ; Disassembled: ; 0: 08 01 00 0b 00 00 00 br_if_xslteq32 x1, x0, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret function %brif_uextend_icmp_eq(i32, i32) -> i32 { @@ -338,8 +338,8 @@ block2: ; ; Disassembled: ; 0: 05 00 01 0b 00 00 00 br_if_xeq32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 01 xconst8 x0, 1 +; 7: 14 00 01 xconst8 x0, 1 ; a: 00 ret -; b: 0e 00 02 xconst8 x0, 2 +; b: 14 00 02 xconst8 x0, 2 ; e: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/brif.clif b/cranelift/filetests/filetests/isa/pulley64/brif.clif index 597257d0d4b9..e3b6e0ec6076 100644 --- a/cranelift/filetests/filetests/isa/pulley64/brif.clif +++ b/cranelift/filetests/filetests/isa/pulley64/brif.clif @@ -26,9 +26,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_i16(i16) -> i8 { @@ -56,9 +56,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_i32(i32) -> i8 { @@ -86,9 +86,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_i64(i64) -> i8 { @@ -116,9 +116,9 @@ block2: ; ; Disassembled: ; 0: 03 00 0a 00 00 00 br_if x0, 0xa // target = 0xa -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 00 ret -; a: 0e 00 01 xconst8 x0, 1 +; a: 14 00 01 xconst8 x0, 1 ; d: 00 ret function %brif_icmp_i8(i8, i8) -> i8 { @@ -147,11 +147,11 @@ block2: ; ret ; ; Disassembled: -; 0: 1a 05 04 xeq32 x5, x0, x1 +; 0: 20 05 04 xeq32 x5, x0, x1 ; 3: 03 05 0a 00 00 00 br_if x5, 0xa // target = 0xd -; 9: 0e 00 00 xconst8 x0, 0 +; 9: 14 00 00 xconst8 x0, 0 ; c: 00 ret -; d: 0e 00 01 xconst8 x0, 1 +; d: 14 00 01 xconst8 x0, 1 ; 10: 00 ret function %brif_icmp_i16(i16, i16) -> i8 { @@ -180,11 +180,11 @@ block2: ; ret ; ; Disassembled: -; 0: 1b 05 04 xneq32 x5, x0, x1 +; 0: 21 05 04 xneq32 x5, x0, x1 ; 3: 03 05 0a 00 00 00 br_if x5, 0xa // target = 0xd -; 9: 0e 00 00 xconst8 x0, 0 +; 9: 14 00 00 xconst8 x0, 0 ; c: 00 ret -; d: 0e 00 01 xconst8 x0, 1 +; d: 14 00 01 xconst8 x0, 1 ; 10: 00 ret function %brif_icmp_i32(i32, i32) -> i8 { @@ -213,9 +213,9 @@ block2: ; ; Disassembled: ; 0: 07 00 01 0b 00 00 00 br_if_xslt32 x0, x1, 0xb // target = 0xb -; 7: 0e 00 00 xconst8 x0, 0 +; 7: 14 00 00 xconst8 x0, 0 ; a: 00 ret -; b: 0e 00 01 xconst8 x0, 1 +; b: 14 00 01 xconst8 x0, 1 ; e: 00 ret function %brif_icmp_i64(i64, i64) -> i8 { @@ -244,10 +244,10 @@ block2: ; ret ; ; Disassembled: -; 0: 19 25 00 xulteq64 x5, x1, x0 +; 0: 1f 25 00 xulteq64 x5, x1, x0 ; 3: 03 05 0a 00 00 00 br_if x5, 0xa // target = 0xd -; 9: 0e 00 00 xconst8 x0, 0 +; 9: 14 00 00 xconst8 x0, 0 ; c: 00 ret -; d: 0e 00 01 xconst8 x0, 1 +; d: 14 00 01 xconst8 x0, 1 ; 10: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/call.clif b/cranelift/filetests/filetests/isa/pulley64/call.clif index b787b0a58f50..294f04f3d825 100644 --- a/cranelift/filetests/filetests/isa/pulley64/call.clif +++ b/cranelift/filetests/filetests/isa/pulley64/call.clif @@ -19,7 +19,7 @@ block0: ; x29 = xmov x27 ; block0: ; x0 = xconst8 0 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [1204185006387685820006398, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 ; x28 = load64_u sp+8 // flags = notrap aligned ; x29 = load64_u sp+0 // flags = notrap aligned @@ -28,18 +28,18 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 00 00 xconst8 x0, 0 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 00 00 xconst8 x0, 0 ; 13: 01 00 00 00 00 call 0x0 // target = 0x13 -; 18: 0e 00 01 xconst8 x0, 1 -; 1b: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 1f: 22 1d 1b load64 fp, sp -; 22: 0e 1e 10 xconst8 spilltmp0, 16 -; 25: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 18: 14 00 01 xconst8 x0, 1 +; 1b: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 1f: 28 1d 1b load64 fp, sp +; 22: 14 1e 10 xconst8 spilltmp0, 16 +; 25: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 28: 00 ret function %colocated_args_i32_rets_i32() -> i32 { @@ -60,7 +60,7 @@ block0: ; x29 = xmov x27 ; block0: ; x0 = xconst8 0 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [1204185006387685820006398, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }], clobbers: PRegSet { bits: [65534, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x0 = xconst8 1 ; x28 = load64_u sp+8 // flags = notrap aligned ; x29 = load64_u sp+0 // flags = notrap aligned @@ -69,18 +69,18 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 00 00 xconst8 x0, 0 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 00 00 xconst8 x0, 0 ; 13: 01 00 00 00 00 call 0x0 // target = 0x13 -; 18: 0e 00 01 xconst8 x0, 1 -; 1b: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 1f: 22 1d 1b load64 fp, sp -; 22: 0e 1e 10 xconst8 spilltmp0, 16 -; 25: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 18: 14 00 01 xconst8 x0, 1 +; 1b: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 1f: 28 1d 1b load64 fp, sp +; 22: 14 1e 10 xconst8 spilltmp0, 16 +; 25: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 28: 00 ret function %colocated_args_i64_i32_i64_i32() { @@ -106,7 +106,7 @@ block0: ; x1 = xconst8 1 ; x2 = xconst8 2 ; x3 = xconst8 3 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [1204185006387685820006399, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x28 = load64_u sp+8 // flags = notrap aligned ; x29 = load64_u sp+0 // flags = notrap aligned ; x30 = xconst8 16 @@ -114,20 +114,20 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 00 00 xconst8 x0, 0 -; 13: 0e 01 01 xconst8 x1, 1 -; 16: 0e 02 02 xconst8 x2, 2 -; 19: 0e 03 03 xconst8 x3, 3 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 00 00 xconst8 x0, 0 +; 13: 14 01 01 xconst8 x1, 1 +; 16: 14 02 02 xconst8 x2, 2 +; 19: 14 03 03 xconst8 x3, 3 ; 1c: 01 00 00 00 00 call 0x0 // target = 0x1c -; 21: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 25: 22 1d 1b load64 fp, sp -; 28: 0e 1e 10 xconst8 spilltmp0, 16 -; 2b: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 21: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 25: 28 1d 1b load64 fp, sp +; 28: 14 1e 10 xconst8 spilltmp0, 16 +; 2b: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 2e: 00 ret function %colocated_rets_i64_i64_i64_i64() -> i64 { @@ -148,7 +148,7 @@ block0: ; store64 sp+0, x29 // flags = notrap aligned ; x29 = xmov x27 ; block0: -; call TestCase(%g), CallInfo { uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }], clobbers: PRegSet { bits: [1204185006387685820006384, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }], clobbers: PRegSet { bits: [65520, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x4 = xadd64 x0, x2 ; x3 = xadd64 x1, x3 ; x0 = xadd64 x4, x3 @@ -159,19 +159,19 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp ; 10: 01 00 00 00 00 call 0x0 // target = 0x10 -; 15: 13 04 08 xadd64 x4, x0, x2 -; 18: 13 23 0c xadd64 x3, x1, x3 -; 1b: 13 80 0c xadd64 x0, x4, x3 -; 1e: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 22: 22 1d 1b load64 fp, sp -; 25: 0e 1e 10 xconst8 spilltmp0, 16 -; 28: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 15: 19 04 08 xadd64 x4, x0, x2 +; 18: 19 23 0c xadd64 x3, x1, x3 +; 1b: 19 80 0c xadd64 x0, x4, x3 +; 1e: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 22: 28 1d 1b load64 fp, sp +; 25: 14 1e 10 xconst8 spilltmp0, 16 +; 28: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 2b: 00 ret function %colocated_stack_args() { @@ -214,7 +214,7 @@ block0: ; x12 = xmov x15 ; x13 = xmov x15 ; x14 = xmov x15 -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [1204185006387685820006399, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }, CallArgPair { vreg: p15i, preg: p15i }], defs: [], clobbers: PRegSet { bits: [65535, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x30 = xconst8 48 ; x27 = xadd32 x27, x30 ; x28 = load64_u sp+8 // flags = notrap aligned @@ -224,42 +224,42 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 1e d0 xconst8 spilltmp0, -48 -; 13: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 16: 0e 0f 00 xconst8 x15, 0 -; 19: 2a 1b 0f store64 sp, x15 -; 1c: 2c 1b 08 0f store64_offset8 sp, 8, x15 -; 20: 2c 1b 10 0f store64_offset8 sp, 16, x15 -; 24: 2c 1b 18 0f store64_offset8 sp, 24, x15 -; 28: 2c 1b 20 0f store64_offset8 sp, 32, x15 -; 2c: 2c 1b 28 0f store64_offset8 sp, 40, x15 -; 30: 0b 00 0f xmov x0, x15 -; 33: 0b 01 0f xmov x1, x15 -; 36: 0b 02 0f xmov x2, x15 -; 39: 0b 03 0f xmov x3, x15 -; 3c: 0b 04 0f xmov x4, x15 -; 3f: 0b 05 0f xmov x5, x15 -; 42: 0b 06 0f xmov x6, x15 -; 45: 0b 07 0f xmov x7, x15 -; 48: 0b 08 0f xmov x8, x15 -; 4b: 0b 09 0f xmov x9, x15 -; 4e: 0b 0a 0f xmov x10, x15 -; 51: 0b 0b 0f xmov x11, x15 -; 54: 0b 0c 0f xmov x12, x15 -; 57: 0b 0d 0f xmov x13, x15 -; 5a: 0b 0e 0f xmov x14, x15 +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 1e d0 xconst8 spilltmp0, -48 +; 13: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 16: 14 0f 00 xconst8 x15, 0 +; 19: 30 1b 0f store64 sp, x15 +; 1c: 32 1b 08 0f store64_offset8 sp, 8, x15 +; 20: 32 1b 10 0f store64_offset8 sp, 16, x15 +; 24: 32 1b 18 0f store64_offset8 sp, 24, x15 +; 28: 32 1b 20 0f store64_offset8 sp, 32, x15 +; 2c: 32 1b 28 0f store64_offset8 sp, 40, x15 +; 30: 11 00 0f xmov x0, x15 +; 33: 11 01 0f xmov x1, x15 +; 36: 11 02 0f xmov x2, x15 +; 39: 11 03 0f xmov x3, x15 +; 3c: 11 04 0f xmov x4, x15 +; 3f: 11 05 0f xmov x5, x15 +; 42: 11 06 0f xmov x6, x15 +; 45: 11 07 0f xmov x7, x15 +; 48: 11 08 0f xmov x8, x15 +; 4b: 11 09 0f xmov x9, x15 +; 4e: 11 0a 0f xmov x10, x15 +; 51: 11 0b 0f xmov x11, x15 +; 54: 11 0c 0f xmov x12, x15 +; 57: 11 0d 0f xmov x13, x15 +; 5a: 11 0e 0f xmov x14, x15 ; 5d: 01 00 00 00 00 call 0x0 // target = 0x5d -; 62: 0e 1e 30 xconst8 spilltmp0, 48 -; 65: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 68: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 6c: 22 1d 1b load64 fp, sp -; 6f: 0e 1e 10 xconst8 spilltmp0, 16 -; 72: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 62: 14 1e 30 xconst8 spilltmp0, 48 +; 65: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 68: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 6c: 28 1d 1b load64 fp, sp +; 6f: 14 1e 10 xconst8 spilltmp0, 16 +; 72: 18 7b 7b xadd32 sp, sp, spilltmp0 ; 75: 00 ret function %colocated_stack_rets() -> i64 { @@ -310,7 +310,7 @@ block0: ; store64 sp+48, x18 // flags = notrap aligned ; block0: ; x0 = load_addr OutgoingArg(0) -; call TestCase(%g), CallInfo { uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }, CallRetPair { vreg: Writable { reg: p4i }, preg: p4i }, CallRetPair { vreg: Writable { reg: p5i }, preg: p5i }, CallRetPair { vreg: Writable { reg: p6i }, preg: p6i }, CallRetPair { vreg: Writable { reg: p7i }, preg: p7i }, CallRetPair { vreg: Writable { reg: p8i }, preg: p8i }, CallRetPair { vreg: Writable { reg: p9i }, preg: p9i }, CallRetPair { vreg: Writable { reg: p10i }, preg: p10i }, CallRetPair { vreg: Writable { reg: p11i }, preg: p11i }, CallRetPair { vreg: Writable { reg: p12i }, preg: p12i }, CallRetPair { vreg: Writable { reg: p13i }, preg: p13i }, CallRetPair { vreg: Writable { reg: p14i }, preg: p14i }, CallRetPair { vreg: Writable { reg: p15i }, preg: p15i }], clobbers: PRegSet { bits: [1204185006387685819940864, 4294967295] }, callee_pop_size: 0 } +; call CallInfo { dest: TestCase(%g), uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, preg: p0i }, CallRetPair { vreg: Writable { reg: p1i }, preg: p1i }, CallRetPair { vreg: Writable { reg: p2i }, preg: p2i }, CallRetPair { vreg: Writable { reg: p3i }, preg: p3i }, CallRetPair { vreg: Writable { reg: p4i }, preg: p4i }, CallRetPair { vreg: Writable { reg: p5i }, preg: p5i }, CallRetPair { vreg: Writable { reg: p6i }, preg: p6i }, CallRetPair { vreg: Writable { reg: p7i }, preg: p7i }, CallRetPair { vreg: Writable { reg: p8i }, preg: p8i }, CallRetPair { vreg: Writable { reg: p9i }, preg: p9i }, CallRetPair { vreg: Writable { reg: p10i }, preg: p10i }, CallRetPair { vreg: Writable { reg: p11i }, preg: p11i }, CallRetPair { vreg: Writable { reg: p12i }, preg: p12i }, CallRetPair { vreg: Writable { reg: p13i }, preg: p13i }, CallRetPair { vreg: Writable { reg: p14i }, preg: p14i }, CallRetPair { vreg: Writable { reg: p15i }, preg: p15i }], clobbers: PRegSet { bits: [0, 65279, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0 } ; x16 = xmov x13 ; x18 = xmov x11 ; x25 = load64_u OutgoingArg(0) // flags = notrap aligned @@ -354,56 +354,56 @@ block0: ; ret ; ; Disassembled: -; 0: 0e 1e f0 xconst8 spilltmp0, -16 -; 3: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 6: 2c 1b 08 1c store64_offset8 sp, 8, lr -; a: 2a 1b 1d store64 sp, fp -; d: 0b 1d 1b xmov fp, sp -; 10: 0e 1e c0 xconst8 spilltmp0, -64 -; 13: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 16: 2c 1b 38 10 store64_offset8 sp, 56, x16 -; 1a: 2c 1b 30 12 store64_offset8 sp, 48, x18 -; 1e: 0b 00 1b xmov x0, sp +; 0: 14 1e f0 xconst8 spilltmp0, -16 +; 3: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 6: 32 1b 08 1c store64_offset8 sp, 8, lr +; a: 30 1b 1d store64 sp, fp +; d: 11 1d 1b xmov fp, sp +; 10: 14 1e c0 xconst8 spilltmp0, -64 +; 13: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 16: 32 1b 38 10 store64_offset8 sp, 56, x16 +; 1a: 32 1b 30 12 store64_offset8 sp, 48, x18 +; 1e: 11 00 1b xmov x0, sp ; 21: 01 00 00 00 00 call 0x0 // target = 0x21 -; 26: 0b 10 0d xmov x16, x13 -; 29: 0b 12 0b xmov x18, x11 -; 2c: 22 19 1b load64 x25, sp -; 2f: 25 0b 1b 08 load64_offset8 x11, sp, 8 -; 33: 25 0d 1b 10 load64_offset8 x13, sp, 16 -; 37: 25 1f 1b 18 load64_offset8 spilltmp1, sp, 24 -; 3b: 25 11 1b 20 load64_offset8 x17, sp, 32 -; 3f: 13 1e 04 xadd64 spilltmp0, x0, x1 -; 42: 13 5d 0c xadd64 fp, x2, x3 -; 45: 13 85 14 xadd64 x5, x4, x5 -; 48: 13 c6 1c xadd64 x6, x6, x7 -; 4b: 13 07 25 xadd64 x7, x8, x9 -; 4e: 0b 00 12 xmov x0, x18 -; 51: 13 44 01 xadd64 x4, x10, x0 -; 54: 0b 0a 10 xmov x10, x16 -; 57: 13 88 29 xadd64 x8, x12, x10 -; 5a: 13 ce 3d xadd64 x14, x14, x15 -; 5d: 13 2f 2f xadd64 x15, x25, x11 -; 60: 13 6d 35 xadd64 x13, x11, x13 -; 63: 13 e0 47 xadd64 x0, spilltmp1, x17 -; 66: 13 c1 77 xadd64 x1, spilltmp0, fp -; 69: 13 a2 18 xadd64 x2, x5, x6 -; 6c: 13 e3 10 xadd64 x3, x7, x4 -; 6f: 13 0e 39 xadd64 x14, x8, x14 -; 72: 13 ed 35 xadd64 x13, x15, x13 -; 75: 13 0f 00 xadd64 x15, x0, x0 -; 78: 13 20 08 xadd64 x0, x1, x2 -; 7b: 13 6e 38 xadd64 x14, x3, x14 -; 7e: 13 ad 3d xadd64 x13, x13, x15 -; 81: 13 0e 38 xadd64 x14, x0, x14 -; 84: 13 ad 35 xadd64 x13, x13, x13 -; 87: 13 c0 35 xadd64 x0, x14, x13 -; 8a: 25 10 1b 38 load64_offset8 x16, sp, 56 -; 8e: 25 12 1b 30 load64_offset8 x18, sp, 48 -; 92: 0e 1e 40 xconst8 spilltmp0, 64 -; 95: 12 7b 7b xadd32 sp, sp, spilltmp0 -; 98: 25 1c 1b 08 load64_offset8 lr, sp, 8 -; 9c: 22 1d 1b load64 fp, sp -; 9f: 0e 1e 10 xconst8 spilltmp0, 16 -; a2: 12 7b 7b xadd32 sp, sp, spilltmp0 +; 26: 11 10 0d xmov x16, x13 +; 29: 11 12 0b xmov x18, x11 +; 2c: 28 19 1b load64 x25, sp +; 2f: 2b 0b 1b 08 load64_offset8 x11, sp, 8 +; 33: 2b 0d 1b 10 load64_offset8 x13, sp, 16 +; 37: 2b 1f 1b 18 load64_offset8 spilltmp1, sp, 24 +; 3b: 2b 11 1b 20 load64_offset8 x17, sp, 32 +; 3f: 19 1e 04 xadd64 spilltmp0, x0, x1 +; 42: 19 5d 0c xadd64 fp, x2, x3 +; 45: 19 85 14 xadd64 x5, x4, x5 +; 48: 19 c6 1c xadd64 x6, x6, x7 +; 4b: 19 07 25 xadd64 x7, x8, x9 +; 4e: 11 00 12 xmov x0, x18 +; 51: 19 44 01 xadd64 x4, x10, x0 +; 54: 11 0a 10 xmov x10, x16 +; 57: 19 88 29 xadd64 x8, x12, x10 +; 5a: 19 ce 3d xadd64 x14, x14, x15 +; 5d: 19 2f 2f xadd64 x15, x25, x11 +; 60: 19 6d 35 xadd64 x13, x11, x13 +; 63: 19 e0 47 xadd64 x0, spilltmp1, x17 +; 66: 19 c1 77 xadd64 x1, spilltmp0, fp +; 69: 19 a2 18 xadd64 x2, x5, x6 +; 6c: 19 e3 10 xadd64 x3, x7, x4 +; 6f: 19 0e 39 xadd64 x14, x8, x14 +; 72: 19 ed 35 xadd64 x13, x15, x13 +; 75: 19 0f 00 xadd64 x15, x0, x0 +; 78: 19 20 08 xadd64 x0, x1, x2 +; 7b: 19 6e 38 xadd64 x14, x3, x14 +; 7e: 19 ad 3d xadd64 x13, x13, x15 +; 81: 19 0e 38 xadd64 x14, x0, x14 +; 84: 19 ad 35 xadd64 x13, x13, x13 +; 87: 19 c0 35 xadd64 x0, x14, x13 +; 8a: 2b 10 1b 38 load64_offset8 x16, sp, 56 +; 8e: 2b 12 1b 30 load64_offset8 x18, sp, 48 +; 92: 14 1e 40 xconst8 spilltmp0, 64 +; 95: 18 7b 7b xadd32 sp, sp, spilltmp0 +; 98: 2b 1c 1b 08 load64_offset8 lr, sp, 8 +; 9c: 28 1d 1b load64 fp, sp +; 9f: 14 1e 10 xconst8 spilltmp0, 16 +; a2: 18 7b 7b xadd32 sp, sp, spilltmp0 ; a5: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif b/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif index f2520abaeef2..3d191c57ee82 100644 --- a/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif +++ b/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif @@ -13,5 +13,6 @@ block0: ; ret ; ; Disassembled: -; 0: 3d 02 00 00 get_sp x0 +; 0: 43 02 00 00 get_sp x0 ; 4: 00 ret + diff --git a/cranelift/filetests/filetests/isa/pulley64/iadd.clif b/cranelift/filetests/filetests/isa/pulley64/iadd.clif index 7a6cffde6e6d..16c33036fc1e 100644 --- a/cranelift/filetests/filetests/isa/pulley64/iadd.clif +++ b/cranelift/filetests/filetests/isa/pulley64/iadd.clif @@ -13,7 +13,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 12 00 04 xadd32 x0, x0, x1 +; 0: 18 00 04 xadd32 x0, x0, x1 ; 3: 00 ret function %i16(i16, i16) -> i16 { @@ -28,7 +28,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 12 00 04 xadd32 x0, x0, x1 +; 0: 18 00 04 xadd32 x0, x0, x1 ; 3: 00 ret function %i32(i32, i32) -> i32 { @@ -43,7 +43,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 12 00 04 xadd32 x0, x0, x1 +; 0: 18 00 04 xadd32 x0, x0, x1 ; 3: 00 ret function %i64(i64, i64) -> i64 { @@ -58,6 +58,6 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 13 00 04 xadd64 x0, x0, x1 +; 0: 19 00 04 xadd64 x0, x0, x1 ; 3: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/icmp.clif b/cranelift/filetests/filetests/isa/pulley64/icmp.clif index 7aaf069f584e..15a09aae84bb 100644 --- a/cranelift/filetests/filetests/isa/pulley64/icmp.clif +++ b/cranelift/filetests/filetests/isa/pulley64/icmp.clif @@ -13,7 +13,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1a 00 04 xeq32 x0, x0, x1 +; 0: 20 00 04 xeq32 x0, x0, x1 ; 3: 00 ret function %i16_eq(i16, i16) -> i8 { @@ -28,7 +28,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1a 00 04 xeq32 x0, x0, x1 +; 0: 20 00 04 xeq32 x0, x0, x1 ; 3: 00 ret function %i32_eq(i32, i32) -> i8 { @@ -43,7 +43,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1a 00 04 xeq32 x0, x0, x1 +; 0: 20 00 04 xeq32 x0, x0, x1 ; 3: 00 ret function %i64_eq(i64, i64) -> i8 { @@ -58,7 +58,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 14 00 04 xeq64 x0, x0, x1 +; 0: 1a 00 04 xeq64 x0, x0, x1 ; 3: 00 ret function %i8_ne(i8, i8) -> i8 { @@ -73,7 +73,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1b 00 04 xneq32 x0, x0, x1 +; 0: 21 00 04 xneq32 x0, x0, x1 ; 3: 00 ret function %i16_ne(i16, i16) -> i8 { @@ -88,7 +88,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1b 00 04 xneq32 x0, x0, x1 +; 0: 21 00 04 xneq32 x0, x0, x1 ; 3: 00 ret function %i32_ne(i32, i32) -> i8 { @@ -103,7 +103,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1b 00 04 xneq32 x0, x0, x1 +; 0: 21 00 04 xneq32 x0, x0, x1 ; 3: 00 ret function %i64_ne(i64, i64) -> i8 { @@ -118,7 +118,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 15 00 04 xneq64 x0, x0, x1 +; 0: 1b 00 04 xneq64 x0, x0, x1 ; 3: 00 ret function %i8_ult(i8, i8) -> i8 { @@ -133,7 +133,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1e 00 04 xult32 x0, x0, x1 +; 0: 24 00 04 xult32 x0, x0, x1 ; 3: 00 ret function %i16_ult(i16, i16) -> i8 { @@ -148,7 +148,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1e 00 04 xult32 x0, x0, x1 +; 0: 24 00 04 xult32 x0, x0, x1 ; 3: 00 ret function %i32_ult(i32, i32) -> i8 { @@ -163,7 +163,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1e 00 04 xult32 x0, x0, x1 +; 0: 24 00 04 xult32 x0, x0, x1 ; 3: 00 ret function %i64_ult(i64, i64) -> i8 { @@ -178,7 +178,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 18 00 04 xult64 x0, x0, x1 +; 0: 1e 00 04 xult64 x0, x0, x1 ; 3: 00 ret function %i8_ule(i8, i8) -> i8 { @@ -193,7 +193,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1f 00 04 xulteq32 x0, x0, x1 +; 0: 25 00 04 xulteq32 x0, x0, x1 ; 3: 00 ret function %i16_ule(i16, i16) -> i8 { @@ -208,7 +208,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1f 00 04 xulteq32 x0, x0, x1 +; 0: 25 00 04 xulteq32 x0, x0, x1 ; 3: 00 ret function %i32_ule(i32, i32) -> i8 { @@ -223,7 +223,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1f 00 04 xulteq32 x0, x0, x1 +; 0: 25 00 04 xulteq32 x0, x0, x1 ; 3: 00 ret function %i64_ule(i64, i64) -> i8 { @@ -238,7 +238,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 19 00 04 xulteq64 x0, x0, x1 +; 0: 1f 00 04 xulteq64 x0, x0, x1 ; 3: 00 ret function %i8_slt(i8, i8) -> i8 { @@ -253,7 +253,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1c 00 04 xslt32 x0, x0, x1 +; 0: 22 00 04 xslt32 x0, x0, x1 ; 3: 00 ret function %i16_slt(i16, i16) -> i8 { @@ -268,7 +268,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1c 00 04 xslt32 x0, x0, x1 +; 0: 22 00 04 xslt32 x0, x0, x1 ; 3: 00 ret function %i32_slt(i32, i32) -> i8 { @@ -283,7 +283,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1c 00 04 xslt32 x0, x0, x1 +; 0: 22 00 04 xslt32 x0, x0, x1 ; 3: 00 ret function %i64_slt(i64, i64) -> i8 { @@ -298,7 +298,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 16 00 04 xslt64 x0, x0, x1 +; 0: 1c 00 04 xslt64 x0, x0, x1 ; 3: 00 ret function %i8_sle(i8, i8) -> i8 { @@ -313,7 +313,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1d 00 04 xslteq32 x0, x0, x1 +; 0: 23 00 04 xslteq32 x0, x0, x1 ; 3: 00 ret function %i16_sle(i16, i16) -> i8 { @@ -328,7 +328,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1d 00 04 xslteq32 x0, x0, x1 +; 0: 23 00 04 xslteq32 x0, x0, x1 ; 3: 00 ret function %i32_sle(i32, i32) -> i8 { @@ -343,7 +343,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1d 00 04 xslteq32 x0, x0, x1 +; 0: 23 00 04 xslteq32 x0, x0, x1 ; 3: 00 ret function %i64_sle(i64, i64) -> i8 { @@ -358,7 +358,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 17 00 04 xslteq64 x0, x0, x1 +; 0: 1d 00 04 xslteq64 x0, x0, x1 ; 3: 00 ret function %i8_ugt(i8, i8) -> i8 { @@ -373,7 +373,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1e 20 00 xult32 x0, x1, x0 +; 0: 24 20 00 xult32 x0, x1, x0 ; 3: 00 ret function %i16_ugt(i16, i16) -> i8 { @@ -388,7 +388,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1e 20 00 xult32 x0, x1, x0 +; 0: 24 20 00 xult32 x0, x1, x0 ; 3: 00 ret function %i32_ugt(i32, i32) -> i8 { @@ -403,7 +403,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1e 20 00 xult32 x0, x1, x0 +; 0: 24 20 00 xult32 x0, x1, x0 ; 3: 00 ret function %i64_ugt(i64, i64) -> i8 { @@ -418,7 +418,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 18 20 00 xult64 x0, x1, x0 +; 0: 1e 20 00 xult64 x0, x1, x0 ; 3: 00 ret function %i8_sgt(i8, i8) -> i8 { @@ -433,7 +433,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1c 20 00 xslt32 x0, x1, x0 +; 0: 22 20 00 xslt32 x0, x1, x0 ; 3: 00 ret function %i16_sgt(i16, i16) -> i8 { @@ -448,7 +448,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1c 20 00 xslt32 x0, x1, x0 +; 0: 22 20 00 xslt32 x0, x1, x0 ; 3: 00 ret function %i32_sgt(i32, i32) -> i8 { @@ -463,7 +463,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1c 20 00 xslt32 x0, x1, x0 +; 0: 22 20 00 xslt32 x0, x1, x0 ; 3: 00 ret function %i64_sgt(i64, i64) -> i8 { @@ -478,7 +478,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 16 20 00 xslt64 x0, x1, x0 +; 0: 1c 20 00 xslt64 x0, x1, x0 ; 3: 00 ret function %i8_uge(i8, i8) -> i8 { @@ -493,7 +493,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1f 20 00 xulteq32 x0, x1, x0 +; 0: 25 20 00 xulteq32 x0, x1, x0 ; 3: 00 ret function %i16_uge(i16, i16) -> i8 { @@ -508,7 +508,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1f 20 00 xulteq32 x0, x1, x0 +; 0: 25 20 00 xulteq32 x0, x1, x0 ; 3: 00 ret function %i32_uge(i32, i32) -> i8 { @@ -523,7 +523,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1f 20 00 xulteq32 x0, x1, x0 +; 0: 25 20 00 xulteq32 x0, x1, x0 ; 3: 00 ret function %i64_uge(i64, i64) -> i8 { @@ -538,7 +538,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 19 20 00 xulteq64 x0, x1, x0 +; 0: 1f 20 00 xulteq64 x0, x1, x0 ; 3: 00 ret function %i8_sge(i8, i8) -> i8 { @@ -553,7 +553,7 @@ block0(v0: i8, v1: i8): ; ret ; ; Disassembled: -; 0: 1d 20 00 xslteq32 x0, x1, x0 +; 0: 23 20 00 xslteq32 x0, x1, x0 ; 3: 00 ret function %i16_sge(i16, i16) -> i8 { @@ -568,7 +568,7 @@ block0(v0: i16, v1: i16): ; ret ; ; Disassembled: -; 0: 1d 20 00 xslteq32 x0, x1, x0 +; 0: 23 20 00 xslteq32 x0, x1, x0 ; 3: 00 ret function %i32_sge(i32, i32) -> i8 { @@ -583,7 +583,7 @@ block0(v0: i32, v1: i32): ; ret ; ; Disassembled: -; 0: 1d 20 00 xslteq32 x0, x1, x0 +; 0: 23 20 00 xslteq32 x0, x1, x0 ; 3: 00 ret function %i64_sge(i64, i64) -> i8 { @@ -598,6 +598,6 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 17 20 00 xslteq64 x0, x1, x0 +; 0: 1d 20 00 xslteq64 x0, x1, x0 ; 3: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/iconst.clif b/cranelift/filetests/filetests/isa/pulley64/iconst.clif index 36ae9b0095f4..c6edbbdba8b5 100644 --- a/cranelift/filetests/filetests/isa/pulley64/iconst.clif +++ b/cranelift/filetests/filetests/isa/pulley64/iconst.clif @@ -13,7 +13,7 @@ block0: ; ret ; ; Disassembled: -; 0: 0f 00 ff 00 xconst16 x0, 255 +; 0: 15 00 ff 00 xconst16 x0, 255 ; 4: 00 ret function %i16() -> i16 { @@ -28,7 +28,7 @@ block0: ; ret ; ; Disassembled: -; 0: 10 00 ff ff 00 00 xconst32 x0, 65535 +; 0: 16 00 ff ff 00 00 xconst32 x0, 65535 ; 6: 00 ret function %i32() -> i32 { @@ -43,7 +43,7 @@ block0: ; ret ; ; Disassembled: -; 0: 10 00 ff ff ff ff xconst32 x0, -1 +; 0: 16 00 ff ff ff ff xconst32 x0, -1 ; 6: 00 ret function %i64() -> i64 { @@ -58,6 +58,6 @@ block0: ; ret ; ; Disassembled: -; 0: 11 00 ff ff ff ff ff ff ff ff xconst64 x0, -1 +; 0: 17 00 ff ff ff ff ff ff ff ff xconst64 x0, -1 ; a: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/jump.clif b/cranelift/filetests/filetests/isa/pulley64/jump.clif index 011984697dcf..6694e3a81da0 100644 --- a/cranelift/filetests/filetests/isa/pulley64/jump.clif +++ b/cranelift/filetests/filetests/isa/pulley64/jump.clif @@ -31,8 +31,8 @@ block3(v3: i8): ; ; Disassembled: ; 0: 03 00 0e 00 00 00 br_if x0, 0xe // target = 0xe -; 6: 0e 00 00 xconst8 x0, 0 +; 6: 14 00 00 xconst8 x0, 0 ; 9: 02 08 00 00 00 jump 0x8 // target = 0x11 -; e: 0e 00 01 xconst8 x0, 1 +; e: 14 00 01 xconst8 x0, 1 ; 11: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/load.clif b/cranelift/filetests/filetests/isa/pulley64/load.clif index a692da083b5b..4e7c5b4753ca 100644 --- a/cranelift/filetests/filetests/isa/pulley64/load.clif +++ b/cranelift/filetests/filetests/isa/pulley64/load.clif @@ -13,7 +13,7 @@ block0(v0: i64): ; ret ; ; Disassembled: -; 0: 20 00 00 load32_u x0, x0 +; 0: 26 00 00 load32_u x0, x0 ; 3: 00 ret function %load_i64(i64) -> i64 { @@ -28,7 +28,7 @@ block0(v0: i64): ; ret ; ; Disassembled: -; 0: 22 00 00 load64 x0, x0 +; 0: 28 00 00 load64 x0, x0 ; 3: 00 ret function %load_i32_with_offset(i64) -> i32 { @@ -43,7 +43,7 @@ block0(v0: i64): ; ret ; ; Disassembled: -; 0: 23 00 00 04 load32_u_offset8 x0, x0, 4 +; 0: 29 00 00 04 load32_u_offset8 x0, x0, 4 ; 4: 00 ret function %load_i64_with_offset(i64) -> i64 { @@ -58,5 +58,6 @@ block0(v0: i64): ; ret ; ; Disassembled: -; 0: 25 00 00 08 load64_offset8 x0, x0, 8 +; 0: 2b 00 00 08 load64_offset8 x0, x0, 8 ; 4: 00 ret + diff --git a/cranelift/filetests/filetests/isa/pulley64/store.clif b/cranelift/filetests/filetests/isa/pulley64/store.clif index bec7e1a77344..21aa9297cc7e 100644 --- a/cranelift/filetests/filetests/isa/pulley64/store.clif +++ b/cranelift/filetests/filetests/isa/pulley64/store.clif @@ -13,7 +13,7 @@ block0(v0: i32, v1: i64): ; ret ; ; Disassembled: -; 0: 29 01 00 store32 x1, x0 +; 0: 2f 01 00 store32 x1, x0 ; 3: 00 ret function %store_i64(i64, i64) { @@ -28,7 +28,7 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 2a 01 00 store64 x1, x0 +; 0: 30 01 00 store64 x1, x0 ; 3: 00 ret function %store_i32_with_offset(i32, i64) { @@ -43,7 +43,7 @@ block0(v0: i32, v1: i64): ; ret ; ; Disassembled: -; 0: 2b 01 04 00 store32_offset8 x1, 4, x0 +; 0: 31 01 04 00 store32_offset8 x1, 4, x0 ; 4: 00 ret function %store_i64_with_offset(i64, i64) { @@ -58,6 +58,6 @@ block0(v0: i64, v1: i64): ; ret ; ; Disassembled: -; 0: 2c 01 08 00 store64_offset8 x1, 8, x0 +; 0: 32 01 08 00 store64_offset8 x1, 8, x0 ; 4: 00 ret diff --git a/cranelift/filetests/filetests/isa/pulley64/trap.clif b/cranelift/filetests/filetests/isa/pulley64/trap.clif index 7615f2a74685..b00ee9f84985 100644 --- a/cranelift/filetests/filetests/isa/pulley64/trap.clif +++ b/cranelift/filetests/filetests/isa/pulley64/trap.clif @@ -11,7 +11,7 @@ block0: ; trap // code = User(0) ; ; Disassembled: -; 0: 3d 00 00 trap +; 0: 43 00 00 trap function %trapnz(i64) { block0(v0: i64): @@ -32,11 +32,11 @@ block0(v0: i64): ; trap // code = User(0) ; ; Disassembled: -; 0: 0e 03 2a xconst8 x3, 42 -; 3: 14 03 0c xeq64 x3, x0, x3 +; 0: 14 03 2a xconst8 x3, 42 +; 3: 1a 03 0c xeq64 x3, x0, x3 ; 6: 03 03 07 00 00 00 br_if x3, 0x7 // target = 0xd ; c: 00 ret -; d: 3d 00 00 trap +; d: 43 00 00 trap function %trapz(i64) { block0(v0: i64): @@ -57,8 +57,9 @@ block0(v0: i64): ; trap // code = User(0) ; ; Disassembled: -; 0: 0e 03 2a xconst8 x3, 42 -; 3: 14 03 0c xeq64 x3, x0, x3 +; 0: 14 03 2a xconst8 x3, 42 +; 3: 1a 03 0c xeq64 x3, x0, x3 ; 6: 04 03 07 00 00 00 br_if_not x3, 0x7 // target = 0xd ; c: 00 ret -; d: 3d 00 00 trap +; d: 43 00 00 trap + diff --git a/cranelift/filetests/filetests/isa/riscv64/amodes.clif b/cranelift/filetests/filetests/isa/riscv64/amodes.clif index 545eaf7cedd0..678b86f30200 100644 --- a/cranelift/filetests/filetests/isa/riscv64/amodes.clif +++ b/cranelift/filetests/filetests/isa/riscv64/amodes.clif @@ -387,21 +387,19 @@ block0(v0: i64): ; VCode: ; block0: ; ld a2,0(a0) -; mv a4,a2 ; ld a1,8(a0) ; sd a2,0(a0) ; sd a1,8(a0) -; mv a0,a4 +; mv a0,a2 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; ld a2, 0(a0) ; trap: heap_oob -; mv a4, a2 ; ld a1, 8(a0) ; trap: heap_oob ; sd a2, 0(a0) ; trap: heap_oob ; sd a1, 8(a0) ; trap: heap_oob -; mv a0, a4 +; mv a0, a2 ; ret function %i128_imm_offset(i64) -> i128 { @@ -414,21 +412,19 @@ block0(v0: i64): ; VCode: ; block0: ; ld a2,16(a0) -; mv a4,a2 ; ld a1,24(a0) ; sd a2,16(a0) ; sd a1,24(a0) -; mv a0,a4 +; mv a0,a2 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; ld a2, 0x10(a0) ; trap: heap_oob -; mv a4, a2 ; ld a1, 0x18(a0) ; trap: heap_oob ; sd a2, 0x10(a0) ; trap: heap_oob ; sd a1, 0x18(a0) ; trap: heap_oob -; mv a0, a4 +; mv a0, a2 ; ret function %i128_imm_offset_large(i64) -> i128 { @@ -441,21 +437,19 @@ block0(v0: i64): ; VCode: ; block0: ; ld a2,504(a0) -; mv a4,a2 ; ld a1,512(a0) ; sd a2,504(a0) ; sd a1,512(a0) -; mv a0,a4 +; mv a0,a2 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; ld a2, 0x1f8(a0) ; trap: heap_oob -; mv a4, a2 ; ld a1, 0x200(a0) ; trap: heap_oob ; sd a2, 0x1f8(a0) ; trap: heap_oob ; sd a1, 0x200(a0) ; trap: heap_oob -; mv a0, a4 +; mv a0, a2 ; ret function %i128_imm_offset_negative_large(i64) -> i128 { @@ -468,21 +462,19 @@ block0(v0: i64): ; VCode: ; block0: ; ld a2,-512(a0) -; mv a4,a2 ; ld a1,-504(a0) ; sd a2,-512(a0) ; sd a1,-504(a0) -; mv a0,a4 +; mv a0,a2 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; ld a2, -0x200(a0) ; trap: heap_oob -; mv a4, a2 ; ld a1, -0x1f8(a0) ; trap: heap_oob ; sd a2, -0x200(a0) ; trap: heap_oob ; sd a1, -0x1f8(a0) ; trap: heap_oob -; mv a0, a4 +; mv a0, a2 ; ret function %i128_add_offset(i64) -> i128 { @@ -496,21 +488,19 @@ block0(v0: i64): ; VCode: ; block0: ; ld a2,32(a0) -; mv a4,a2 ; ld a1,40(a0) ; sd a2,32(a0) ; sd a1,40(a0) -; mv a0,a4 +; mv a0,a2 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; ld a2, 0x20(a0) ; trap: heap_oob -; mv a4, a2 ; ld a1, 0x28(a0) ; trap: heap_oob ; sd a2, 0x20(a0) ; trap: heap_oob ; sd a1, 0x28(a0) ; trap: heap_oob -; mv a0, a4 +; mv a0, a2 ; ret function %i128_32bit_sextend_simple(i32) -> i128 { @@ -554,11 +544,10 @@ block0(v0: i64, v1: i32): ; sext.w a1,a1 ; add a0,a0,a1 ; ld a5,24(a0) -; mv a2,a5 ; ld a1,32(a0) ; sd a5,24(a0) ; sd a1,32(a0) -; mv a0,a2 +; mv a0,a5 ; ret ; ; Disassembled: @@ -566,11 +555,10 @@ block0(v0: i64, v1: i32): ; sext.w a1, a1 ; add a0, a0, a1 ; ld a5, 0x18(a0) ; trap: heap_oob -; mv a2, a5 ; ld a1, 0x20(a0) ; trap: heap_oob ; sd a5, 0x18(a0) ; trap: heap_oob ; sd a1, 0x20(a0) ; trap: heap_oob -; mv a0, a2 +; mv a0, a5 ; ret function %load_from_get_stack_pointer() -> i64 { diff --git a/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif b/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif index 9f20971c8c5a..775137e8fb30 100644 --- a/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif +++ b/cranelift/filetests/filetests/isa/riscv64/arithmetic.clif @@ -587,21 +587,19 @@ block0(v0: i128, v1: i128): ; VCode: ; block0: ; sub a5,a0,a2 -; mv a4,a5 -; sltu a2,a0,a4 -; mv a0,a4 +; sltu a2,a0,a5 ; sub a3,a1,a3 ; sub a1,a3,a2 +; mv a0,a5 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; sub a5, a0, a2 -; mv a4, a5 -; sltu a2, a0, a4 -; mv a0, a4 +; sltu a2, a0, a5 ; sub a3, a1, a3 ; sub a1, a3, a2 +; mv a0, a5 ; ret function %add_mul_2(i32, i32, i32) -> i32 { diff --git a/cranelift/filetests/filetests/isa/riscv64/bitrev.clif b/cranelift/filetests/filetests/isa/riscv64/bitrev.clif index 83b8c91fab96..2d03516441cb 100644 --- a/cranelift/filetests/filetests/isa/riscv64/bitrev.clif +++ b/cranelift/filetests/filetests/isa/riscv64/bitrev.clif @@ -361,12 +361,6 @@ block0(v0: i128): } ; VCode: -; addi sp,sp,-16 -; sd ra,8(sp) -; sd fp,0(sp) -; mv fp,sp -; addi sp,sp,-16 -; sd s3,8(sp) ; block0: ; slli a3,a1,8 ; srli a5,a1,8 @@ -404,60 +398,47 @@ block0(v0: i128): ; srli a4,a1,32 ; or a5,a3,a4 ; brev8 a4,a5##tmp=a1 tmp2=a2 step=a3 ty=i64 -; mv s3,a4 ; slli a1,a0,8 ; srli a2,a0,8 -; slli a4,a2,56 -; srli a2,a4,56 +; slli a5,a2,56 +; srli a2,a5,56 ; or a2,a1,a2 -; slli a4,a2,16 +; slli a5,a2,16 ; srli a1,a0,16 ; slli a2,a1,8 -; srli a5,a1,8 -; slli a1,a5,56 +; srli a1,a1,8 +; slli a1,a1,56 ; srli a3,a1,56 -; or a5,a2,a3 -; slli a1,a5,48 +; or a1,a2,a3 +; slli a1,a1,48 ; srli a2,a1,48 -; or a4,a4,a2 -; slli a1,a4,32 +; or a5,a5,a2 +; slli a1,a5,32 ; srli a3,a0,32 -; slli a4,a3,8 +; slli a5,a3,8 ; srli a0,a3,8 ; slli a2,a0,56 -; srli a5,a2,56 -; or a0,a4,a5 +; srli a0,a2,56 +; or a0,a5,a0 ; slli a2,a0,16 -; srli a4,a3,16 -; slli a0,a4,8 -; srli a3,a4,8 -; slli a4,a3,56 -; srli a3,a4,56 +; srli a5,a3,16 +; slli a0,a5,8 +; srli a3,a5,8 +; slli a5,a3,56 +; srli a3,a5,56 ; or a3,a0,a3 -; slli a4,a3,48 -; srli a0,a4,48 +; slli a5,a3,48 +; srli a0,a5,48 ; or a2,a2,a0 -; slli a4,a2,32 -; srli a0,a4,32 -; or a2,a1,a0 -; brev8 a1,a2##tmp=a4 tmp2=a5 step=a0 ty=i64 -; mv a0,s3 -; ld s3,8(sp) -; addi sp,sp,16 -; ld ra,8(sp) -; ld fp,0(sp) -; addi sp,sp,16 +; slli a5,a2,32 +; srli a0,a5,32 +; or a3,a1,a0 +; brev8 a1,a3##tmp=a2 tmp2=a5 step=a0 ty=i64 +; mv a0,a4 ; ret ; ; Disassembled: ; block0: ; offset 0x0 -; addi sp, sp, -0x10 -; sd ra, 8(sp) -; sd s0, 0(sp) -; mv s0, sp -; addi sp, sp, -0x10 -; sd s3, 8(sp) -; block1: ; offset 0x18 ; slli a3, a1, 8 ; srli a5, a1, 8 ; slli a2, a5, 0x38 @@ -512,54 +493,53 @@ block0(v0: i128): ; j -0x28 ; slli a2, a2, 1 ; j -0x30 -; mv s3, a4 ; slli a1, a0, 8 ; srli a2, a0, 8 -; slli a4, a2, 0x38 -; srli a2, a4, 0x38 +; slli a5, a2, 0x38 +; srli a2, a5, 0x38 ; or a2, a1, a2 -; slli a4, a2, 0x10 +; slli a5, a2, 0x10 ; srli a1, a0, 0x10 ; slli a2, a1, 8 -; srli a5, a1, 8 -; slli a1, a5, 0x38 +; srli a1, a1, 8 +; slli a1, a1, 0x38 ; srli a3, a1, 0x38 -; or a5, a2, a3 -; slli a1, a5, 0x30 +; or a1, a2, a3 +; slli a1, a1, 0x30 ; srli a2, a1, 0x30 -; or a4, a4, a2 -; slli a1, a4, 0x20 +; or a5, a5, a2 +; slli a1, a5, 0x20 ; srli a3, a0, 0x20 -; slli a4, a3, 8 +; slli a5, a3, 8 ; srli a0, a3, 8 ; slli a2, a0, 0x38 -; srli a5, a2, 0x38 -; or a0, a4, a5 +; srli a0, a2, 0x38 +; or a0, a5, a0 ; slli a2, a0, 0x10 -; srli a4, a3, 0x10 -; slli a0, a4, 8 -; srli a3, a4, 8 -; slli a4, a3, 0x38 -; srli a3, a4, 0x38 +; srli a5, a3, 0x10 +; slli a0, a5, 8 +; srli a3, a5, 8 +; slli a5, a3, 0x38 +; srli a3, a5, 0x38 ; or a3, a0, a3 -; slli a4, a3, 0x30 -; srli a0, a4, 0x30 +; slli a5, a3, 0x30 +; srli a0, a5, 0x30 ; or a2, a2, a0 -; slli a4, a2, 0x20 -; srli a0, a4, 0x20 -; or a2, a1, a0 +; slli a5, a2, 0x20 +; srli a0, a5, 0x20 +; or a3, a1, a0 ; mv a1, zero ; addi a0, zero, 0x40 -; addi a4, zero, 1 -; slli a4, a4, 0x3f +; addi a2, zero, 1 +; slli a2, a2, 0x3f ; addi a5, zero, 1 ; slli a5, a5, 0x38 ; blez a0, 0x34 -; and t5, a4, a2 +; and t5, a2, a3 ; beq zero, t5, 8 ; or a1, a1, a5 ; addi a0, a0, -1 -; srli a4, a4, 1 +; srli a2, a2, 1 ; addi t5, zero, 8 ; rem t5, a0, t5 ; bnez t5, 0xc @@ -567,11 +547,6 @@ block0(v0: i128): ; j -0x28 ; slli a5, a5, 1 ; j -0x30 -; mv a0, s3 -; ld s3, 8(sp) -; addi sp, sp, 0x10 -; ld ra, 8(sp) -; ld s0, 0(sp) -; addi sp, sp, 0x10 +; mv a0, a4 ; ret diff --git a/cranelift/filetests/filetests/isa/riscv64/bswap.clif b/cranelift/filetests/filetests/isa/riscv64/bswap.clif index cbcfe12e57c0..4007284550c5 100644 --- a/cranelift/filetests/filetests/isa/riscv64/bswap.clif +++ b/cranelift/filetests/filetests/isa/riscv64/bswap.clif @@ -197,43 +197,42 @@ block0(v0: i128): ; slli a1,a5,32 ; srli a4,a1,32 ; or a5,a3,a4 -; mv t1,a5 ; slli a1,a0,8 ; srli a3,a0,8 -; slli a5,a3,56 -; srli a2,a5,56 +; slli a2,a3,56 +; srli a2,a2,56 ; or a3,a1,a2 -; slli a5,a3,16 -; srli a1,a0,16 -; slli a3,a1,8 -; srli a1,a1,8 -; slli a1,a1,56 -; srli a4,a1,56 -; or a1,a3,a4 -; slli a1,a1,48 -; srli a3,a1,48 -; or a5,a5,a3 -; slli a1,a5,32 +; slli a1,a3,16 +; srli a2,a0,16 +; slli a3,a2,8 +; srli a2,a2,8 +; slli a2,a2,56 +; srli a4,a2,56 +; or a2,a3,a4 +; slli a2,a2,48 +; srli a3,a2,48 +; or a1,a1,a3 +; slli a1,a1,32 ; srli a4,a0,32 -; slli a5,a4,8 +; slli a0,a4,8 ; srli a2,a4,8 ; slli a3,a2,56 -; srli a0,a3,56 -; or a2,a5,a0 +; srli a2,a3,56 +; or a2,a0,a2 ; slli a3,a2,16 -; srli a5,a4,16 -; slli a2,a5,8 -; srli a4,a5,8 -; slli a5,a4,56 -; srli a4,a5,56 +; srli a0,a4,16 +; slli a2,a0,8 +; srli a4,a0,8 +; slli a0,a4,56 +; srli a4,a0,56 ; or a4,a2,a4 -; slli a5,a4,48 -; srli a2,a5,48 +; slli a0,a4,48 +; srli a2,a0,48 ; or a3,a3,a2 -; slli a5,a3,32 -; srli a2,a5,32 +; slli a0,a3,32 +; srli a2,a0,32 ; or a1,a1,a2 -; mv a0,t1 +; mv a0,a5 ; ret ; ; Disassembled: @@ -273,42 +272,41 @@ block0(v0: i128): ; slli a1, a5, 0x20 ; srli a4, a1, 0x20 ; or a5, a3, a4 -; mv t1, a5 ; slli a1, a0, 8 ; srli a3, a0, 8 -; slli a5, a3, 0x38 -; srli a2, a5, 0x38 +; slli a2, a3, 0x38 +; srli a2, a2, 0x38 ; or a3, a1, a2 -; slli a5, a3, 0x10 -; srli a1, a0, 0x10 -; slli a3, a1, 8 -; srli a1, a1, 8 -; slli a1, a1, 0x38 -; srli a4, a1, 0x38 -; or a1, a3, a4 -; slli a1, a1, 0x30 -; srli a3, a1, 0x30 -; or a5, a5, a3 -; slli a1, a5, 0x20 +; slli a1, a3, 0x10 +; srli a2, a0, 0x10 +; slli a3, a2, 8 +; srli a2, a2, 8 +; slli a2, a2, 0x38 +; srli a4, a2, 0x38 +; or a2, a3, a4 +; slli a2, a2, 0x30 +; srli a3, a2, 0x30 +; or a1, a1, a3 +; slli a1, a1, 0x20 ; srli a4, a0, 0x20 -; slli a5, a4, 8 +; slli a0, a4, 8 ; srli a2, a4, 8 ; slli a3, a2, 0x38 -; srli a0, a3, 0x38 -; or a2, a5, a0 +; srli a2, a3, 0x38 +; or a2, a0, a2 ; slli a3, a2, 0x10 -; srli a5, a4, 0x10 -; slli a2, a5, 8 -; srli a4, a5, 8 -; slli a5, a4, 0x38 -; srli a4, a5, 0x38 +; srli a0, a4, 0x10 +; slli a2, a0, 8 +; srli a4, a0, 8 +; slli a0, a4, 0x38 +; srli a4, a0, 0x38 ; or a4, a2, a4 -; slli a5, a4, 0x30 -; srli a2, a5, 0x30 +; slli a0, a4, 0x30 +; srli a2, a0, 0x30 ; or a3, a3, a2 -; slli a5, a3, 0x20 -; srli a2, a5, 0x20 +; slli a0, a3, 0x20 +; srli a2, a0, 0x20 ; or a1, a1, a2 -; mv a0, t1 +; mv a0, a5 ; ret diff --git a/cranelift/filetests/filetests/isa/riscv64/call.clif b/cranelift/filetests/filetests/isa/riscv64/call.clif index 534cc5398132..8fcfe0f709aa 100644 --- a/cranelift/filetests/filetests/isa/riscv64/call.clif +++ b/cranelift/filetests/filetests/isa/riscv64/call.clif @@ -291,7 +291,7 @@ block0: ; addi sp,sp,-32 ; fsd fs0,24(sp) ; fsd fs2,16(sp) -; fsd fs3,8(sp) +; fsd fs4,8(sp) ; block0: ; load_sym a3,%g0+0 ; callind a3 @@ -301,7 +301,7 @@ block0: ; fmv.d fs2,fa0 ; load_sym a3,%g1+0 ; callind a3 -; fmv.d fs3,fa0 +; fmv.d fs4,fa0 ; load_sym a3,%g2+0 ; callind a3 ; load_sym a4,%g3+0 @@ -311,11 +311,11 @@ block0: ; fmv.d fa0,fs2 ; callind a5 ; load_sym a0,%g4+0 -; fmv.d fa0,fs3 +; fmv.d fa0,fs4 ; callind a0 ; fld fs0,24(sp) ; fld fs2,16(sp) -; fld fs3,8(sp) +; fld fs4,8(sp) ; addi sp,sp,32 ; ld ra,8(sp) ; ld fp,0(sp) @@ -331,7 +331,7 @@ block0: ; addi sp, sp, -0x20 ; fsd fs0, 0x18(sp) ; fsd fs2, 0x10(sp) -; fsd fs3, 8(sp) +; fsd fs4, 8(sp) ; block1: ; offset 0x20 ; auipc a3, 0 ; ld a3, 0xc(a3) @@ -353,7 +353,7 @@ block0: ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g1 0 ; .byte 0x00, 0x00, 0x00, 0x00 ; jalr a3 -; fmv.d fs3, fa0 +; fmv.d fs4, fa0 ; auipc a3, 0 ; ld a3, 0xc(a3) ; j 0xc @@ -379,11 +379,11 @@ block0: ; j 0xc ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g4 0 ; .byte 0x00, 0x00, 0x00, 0x00 -; fmv.d fa0, fs3 +; fmv.d fa0, fs4 ; jalr a0 ; fld fs0, 0x18(sp) ; fld fs2, 0x10(sp) -; fld fs3, 8(sp) +; fld fs4, 8(sp) ; addi sp, sp, 0x20 ; ld ra, 8(sp) ; ld s0, 0(sp) @@ -422,9 +422,9 @@ block0(v0: i64): ; sd fp,0(sp) ; mv fp,sp ; block0: -; mv a1,a0 ; li a2,42 ; load_sym a4,%f11+0 +; mv a1,a0 ; mv a0,a2 ; callind a4 ; ld ra,8(sp) @@ -439,13 +439,13 @@ block0(v0: i64): ; sd s0, 0(sp) ; mv s0, sp ; block1: ; offset 0x10 -; mv a1, a0 ; addi a2, zero, 0x2a ; auipc a4, 0 ; ld a4, 0xc(a4) ; j 0xc ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f11 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mv a1, a0 ; mv a0, a2 ; jalr a4 ; ld ra, 8(sp) @@ -485,9 +485,9 @@ block0(v0: i64): ; sd fp,0(sp) ; mv fp,sp ; block0: -; mv a1,a0 ; li a2,42 ; load_sym a4,%f12+0 +; mv a1,a0 ; mv a0,a2 ; callind a4 ; ld ra,8(sp) @@ -502,13 +502,13 @@ block0(v0: i64): ; sd s0, 0(sp) ; mv s0, sp ; block1: ; offset 0x10 -; mv a1, a0 ; addi a2, zero, 0x2a ; auipc a4, 0 ; ld a4, 0xc(a4) ; j 0xc ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f12 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mv a1, a0 ; mv a0, a2 ; jalr a4 ; ld ra, 8(sp) @@ -548,9 +548,9 @@ block0(v0: i64): ; sd fp,0(sp) ; mv fp,sp ; block0: -; mv a1,a0 ; li a2,42 ; load_sym a4,%f13+0 +; mv a1,a0 ; mv a0,a2 ; callind a4 ; ld ra,8(sp) @@ -565,13 +565,13 @@ block0(v0: i64): ; sd s0, 0(sp) ; mv s0, sp ; block1: ; offset 0x10 -; mv a1, a0 ; addi a2, zero, 0x2a ; auipc a4, 0 ; ld a4, 0xc(a4) ; j 0xc ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f13 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mv a1, a0 ; mv a0, a2 ; jalr a4 ; ld ra, 8(sp) @@ -590,8 +590,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128): ; sd fp,0(sp) ; mv fp,sp ; block0: -; mv a0,a7 ; ld a1,-16(incoming_arg) +; mv a0,a7 ; ld ra,8(sp) ; ld fp,0(sp) ; addi sp,sp,16 @@ -604,8 +604,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128): ; sd s0, 0(sp) ; mv s0, sp ; block1: ; offset 0x10 -; mv a0, a7 ; ld a1, 0x10(sp) +; mv a0, a7 ; ld ra, 8(sp) ; ld s0, 0(sp) ; addi sp, sp, 0x10 @@ -627,11 +627,11 @@ block0(v0: i128, v1: i64): ; addi sp,sp,-32 ; sd s1,24(sp) ; block0: -; mv a6,a2 -; mv a7,a0 ; sd a1,0(sp) -; mv a5,a1 ; load_sym s1,%f14+0 +; mv a5,a1 +; mv a6,a2 +; mv a7,a0 ; mv a2,a7 ; mv a3,a5 ; mv a4,a7 @@ -652,15 +652,15 @@ block0(v0: i128, v1: i64): ; addi sp, sp, -0x20 ; sd s1, 0x18(sp) ; block1: ; offset 0x18 -; mv a6, a2 -; mv a7, a0 ; sd a1, 0(sp) -; mv a5, a1 ; auipc s1, 0 ; ld s1, 0xc(s1) ; j 0xc ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f14 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mv a5, a1 +; mv a6, a2 +; mv a7, a0 ; mv a2, a7 ; mv a3, a5 ; mv a4, a7 @@ -683,8 +683,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128): ; sd fp,0(sp) ; mv fp,sp ; block0: -; mv a0,a7 ; ld a1,-16(incoming_arg) +; mv a0,a7 ; ld ra,8(sp) ; ld fp,0(sp) ; addi sp,sp,16 @@ -697,8 +697,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128): ; sd s0, 0(sp) ; mv s0, sp ; block1: ; offset 0x10 -; mv a0, a7 ; ld a1, 0x10(sp) +; mv a0, a7 ; ld ra, 8(sp) ; ld s0, 0(sp) ; addi sp, sp, 0x10 @@ -720,11 +720,11 @@ block0(v0: i128, v1: i64): ; addi sp,sp,-32 ; sd s1,24(sp) ; block0: -; mv a6,a2 -; mv a7,a0 ; sd a1,0(sp) -; mv a5,a1 ; load_sym s1,%f15+0 +; mv a5,a1 +; mv a6,a2 +; mv a7,a0 ; mv a2,a7 ; mv a3,a5 ; mv a4,a7 @@ -745,15 +745,15 @@ block0(v0: i128, v1: i64): ; addi sp, sp, -0x20 ; sd s1, 0x18(sp) ; block1: ; offset 0x18 -; mv a6, a2 -; mv a7, a0 ; sd a1, 0(sp) -; mv a5, a1 ; auipc s1, 0 ; ld s1, 0xc(s1) ; j 0xc ; .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %f15 0 ; .byte 0x00, 0x00, 0x00, 0x00 +; mv a5, a1 +; mv a6, a2 +; mv a7, a0 ; mv a2, a7 ; mv a3, a5 ; mv a4, a7 diff --git a/cranelift/filetests/filetests/isa/riscv64/i128.clif b/cranelift/filetests/filetests/isa/riscv64/i128.clif new file mode 100644 index 000000000000..22b924792869 --- /dev/null +++ b/cranelift/filetests/filetests/isa/riscv64/i128.clif @@ -0,0 +1,126 @@ +test compile precise-output +set opt_level=speed +target riscv64 + +function %mul_uextend_i64(i64, i64) -> i128 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; block0: +; mul a3,a0,a1 +; mulhu a1,a0,a1 +; mv a0,a3 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mul a3, a0, a1 +; mulhu a1, a0, a1 +; mv a0, a3 +; ret + +function %mul_sextend_i64(i64, i64) -> i128 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; block0: +; mul a3,a0,a1 +; mulh a1,a0,a1 +; mv a0,a3 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mul a3, a0, a1 +; mulh a1, a0, a1 +; mv a0, a3 +; ret + +function %smul_high_i64_pattern(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + v5 = sshr_imm v4, 64 + v6 = ireduce.i64 v5 + return v6 +} + +; VCode: +; block0: +; mulh a0,a0,a1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mulh a0, a0, a1 +; ret + +function %smul_high_i64_isplit(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + v5, v6 = isplit v4 + return v6 +} + +; VCode: +; block0: +; mulh a0,a0,a1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mulh a0, a0, a1 +; ret + +function %umul_high_i64_pattern(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + v5 = ushr_imm v4, 64 + v6 = ireduce.i64 v5 + return v6 +} + +; VCode: +; block0: +; mulhu a0,a0,a1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mulhu a0, a0, a1 +; ret + +function %umul_high_i64_isplit(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + v5, v6 = isplit v4 + return v6 +} + +; VCode: +; block0: +; mulhu a0,a0,a1 +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mulhu a0, a0, a1 +; ret + diff --git a/cranelift/filetests/filetests/isa/riscv64/return-call-indirect.clif b/cranelift/filetests/filetests/isa/riscv64/return-call-indirect.clif index ca12180fad52..d5d1d7b5740f 100644 --- a/cranelift/filetests/filetests/isa/riscv64/return-call-indirect.clif +++ b/cranelift/filetests/filetests/isa/riscv64/return-call-indirect.clif @@ -267,12 +267,12 @@ block0: ; sd s10,48(sp) ; sd s11,40(sp) ; block0: -; li a0,10 -; sd a0,16(slot) -; li a1,15 -; sd a1,8(slot) -; li a2,20 -; sd a2,0(slot) +; li a1,10 +; sd a1,16(slot) +; li a2,15 +; sd a2,8(slot) +; li a3,20 +; sd a3,0(slot) ; li a3,25 ; li a4,30 ; li a5,35 @@ -345,12 +345,12 @@ block0: ; sd s10, 0x30(sp) ; sd s11, 0x28(sp) ; block1: ; offset 0x54 -; addi a0, zero, 0xa -; sd a0, 0x10(sp) -; addi a1, zero, 0xf -; sd a1, 8(sp) -; addi a2, zero, 0x14 -; sd a2, 0(sp) +; addi a1, zero, 0xa +; sd a1, 0x10(sp) +; addi a2, zero, 0xf +; sd a2, 8(sp) +; addi a3, zero, 0x14 +; sd a3, 0(sp) ; addi a3, zero, 0x19 ; addi a4, zero, 0x1e ; addi a5, zero, 0x23 diff --git a/cranelift/filetests/filetests/isa/riscv64/return-call.clif b/cranelift/filetests/filetests/isa/riscv64/return-call.clif index e119025b92a4..b472a6c31c3a 100644 --- a/cranelift/filetests/filetests/isa/riscv64/return-call.clif +++ b/cranelift/filetests/filetests/isa/riscv64/return-call.clif @@ -285,10 +285,10 @@ block0: ; sd s10,32(sp) ; sd s11,24(sp) ; block0: -; li a0,10 -; sd a0,8(slot) -; li a1,15 -; sd a1,0(slot) +; li a1,10 +; sd a1,8(slot) +; li a2,15 +; sd a2,0(slot) ; li a2,20 ; li a3,25 ; li a4,30 @@ -360,10 +360,10 @@ block0: ; sd s10, 0x20(sp) ; sd s11, 0x18(sp) ; block1: ; offset 0x54 -; addi a0, zero, 0xa -; sd a0, 8(sp) -; addi a1, zero, 0xf -; sd a1, 0(sp) +; addi a1, zero, 0xa +; sd a1, 8(sp) +; addi a2, zero, 0xf +; sd a2, 0(sp) ; addi a2, zero, 0x14 ; addi a3, zero, 0x19 ; addi a4, zero, 0x1e @@ -561,10 +561,10 @@ block2: ; block0: ; li a1,10 ; sd a1,16(slot) -; li a1,15 -; sd a1,8(slot) -; li a2,20 -; sd a2,0(slot) +; li a2,15 +; sd a2,8(slot) +; li a3,20 +; sd a3,0(slot) ; li a3,25 ; li a4,30 ; li a5,35 @@ -572,11 +572,11 @@ block2: ; li a7,45 ; li a2,50 ; li a1,55 -; li s5,60 -; li s4,65 -; li s3,70 -; li s2,75 -; li s1,80 +; li s1,60 +; li s5,65 +; li s4,70 +; li s3,75 +; li s2,80 ; li t4,85 ; li t3,90 ; li t2,95 @@ -593,11 +593,11 @@ block2: ; li a0,140 ; sd a2,-160(incoming_arg) ; sd a1,-152(incoming_arg) -; sd s5,-144(incoming_arg) -; sd s4,-136(incoming_arg) -; sd s3,-128(incoming_arg) -; sd s2,-120(incoming_arg) -; sd s1,-112(incoming_arg) +; sd s1,-144(incoming_arg) +; sd s5,-136(incoming_arg) +; sd s4,-128(incoming_arg) +; sd s3,-120(incoming_arg) +; sd s2,-112(incoming_arg) ; sd t4,-104(incoming_arg) ; sd t3,-96(incoming_arg) ; sd t2,-88(incoming_arg) @@ -619,11 +619,11 @@ block2: ; ld a0,16(slot) ; sd a2,-144(incoming_arg) ; sd a1,-136(incoming_arg) -; sd s5,-128(incoming_arg) -; sd s4,-120(incoming_arg) -; sd s3,-112(incoming_arg) -; sd s2,-104(incoming_arg) -; sd s1,-96(incoming_arg) +; sd s1,-128(incoming_arg) +; sd s5,-120(incoming_arg) +; sd s4,-112(incoming_arg) +; sd s3,-104(incoming_arg) +; sd s2,-96(incoming_arg) ; sd t4,-88(incoming_arg) ; sd t3,-80(incoming_arg) ; sd t2,-72(incoming_arg) @@ -666,10 +666,10 @@ block2: ; block1: ; offset 0x54 ; addi a1, zero, 0xa ; sd a1, 0x10(sp) -; addi a1, zero, 0xf -; sd a1, 8(sp) -; addi a2, zero, 0x14 -; sd a2, 0(sp) +; addi a2, zero, 0xf +; sd a2, 8(sp) +; addi a3, zero, 0x14 +; sd a3, 0(sp) ; addi a3, zero, 0x19 ; addi a4, zero, 0x1e ; addi a5, zero, 0x23 @@ -677,11 +677,11 @@ block2: ; addi a7, zero, 0x2d ; addi a2, zero, 0x32 ; addi a1, zero, 0x37 -; addi s5, zero, 0x3c -; addi s4, zero, 0x41 -; addi s3, zero, 0x46 -; addi s2, zero, 0x4b -; addi s1, zero, 0x50 +; addi s1, zero, 0x3c +; addi s5, zero, 0x41 +; addi s4, zero, 0x46 +; addi s3, zero, 0x4b +; addi s2, zero, 0x50 ; addi t4, zero, 0x55 ; addi t3, zero, 0x5a ; addi t2, zero, 0x5f @@ -698,11 +698,11 @@ block2: ; addi a0, zero, 0x8c ; sd a2, 0x90(sp) ; sd a1, 0x98(sp) -; sd s5, 0xa0(sp) -; sd s4, 0xa8(sp) -; sd s3, 0xb0(sp) -; sd s2, 0xb8(sp) -; sd s1, 0xc0(sp) +; sd s1, 0xa0(sp) +; sd s5, 0xa8(sp) +; sd s4, 0xb0(sp) +; sd s3, 0xb8(sp) +; sd s2, 0xc0(sp) ; sd t4, 0xc8(sp) ; sd t3, 0xd0(sp) ; sd t2, 0xd8(sp) @@ -742,11 +742,11 @@ block2: ; ld a0, 0x10(sp) ; sd a2, 0xa0(sp) ; sd a1, 0xa8(sp) -; sd s5, 0xb0(sp) -; sd s4, 0xb8(sp) -; sd s3, 0xc0(sp) -; sd s2, 0xc8(sp) -; sd s1, 0xd0(sp) +; sd s1, 0xb0(sp) +; sd s5, 0xb8(sp) +; sd s4, 0xc0(sp) +; sd s3, 0xc8(sp) +; sd s2, 0xd0(sp) ; sd t4, 0xd8(sp) ; sd t3, 0xe0(sp) ; sd t2, 0xe8(sp) diff --git a/cranelift/filetests/filetests/isa/riscv64/stack.clif b/cranelift/filetests/filetests/isa/riscv64/stack.clif index 2d4bd0eb3069..88df5938e976 100644 --- a/cranelift/filetests/filetests/isa/riscv64/stack.clif +++ b/cranelift/filetests/filetests/isa/riscv64/stack.clif @@ -537,47 +537,47 @@ block0(v0: i8): ; addi a0,a0,37 ; ld a1,1256(slot) ; addi a1,a1,39 -; ld a5,1248(slot) -; addi a2,a5,31 +; ld a2,1248(slot) +; addi a2,a2,31 ; ld a3,1240(slot) ; addi a3,a3,33 -; ld a5,1232(slot) -; addi a4,a5,35 +; ld a4,1232(slot) +; addi a4,a4,35 ; ld a5,1224(slot) ; addi a5,a5,37 -; ld s11,1216(slot) -; addi s7,s11,39 -; ld t2,1208(slot) -; addi s8,t2,31 -; ld t3,1200(slot) -; addi s9,t3,33 -; ld s2,1192(slot) -; addi s10,s2,35 -; ld s5,1184(slot) -; addi s11,s5,37 +; ld t0,1216(slot) +; addi s7,t0,39 +; ld a6,1208(slot) +; addi s8,a6,31 +; ld t4,1200(slot) +; addi s9,t4,33 +; ld s3,1192(slot) +; addi s10,s3,35 +; ld s11,1184(slot) +; addi s11,s11,37 ; ld t0,1176(slot) ; addi t0,t0,39 -; ld t1,1160(slot) -; ld t2,1168(slot) -; add t1,t2,t1 -; ld a7,1152(slot) -; ld t4,1144(slot) -; add t2,a7,t4 -; ld s3,1136(slot) -; ld s5,1128(slot) -; add a6,s3,s5 +; ld t1,1168(slot) +; ld t2,1160(slot) +; add t1,t1,t2 +; ld s1,1144(slot) +; ld t3,1152(slot) +; add t2,t3,s1 +; ld a6,1128(slot) +; ld s4,1136(slot) +; add a6,s4,a6 ; ld a7,1112(slot) ; ld t3,1120(slot) ; add a7,t3,a7 ; ld t3,1096(slot) ; ld t4,1104(slot) ; add t3,t4,t3 -; ld s2,1080(slot) -; ld t4,1088(slot) -; add t4,t4,s2 +; ld s1,1088(slot) +; ld s3,1080(slot) +; add t4,s1,s3 ; ld s1,1064(slot) -; ld s5,1072(slot) -; add s1,s5,s1 +; ld s2,1072(slot) +; add s1,s2,s1 ; ld s2,1048(slot) ; ld s3,1056(slot) ; add s2,s3,s2 @@ -743,47 +743,47 @@ block0(v0: i8): ; addi a0, a0, 0x25 ; ld a1, 0x4e8(sp) ; addi a1, a1, 0x27 -; ld a5, 0x4e0(sp) -; addi a2, a5, 0x1f +; ld a2, 0x4e0(sp) +; addi a2, a2, 0x1f ; ld a3, 0x4d8(sp) ; addi a3, a3, 0x21 -; ld a5, 0x4d0(sp) -; addi a4, a5, 0x23 +; ld a4, 0x4d0(sp) +; addi a4, a4, 0x23 ; ld a5, 0x4c8(sp) ; addi a5, a5, 0x25 -; ld s11, 0x4c0(sp) -; addi s7, s11, 0x27 -; ld t2, 0x4b8(sp) -; addi s8, t2, 0x1f -; ld t3, 0x4b0(sp) -; addi s9, t3, 0x21 -; ld s2, 0x4a8(sp) -; addi s10, s2, 0x23 -; ld s5, 0x4a0(sp) -; addi s11, s5, 0x25 +; ld t0, 0x4c0(sp) +; addi s7, t0, 0x27 +; ld a6, 0x4b8(sp) +; addi s8, a6, 0x1f +; ld t4, 0x4b0(sp) +; addi s9, t4, 0x21 +; ld s3, 0x4a8(sp) +; addi s10, s3, 0x23 +; ld s11, 0x4a0(sp) +; addi s11, s11, 0x25 ; ld t0, 0x498(sp) ; addi t0, t0, 0x27 -; ld t1, 0x488(sp) -; ld t2, 0x490(sp) -; add t1, t2, t1 -; ld a7, 0x480(sp) -; ld t4, 0x478(sp) -; add t2, a7, t4 -; ld s3, 0x470(sp) -; ld s5, 0x468(sp) -; add a6, s3, s5 +; ld t1, 0x490(sp) +; ld t2, 0x488(sp) +; add t1, t1, t2 +; ld s1, 0x478(sp) +; ld t3, 0x480(sp) +; add t2, t3, s1 +; ld a6, 0x468(sp) +; ld s4, 0x470(sp) +; add a6, s4, a6 ; ld a7, 0x458(sp) ; ld t3, 0x460(sp) ; add a7, t3, a7 ; ld t3, 0x448(sp) ; ld t4, 0x450(sp) ; add t3, t4, t3 -; ld s2, 0x438(sp) -; ld t4, 0x440(sp) -; add t4, t4, s2 +; ld s1, 0x440(sp) +; ld s3, 0x438(sp) +; add t4, s1, s3 ; ld s1, 0x428(sp) -; ld s5, 0x430(sp) -; add s1, s5, s1 +; ld s2, 0x430(sp) +; add s1, s2, s1 ; ld s2, 0x418(sp) ; ld s3, 0x420(sp) ; add s2, s3, s2 diff --git a/cranelift/filetests/filetests/isa/riscv64/tail-call-conv.clif b/cranelift/filetests/filetests/isa/riscv64/tail-call-conv.clif index b0cada1a7d4d..279f8da1af91 100644 --- a/cranelift/filetests/filetests/isa/riscv64/tail-call-conv.clif +++ b/cranelift/filetests/filetests/isa/riscv64/tail-call-conv.clif @@ -87,10 +87,10 @@ block0: ; sd s10,176(sp) ; sd s11,168(sp) ; block0: -; li a0,10 -; sd a0,8(slot) -; li a1,15 -; sd a1,0(slot) +; li a1,10 +; sd a1,8(slot) +; li a2,15 +; sd a2,0(slot) ; li a2,20 ; li a3,25 ; li a4,30 @@ -173,10 +173,10 @@ block0: ; sd s10, 0xb0(sp) ; sd s11, 0xa8(sp) ; block1: ; offset 0x40 -; addi a0, zero, 0xa -; sd a0, 0x98(sp) -; addi a1, zero, 0xf -; sd a1, 0x90(sp) +; addi a1, zero, 0xa +; sd a1, 0x98(sp) +; addi a2, zero, 0xf +; sd a2, 0x90(sp) ; addi a2, zero, 0x14 ; addi a3, zero, 0x19 ; addi a4, zero, 0x1e @@ -296,64 +296,62 @@ block0: ; sd s10,48(sp) ; sd s11,40(sp) ; block0: -; li a3,10 -; sd a3,24(slot) -; li a1,15 +; li a1,10 ; sd a1,16(slot) +; li a1,15 +; sd a1,8(slot) ; li a4,20 -; sd a4,8(slot) -; li a4,25 -; li a5,30 -; li a2,35 -; li s3,40 -; li s4,45 -; li s5,50 -; li s6,55 -; li s7,60 -; li s8,65 -; li s9,70 -; li s10,75 -; li s11,80 -; li t0,85 -; li t1,90 -; li t2,95 -; li a6,100 -; li a7,105 -; li t3,110 -; li t4,115 -; li s1,120 -; li s2,125 +; li a5,25 +; li a2,30 +; li s3,35 +; li s4,40 +; li s5,45 +; li s6,50 +; li s7,55 +; li s8,60 +; li s9,65 +; li s10,70 +; li s11,75 +; li t0,80 +; li t1,85 +; li t2,90 +; li a6,95 +; li a7,100 +; li t3,105 +; li t4,110 +; li s1,115 +; li s2,120 +; li a3,125 +; sd a3,0(slot) ; li a1,130 ; li a3,135 -; sd a3,0(slot) -; ld a3,8(slot) -; sd a3,0(a0) -; sd a4,8(a0) -; sd a5,16(a0) -; sd a2,24(a0) -; sd s3,32(a0) -; sd s4,40(a0) -; sd s5,48(a0) -; sd s6,56(a0) -; sd s7,64(a0) -; sd s8,72(a0) -; sd s9,80(a0) -; sd s10,88(a0) -; sd s11,96(a0) -; sd t0,104(a0) -; sd t1,112(a0) -; sd t2,120(a0) -; sd a6,128(a0) -; sd a7,136(a0) -; sd t3,144(a0) -; sd t4,152(a0) -; sd s1,160(a0) -; sd s2,168(a0) +; sd a4,0(a0) +; sd a5,8(a0) +; sd a2,16(a0) +; sd s3,24(a0) +; sd s4,32(a0) +; sd s5,40(a0) +; sd s6,48(a0) +; sd s7,56(a0) +; sd s8,64(a0) +; sd s9,72(a0) +; sd s10,80(a0) +; sd s11,88(a0) +; sd t0,96(a0) +; sd t1,104(a0) +; sd t2,112(a0) +; sd a6,120(a0) +; sd a7,128(a0) +; sd t3,136(a0) +; sd t4,144(a0) +; sd s1,152(a0) +; sd s2,160(a0) +; ld a4,0(slot) +; sd a4,168(a0) ; sd a1,176(a0) -; ld a3,0(slot) ; sd a3,184(a0) -; ld a0,24(slot) -; ld a1,16(slot) +; ld a0,16(slot) +; ld a1,8(slot) ; ld s1,120(sp) ; ld s2,112(sp) ; ld s3,104(sp) @@ -390,64 +388,62 @@ block0: ; sd s10, 0x30(sp) ; sd s11, 0x28(sp) ; block1: ; offset 0x40 -; addi a3, zero, 0xa -; sd a3, 0x18(sp) -; addi a1, zero, 0xf +; addi a1, zero, 0xa ; sd a1, 0x10(sp) +; addi a1, zero, 0xf +; sd a1, 8(sp) ; addi a4, zero, 0x14 -; sd a4, 8(sp) -; addi a4, zero, 0x19 -; addi a5, zero, 0x1e -; addi a2, zero, 0x23 -; addi s3, zero, 0x28 -; addi s4, zero, 0x2d -; addi s5, zero, 0x32 -; addi s6, zero, 0x37 -; addi s7, zero, 0x3c -; addi s8, zero, 0x41 -; addi s9, zero, 0x46 -; addi s10, zero, 0x4b -; addi s11, zero, 0x50 -; addi t0, zero, 0x55 -; addi t1, zero, 0x5a -; addi t2, zero, 0x5f -; addi a6, zero, 0x64 -; addi a7, zero, 0x69 -; addi t3, zero, 0x6e -; addi t4, zero, 0x73 -; addi s1, zero, 0x78 -; addi s2, zero, 0x7d +; addi a5, zero, 0x19 +; addi a2, zero, 0x1e +; addi s3, zero, 0x23 +; addi s4, zero, 0x28 +; addi s5, zero, 0x2d +; addi s6, zero, 0x32 +; addi s7, zero, 0x37 +; addi s8, zero, 0x3c +; addi s9, zero, 0x41 +; addi s10, zero, 0x46 +; addi s11, zero, 0x4b +; addi t0, zero, 0x50 +; addi t1, zero, 0x55 +; addi t2, zero, 0x5a +; addi a6, zero, 0x5f +; addi a7, zero, 0x64 +; addi t3, zero, 0x69 +; addi t4, zero, 0x6e +; addi s1, zero, 0x73 +; addi s2, zero, 0x78 +; addi a3, zero, 0x7d +; sd a3, 0(sp) ; addi a1, zero, 0x82 ; addi a3, zero, 0x87 -; sd a3, 0(sp) -; ld a3, 8(sp) -; sd a3, 0(a0) -; sd a4, 8(a0) -; sd a5, 0x10(a0) -; sd a2, 0x18(a0) -; sd s3, 0x20(a0) -; sd s4, 0x28(a0) -; sd s5, 0x30(a0) -; sd s6, 0x38(a0) -; sd s7, 0x40(a0) -; sd s8, 0x48(a0) -; sd s9, 0x50(a0) -; sd s10, 0x58(a0) -; sd s11, 0x60(a0) -; sd t0, 0x68(a0) -; sd t1, 0x70(a0) -; sd t2, 0x78(a0) -; sd a6, 0x80(a0) -; sd a7, 0x88(a0) -; sd t3, 0x90(a0) -; sd t4, 0x98(a0) -; sd s1, 0xa0(a0) -; sd s2, 0xa8(a0) +; sd a4, 0(a0) +; sd a5, 8(a0) +; sd a2, 0x10(a0) +; sd s3, 0x18(a0) +; sd s4, 0x20(a0) +; sd s5, 0x28(a0) +; sd s6, 0x30(a0) +; sd s7, 0x38(a0) +; sd s8, 0x40(a0) +; sd s9, 0x48(a0) +; sd s10, 0x50(a0) +; sd s11, 0x58(a0) +; sd t0, 0x60(a0) +; sd t1, 0x68(a0) +; sd t2, 0x70(a0) +; sd a6, 0x78(a0) +; sd a7, 0x80(a0) +; sd t3, 0x88(a0) +; sd t4, 0x90(a0) +; sd s1, 0x98(a0) +; sd s2, 0xa0(a0) +; ld a4, 0(sp) +; sd a4, 0xa8(a0) ; sd a1, 0xb0(a0) -; ld a3, 0(sp) ; sd a3, 0xb8(a0) -; ld a0, 0x18(sp) -; ld a1, 0x10(sp) +; ld a0, 0x10(sp) +; ld a1, 8(sp) ; ld s1, 0x78(sp) ; ld s2, 0x70(sp) ; ld s3, 0x68(sp) @@ -789,10 +785,10 @@ block0: ; sd s10,384(sp) ; sd s11,376(sp) ; block0: -; li a0,10 -; sd a0,8(slot) -; li a1,15 -; sd a1,0(slot) +; li a1,10 +; sd a1,8(slot) +; li a2,15 +; sd a2,0(slot) ; li a2,20 ; li a3,25 ; li a4,30 @@ -901,10 +897,10 @@ block0: ; sd s10, 0x180(sp) ; sd s11, 0x178(sp) ; block1: ; offset 0x40 -; addi a0, zero, 0xa -; sd a0, 0x168(sp) -; addi a1, zero, 0xf -; sd a1, 0x160(sp) +; addi a1, zero, 0xa +; sd a1, 0x168(sp) +; addi a2, zero, 0xf +; sd a2, 0x160(sp) ; addi a2, zero, 0x14 ; addi a3, zero, 0x19 ; addi a4, zero, 0x1e diff --git a/cranelift/filetests/filetests/isa/riscv64/user_stack_maps.clif b/cranelift/filetests/filetests/isa/riscv64/user_stack_maps.clif index 341f7bd4fe0f..4b18ae8abd3e 100644 --- a/cranelift/filetests/filetests/isa/riscv64/user_stack_maps.clif +++ b/cranelift/filetests/filetests/isa/riscv64/user_stack_maps.clif @@ -41,27 +41,21 @@ block0: ; sd s2,32(sp) ; sd s3,24(sp) ; block0: -; li a0,0 -; mv s3,a0 -; li a0,1 -; li a2,2 +; li s3,0 +; li s1,1 +; li s2,2 ; sw zero,0(slot) -; sw a0,4(slot) -; mv s1,a0 -; sw a2,8(slot) -; mv s2,a2 +; sw s1,4(slot) +; sw s2,8(slot) ; mv a0,s3 ; call userextname0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4, 8})], sp_to_sized_stack_slots: None } -; mv a0,s1 -; sw a0,0(slot) -; mv a0,s2 -; sw a0,4(slot) +; sw s1,0(slot) +; sw s2,4(slot) ; mv a0,s3 ; call userextname0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4})], sp_to_sized_stack_slots: None } -; mv a0,s2 -; sw a0,0(slot) +; sw s2,0(slot) ; mv a0,s1 ; call userextname0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0})], sp_to_sized_stack_slots: None } @@ -87,27 +81,21 @@ block0: ; sd s2, 0x20(sp) ; sd s3, 0x18(sp) ; block1: ; offset 0x20 -; mv a0, zero -; mv s3, a0 -; addi a0, zero, 1 -; addi a2, zero, 2 +; mv s3, zero +; addi s1, zero, 1 +; addi s2, zero, 2 ; sw zero, 0(sp) -; sw a0, 4(sp) -; mv s1, a0 -; sw a2, 8(sp) -; mv s2, a2 +; sw s1, 4(sp) +; sw s2, 8(sp) ; mv a0, s3 ; auipc ra, 0 ; reloc_external RiscvCallPlt u0:0 0 ; jalr ra -; mv a0, s1 -; sw a0, 0(sp) -; mv a0, s2 -; sw a0, 4(sp) +; sw s1, 0(sp) +; sw s2, 4(sp) ; mv a0, s3 ; auipc ra, 0 ; reloc_external RiscvCallPlt u0:0 0 ; jalr ra -; mv a0, s2 -; sw a0, 0(sp) +; sw s2, 0(sp) ; mv a0, s1 ; auipc ra, 0 ; reloc_external RiscvCallPlt u0:0 0 ; jalr ra @@ -151,41 +139,41 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; addi sp,sp,-160 ; sd s1,152(sp) ; sd s2,144(sp) -; sd s6,136(sp) -; sd s8,128(sp) -; sd s10,120(sp) +; sd s3,136(sp) +; sd s4,128(sp) +; sd s9,120(sp) ; fsd fs0,112(sp) ; fsd fs2,104(sp) ; block0: -; mv s10,a4 +; mv s2,a4 ; sb a0,0(slot) -; mv s8,a0 +; mv s1,a0 ; sh a1,8(slot) -; mv s6,a1 +; mv s9,a1 ; sw a2,16(slot) -; mv s2,a2 +; mv s4,a2 ; fsw fa0,20(slot) ; fmv.d fs2,fa0 ; sd a3,24(slot) -; mv s1,a3 +; mv s3,a3 ; fsd fa1,32(slot) ; fmv.d fs0,fa1 ; call userextname0 ; ; UserStackMap { by_type: [(types::I8, CompoundBitSet {0}), (types::I16, CompoundBitSet {8}), (types::I32, CompoundBitSet {16}), (types::F32, CompoundBitSet {20}), (types::I64, CompoundBitSet {24}), (types::F64, CompoundBitSet {32})], sp_to_sized_stack_slots: None } -; mv a2,s2 -; mv a4,s10 +; mv a2,s4 +; mv a4,s2 ; sw a2,0(a4) -; mv a3,s1 +; mv a3,s3 ; sd a3,8(a4) -; mv a0,s8 -; mv a1,s6 +; mv a0,s1 +; mv a1,s9 ; fmv.d fa0,fs2 ; fmv.d fa1,fs0 ; ld s1,152(sp) ; ld s2,144(sp) -; ld s6,136(sp) -; ld s8,128(sp) -; ld s10,120(sp) +; ld s3,136(sp) +; ld s4,128(sp) +; ld s9,120(sp) ; fld fs0,112(sp) ; fld fs2,104(sp) ; addi sp,sp,160 @@ -203,41 +191,41 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; addi sp, sp, -0xa0 ; sd s1, 0x98(sp) ; sd s2, 0x90(sp) -; sd s6, 0x88(sp) -; sd s8, 0x80(sp) -; sd s10, 0x78(sp) +; sd s3, 0x88(sp) +; sd s4, 0x80(sp) +; sd s9, 0x78(sp) ; fsd fs0, 0x70(sp) ; fsd fs2, 0x68(sp) ; block1: ; offset 0x30 -; mv s10, a4 +; mv s2, a4 ; sb a0, 0(sp) -; mv s8, a0 +; mv s1, a0 ; sh a1, 8(sp) -; mv s6, a1 +; mv s9, a1 ; sw a2, 0x10(sp) -; mv s2, a2 +; mv s4, a2 ; fsw fa0, 0x14(sp) ; fmv.d fs2, fa0 ; sd a3, 0x18(sp) -; mv s1, a3 +; mv s3, a3 ; fsd fa1, 0x20(sp) ; fmv.d fs0, fa1 ; auipc ra, 0 ; reloc_external RiscvCallPlt u0:0 0 ; jalr ra -; mv a2, s2 -; mv a4, s10 +; mv a2, s4 +; mv a4, s2 ; sw a2, 0(a4) -; mv a3, s1 +; mv a3, s3 ; sd a3, 8(a4) -; mv a0, s8 -; mv a1, s6 +; mv a0, s1 +; mv a1, s9 ; fmv.d fa0, fs2 ; fmv.d fa1, fs0 ; ld s1, 0x98(sp) ; ld s2, 0x90(sp) -; ld s6, 0x88(sp) -; ld s8, 0x80(sp) -; ld s10, 0x78(sp) +; ld s3, 0x88(sp) +; ld s4, 0x80(sp) +; ld s9, 0x78(sp) ; fld fs0, 0x70(sp) ; fld fs2, 0x68(sp) ; addi sp, sp, 0xa0 diff --git a/cranelift/filetests/filetests/isa/riscv64/zca.clif b/cranelift/filetests/filetests/isa/riscv64/zca.clif index 4086bb6353cb..69b31eb2f9d7 100644 --- a/cranelift/filetests/filetests/isa/riscv64/zca.clif +++ b/cranelift/filetests/filetests/isa/riscv64/zca.clif @@ -449,16 +449,15 @@ block0: ; mv fp,sp ; addi sp,sp,-2048 ; block0: -; load_addr a1,1020(slot) -; mv a5,a1 +; load_addr a2,1020(slot) ; load_addr a1,4(slot) -; load_addr a2,512(slot) -; load_addr a3,256(slot) -; load_addr a4,64(slot) -; sd a2,0(a0) -; sd a3,8(a0) -; sd a4,16(a0) -; mv a0,a5 +; load_addr a3,512(slot) +; load_addr a4,256(slot) +; load_addr a5,64(slot) +; sd a3,0(a0) +; sd a4,8(a0) +; sd a5,16(a0) +; mv a0,a2 ; lui t6,1 ; addi t6,t6,-2048 ; add sp,sp,t6 @@ -475,16 +474,15 @@ block0: ; c.mv s0, sp ; addi sp, sp, -0x800 ; block1: ; offset 0xc -; c.addi4spn a1, sp, 0x3fc -; c.mv a5, a1 +; c.addi4spn a2, sp, 0x3fc ; c.addi4spn a1, sp, 4 -; c.addi4spn a2, sp, 0x200 -; c.addi4spn a3, sp, 0x100 -; c.addi4spn a4, sp, 0x40 -; c.sd a2, 0(a0) -; c.sd a3, 8(a0) -; c.sd a4, 0x10(a0) -; c.mv a0, a5 +; c.addi4spn a3, sp, 0x200 +; c.addi4spn a4, sp, 0x100 +; c.addi4spn a5, sp, 0x40 +; c.sd a3, 0(a0) +; c.sd a4, 8(a0) +; c.sd a5, 0x10(a0) +; c.mv a0, a2 ; c.lui t6, 1 ; addi t6, t6, -0x800 ; c.add sp, t6 @@ -586,30 +584,28 @@ block0: ; VCode: ; block0: -; li a1,0 -; mv a5,a1 +; li a2,0 ; li a1,1 -; li a2,-1 -; li a3,-32 -; li a4,31 -; sd a2,0(a0) -; sd a3,8(a0) -; sd a4,16(a0) -; mv a0,a5 +; li a3,-1 +; li a4,-32 +; li a5,31 +; sd a3,0(a0) +; sd a4,8(a0) +; sd a5,16(a0) +; mv a0,a2 ; ret ; ; Disassembled: ; block0: ; offset 0x0 -; c.li a1, 0 -; c.mv a5, a1 +; c.li a2, 0 ; c.li a1, 1 -; c.li a2, -1 -; c.li a3, -0x20 -; c.li a4, 0x1f -; c.sd a2, 0(a0) -; c.sd a3, 8(a0) -; c.sd a4, 0x10(a0) -; c.mv a0, a5 +; c.li a3, -1 +; c.li a4, -0x20 +; c.li a5, 0x1f +; c.sd a3, 0(a0) +; c.sd a4, 8(a0) +; c.sd a5, 0x10(a0) +; c.mv a0, a2 ; c.jr ra function %c_lui() -> i64, i64, i64 { diff --git a/cranelift/filetests/filetests/isa/riscv64/zcb.clif b/cranelift/filetests/filetests/isa/riscv64/zcb.clif index 19bedd07fa24..c5f73c1f725a 100644 --- a/cranelift/filetests/filetests/isa/riscv64/zcb.clif +++ b/cranelift/filetests/filetests/isa/riscv64/zcb.clif @@ -127,17 +127,15 @@ block0(v0: i64): ; VCode: ; block0: ; lbu a3,0(a0) -; mv a4,a3 ; lbu a1,3(a0) -; mv a0,a4 +; mv a0,a3 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; .byte 0x14, 0x81 ; trap: heap_oob -; c.mv a4, a3 ; .byte 0x6c, 0x81 ; trap: heap_oob -; c.mv a0, a4 +; c.mv a0, a3 ; c.jr ra function %c_lhu(i64) -> i32, i64 { @@ -150,17 +148,15 @@ block0(v0: i64): ; VCode: ; block0: ; lhu a3,0(a0) -; mv a4,a3 ; lhu a1,2(a0) -; mv a0,a4 +; mv a0,a3 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; .byte 0x14, 0x85 ; trap: heap_oob -; c.mv a4, a3 ; .byte 0x2c, 0x85 ; trap: heap_oob -; c.mv a0, a4 +; c.mv a0, a3 ; c.jr ra function %c_lh(i64) -> i16, i16 { @@ -173,17 +169,15 @@ block0(v0: i64): ; VCode: ; block0: ; lh a3,0(a0) -; mv a4,a3 ; lh a1,2(a0) -; mv a0,a4 +; mv a0,a3 ; ret ; ; Disassembled: ; block0: ; offset 0x0 ; .byte 0x54, 0x85 ; trap: heap_oob -; c.mv a4, a3 ; .byte 0x6c, 0x85 ; trap: heap_oob -; c.mv a0, a4 +; c.mv a0, a3 ; c.jr ra function %c_sb(i64, i8) { diff --git a/cranelift/filetests/filetests/isa/s390x/arithmetic.clif b/cranelift/filetests/filetests/isa/s390x/arithmetic.clif index 402408137412..a72ea47288ed 100644 --- a/cranelift/filetests/filetests/isa/s390x/arithmetic.clif +++ b/cranelift/filetests/filetests/isa/s390x/arithmetic.clif @@ -1489,10 +1489,11 @@ block0(v0: i64, v1: i64): ; iilf %r4, 4294967295 ; xgrk %r5, %r4, %r2 ; ngrk %r4, %r5, %r3 +; lgr %r5, %r3 ; cgite %r4, -1 -; lgr %r4, %r3 ; lgr %r3, %r2 -; dsgr %r2, %r4 +; lgr %r2, %r5 +; dsgr %r2, %r2 ; lgr %r2, %r3 ; br %r14 ; @@ -1502,10 +1503,11 @@ block0(v0: i64, v1: i64): ; iilf %r4, 0xffffffff ; xgrk %r5, %r4, %r2 ; ngrk %r4, %r5, %r3 +; lgr %r5, %r3 ; cgite %r4, -1 ; trap: int_ovf -; lgr %r4, %r3 ; lgr %r3, %r2 -; dsgr %r2, %r4 ; trap: int_divz +; lgr %r2, %r5 +; dsgr %r2, %r2 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -1518,16 +1520,16 @@ block0(v0: i64): ; VCode: ; block0: -; lgr %r3, %r2 ; lghi %r4, 2 +; lgr %r3, %r2 ; dsgr %r2, %r4 ; lgr %r2, %r3 ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; lgr %r3, %r2 ; lghi %r4, 2 +; lgr %r3, %r2 ; dsgr %r2, %r4 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -1601,13 +1603,12 @@ block0(v0: i16, v1: i16): ; VCode: ; block0: ; lghr %r5, %r2 -; lgr %r2, %r5 ; lhr %r4, %r3 -; lhi %r5, 32767 -; lgr %r3, %r2 -; xr %r5, %r3 -; nr %r5, %r4 -; cite %r5, -1 +; lhi %r2, 32767 +; xrk %r3, %r2, %r5 +; nrk %r2, %r3, %r4 +; cite %r2, -1 +; lgr %r3, %r5 ; dsgfr %r2, %r4 ; lgr %r2, %r3 ; br %r14 @@ -1615,13 +1616,12 @@ block0(v0: i16, v1: i16): ; Disassembled: ; block0: ; offset 0x0 ; lghr %r5, %r2 -; lgr %r2, %r5 ; lhr %r4, %r3 -; lhi %r5, 0x7fff -; lgr %r3, %r2 -; xr %r5, %r3 -; nr %r5, %r4 -; cite %r5, -1 ; trap: int_ovf +; lhi %r2, 0x7fff +; xrk %r3, %r2, %r5 +; nrk %r2, %r3, %r4 +; cite %r2, -1 ; trap: int_ovf +; lgr %r3, %r5 ; dsgfr %r2, %r4 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -1658,13 +1658,12 @@ block0(v0: i8, v1: i8): ; VCode: ; block0: ; lgbr %r5, %r2 -; lgr %r2, %r5 ; lbr %r4, %r3 -; lhi %r5, 127 -; lgr %r3, %r2 -; xr %r5, %r3 -; nr %r5, %r4 -; cite %r5, -1 +; lhi %r2, 127 +; xrk %r3, %r2, %r5 +; nrk %r2, %r3, %r4 +; cite %r2, -1 +; lgr %r3, %r5 ; dsgfr %r2, %r4 ; lgr %r2, %r3 ; br %r14 @@ -1672,13 +1671,12 @@ block0(v0: i8, v1: i8): ; Disassembled: ; block0: ; offset 0x0 ; lgbr %r5, %r2 -; lgr %r2, %r5 ; lbr %r4, %r3 -; lhi %r5, 0x7f -; lgr %r3, %r2 -; xr %r5, %r3 -; nr %r5, %r4 -; cite %r5, -1 ; trap: int_ovf +; lhi %r2, 0x7f +; xrk %r3, %r2, %r5 +; nrk %r2, %r3, %r4 +; cite %r2, -1 ; trap: int_ovf +; lgr %r3, %r5 ; dsgfr %r2, %r4 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -1714,19 +1712,19 @@ block0(v0: i64, v1: i64): ; VCode: ; block0: -; lgr %r4, %r3 +; lgr %r5, %r3 ; lgr %r3, %r2 ; lghi %r2, 0 -; dlgr %r2, %r4 +; dlgr %r2, %r5 ; lgr %r2, %r3 ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; lgr %r4, %r3 +; lgr %r5, %r3 ; lgr %r3, %r2 ; lghi %r2, 0 -; dlgr %r2, %r4 ; trap: int_divz +; dlgr %r2, %r5 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -1763,19 +1761,19 @@ block0(v0: i32, v1: i32): ; VCode: ; block0: -; lgr %r4, %r3 +; lgr %r5, %r3 ; lgr %r3, %r2 ; lhi %r2, 0 -; dlr %r2, %r4 +; dlr %r2, %r5 ; lgr %r2, %r3 ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; lgr %r4, %r3 +; lgr %r5, %r3 ; lgr %r3, %r2 ; lhi %r2, 0 -; dlr %r2, %r4 ; trap: int_divz +; dlr %r2, %r5 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -1811,32 +1809,25 @@ block0(v0: i16, v1: i16): } ; VCode: -; stmg %r7, %r15, 56(%r15) ; block0: ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llhr %r3, %r2 -; llhr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 +; llhr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; lgr %r2, %r3 -; lmg %r7, %r15, 56(%r15) ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r7, %r15, 0x38(%r15) -; block1: ; offset 0x6 ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llhr %r3, %r2 -; llhr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 ; trap: int_divz +; llhr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; trap: int_divz ; lgr %r2, %r3 -; lmg %r7, %r15, 0x38(%r15) ; br %r14 function %udiv_i16_imm(i16) -> i16 { @@ -1849,22 +1840,20 @@ block0(v0: i16): ; VCode: ; block0: ; lhi %r4, 0 -; lgr %r5, %r4 ; llhr %r3, %r2 -; lhi %r4, 2 -; lgr %r2, %r5 -; dlr %r2, %r4 +; lhi %r5, 2 +; lgr %r2, %r4 +; dlr %r2, %r5 ; lgr %r2, %r3 ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 ; lhi %r4, 0 -; lgr %r5, %r4 ; llhr %r3, %r2 -; lhi %r4, 2 -; lgr %r2, %r5 -; dlr %r2, %r4 ; trap: int_divz +; lhi %r5, 2 +; lgr %r2, %r4 +; dlr %r2, %r5 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -1875,32 +1864,25 @@ block0(v0: i8, v1: i8): } ; VCode: -; stmg %r7, %r15, 56(%r15) ; block0: ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llcr %r3, %r2 -; llcr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 +; llcr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; lgr %r2, %r3 -; lmg %r7, %r15, 56(%r15) ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r7, %r15, 0x38(%r15) -; block1: ; offset 0x6 ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llcr %r3, %r2 -; llcr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 ; trap: int_divz +; llcr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; trap: int_divz ; lgr %r2, %r3 -; lmg %r7, %r15, 0x38(%r15) ; br %r14 function %udiv_i8_imm(i8) -> i8 { @@ -1913,22 +1895,20 @@ block0(v0: i8): ; VCode: ; block0: ; lhi %r4, 0 -; lgr %r5, %r4 ; llcr %r3, %r2 -; lhi %r4, 2 -; lgr %r2, %r5 -; dlr %r2, %r4 +; lhi %r5, 2 +; lgr %r2, %r4 +; dlr %r2, %r5 ; lgr %r2, %r3 ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 ; lhi %r4, 0 -; lgr %r5, %r4 ; llcr %r3, %r2 -; lhi %r4, 2 -; lgr %r2, %r5 -; dlr %r2, %r4 ; trap: int_divz +; lhi %r5, 2 +; lgr %r2, %r4 +; dlr %r2, %r5 ; trap: int_divz ; lgr %r2, %r3 ; br %r14 @@ -2077,30 +2057,23 @@ block0(v0: i16, v1: i16): } ; VCode: -; stmg %r7, %r15, 56(%r15) ; block0: ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llhr %r3, %r2 -; llhr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 -; lmg %r7, %r15, 56(%r15) +; llhr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r7, %r15, 0x38(%r15) -; block1: ; offset 0x6 ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llhr %r3, %r2 -; llhr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 ; trap: int_divz -; lmg %r7, %r15, 0x38(%r15) +; llhr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; trap: int_divz ; br %r14 function %urem_i8(i8, i8) -> i8 { @@ -2110,29 +2083,22 @@ block0(v0: i8, v1: i8): } ; VCode: -; stmg %r7, %r15, 56(%r15) ; block0: ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llcr %r3, %r2 -; llcr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 -; lmg %r7, %r15, 56(%r15) +; llcr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r7, %r15, 0x38(%r15) -; block1: ; offset 0x6 ; lgr %r4, %r3 ; lhi %r5, 0 -; lgr %r7, %r5 ; llcr %r3, %r2 -; llcr %r5, %r4 -; lgr %r2, %r7 -; dlr %r2, %r5 ; trap: int_divz -; lmg %r7, %r15, 0x38(%r15) +; llcr %r4, %r4 +; lgr %r2, %r5 +; dlr %r2, %r4 ; trap: int_divz ; br %r14 diff --git a/cranelift/filetests/filetests/isa/s390x/call-tail.clif b/cranelift/filetests/filetests/isa/s390x/call-tail.clif index e2e93038219b..1ce224b65ce8 100644 --- a/cranelift/filetests/filetests/isa/s390x/call-tail.clif +++ b/cranelift/filetests/filetests/isa/s390x/call-tail.clif @@ -245,16 +245,16 @@ block0(v0: i64): ; block0: ; lgr %r10, %r2 ; brasl %r14, %f +; lgr %r13, %r2 +; brasl %r14, %f +; lgr %r9, %r2 +; brasl %r14, %f ; lgr %r12, %r2 ; brasl %r14, %f ; lgr %r8, %r2 ; brasl %r14, %f -; lgr %r9, %r2 -; brasl %r14, %f ; lgr %r11, %r2 ; brasl %r14, %f -; lgr %r13, %r2 -; brasl %r14, %f ; stg %r2, 184(%r15) ; brasl %r14, %f ; stg %r2, 176(%r15) @@ -266,11 +266,11 @@ block0(v0: i64): ; lg %r2, 352(%r15) ; stg %r2, 168(%r15) ; lgr %r2, %r10 -; lgr %r3, %r12 -; lgr %r4, %r8 -; lgr %r5, %r9 -; lgr %r6, %r11 -; lgr %r7, %r13 +; lgr %r3, %r13 +; lgr %r4, %r9 +; lgr %r5, %r12 +; lgr %r6, %r8 +; lgr %r7, %r11 ; brasl %r14, %g ; callee_pop_size 176 ; lg %r2, 168(%r15) ; lmg %r8, %r15, 256(%r15) @@ -283,15 +283,15 @@ block0(v0: i64): ; block1: ; offset 0xa ; lgr %r10, %r2 ; brasl %r14, 0xe ; reloc_external PLTRel32Dbl %f 2 -; lgr %r12, %r2 +; lgr %r13, %r2 ; brasl %r14, 0x18 ; reloc_external PLTRel32Dbl %f 2 -; lgr %r8, %r2 -; brasl %r14, 0x22 ; reloc_external PLTRel32Dbl %f 2 ; lgr %r9, %r2 +; brasl %r14, 0x22 ; reloc_external PLTRel32Dbl %f 2 +; lgr %r12, %r2 ; brasl %r14, 0x2c ; reloc_external PLTRel32Dbl %f 2 -; lgr %r11, %r2 +; lgr %r8, %r2 ; brasl %r14, 0x36 ; reloc_external PLTRel32Dbl %f 2 -; lgr %r13, %r2 +; lgr %r11, %r2 ; brasl %r14, 0x40 ; reloc_external PLTRel32Dbl %f 2 ; stg %r2, 0xb8(%r15) ; brasl %r14, 0x4c ; reloc_external PLTRel32Dbl %f 2 @@ -304,11 +304,11 @@ block0(v0: i64): ; lg %r2, 0x160(%r15) ; stg %r2, 0xa8(%r15) ; lgr %r2, %r10 -; lgr %r3, %r12 -; lgr %r4, %r8 -; lgr %r5, %r9 -; lgr %r6, %r11 -; lgr %r7, %r13 +; lgr %r3, %r13 +; lgr %r4, %r9 +; lgr %r5, %r12 +; lgr %r6, %r8 +; lgr %r7, %r11 ; brasl %r14, 0x98 ; reloc_external PLTRel32Dbl %g 2 ; lg %r2, 0xa8(%r15) ; lmg %r8, %r15, 0x100(%r15) diff --git a/cranelift/filetests/filetests/isa/s390x/i128.clif b/cranelift/filetests/filetests/isa/s390x/i128.clif new file mode 100644 index 000000000000..03d34a0efbe1 --- /dev/null +++ b/cranelift/filetests/filetests/isa/s390x/i128.clif @@ -0,0 +1,154 @@ +test compile precise-output +set opt_level=speed +target s390x + +function %mul_uextend_i64(i64, i64) -> i128 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; block0: +; lgr %r5, %r2 +; mlgr %r2, %r4 +; vlvgp %v7, %r2, %r3 +; lgr %r2, %r5 +; vst %v7, 0(%r2) +; br %r14 +; +; Disassembled: +; block0: ; offset 0x0 +; lgr %r5, %r2 +; mlgr %r2, %r4 +; vlvgp %v7, %r2, %r3 +; lgr %r2, %r5 +; vst %v7, 0(%r2) +; br %r14 + +function %mul_sextend_i64(i64, i64) -> i128 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; block0: +; lgr %r5, %r2 +; mgrk %r2, %r3, %r4 +; vlvgp %v7, %r2, %r3 +; lgr %r2, %r5 +; vst %v7, 0(%r2) +; br %r14 +; +; Disassembled: +; block0: ; offset 0x0 +; lgr %r5, %r2 +; mgrk %r2, %r3, %r4 +; vlvgp %v7, %r2, %r3 +; lgr %r2, %r5 +; vst %v7, 0(%r2) +; br %r14 + +function %smul_high_i64_pattern(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + v5 = sshr_imm v4, 64 + v6 = ireduce.i64 v5 + return v6 +} + +; VCode: +; block0: +; mgrk %r2, %r2, %r3 +; br %r14 +; +; Disassembled: +; block0: ; offset 0x0 +; mgrk %r2, %r2, %r3 +; br %r14 + +function %smul_high_i64_isplit(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = sextend.i128 v0 + v3 = sextend.i128 v1 + v4 = imul v2, v3 + v5, v6 = isplit v4 + return v6 +} + +; VCode: +; block0: +; mgrk %r2, %r2, %r3 +; vlvgp %v16, %r2, %r3 +; vlgvg %r2, %v16, 0 +; vlgvg %r5, %v16, 1 +; br %r14 +; +; Disassembled: +; block0: ; offset 0x0 +; mgrk %r2, %r2, %r3 +; vlvgp %v16, %r2, %r3 +; vlgvg %r2, %v16, 0 +; vlgvg %r5, %v16, 1 +; br %r14 + +function %umul_high_i64_pattern(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + v5 = ushr_imm v4, 64 + v6 = ireduce.i64 v5 + return v6 +} + +; VCode: +; block0: +; lgr %r4, %r3 +; lgr %r3, %r2 +; mlgr %r2, %r4 +; br %r14 +; +; Disassembled: +; block0: ; offset 0x0 +; lgr %r4, %r3 +; lgr %r3, %r2 +; mlgr %r2, %r4 +; br %r14 + +function %umul_high_i64_isplit(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + v5, v6 = isplit v4 + return v6 +} + +; VCode: +; block0: +; lgr %r4, %r3 +; lgr %r3, %r2 +; mlgr %r2, %r4 +; vlvgp %v16, %r2, %r3 +; vlgvg %r2, %v16, 0 +; vlgvg %r5, %v16, 1 +; br %r14 +; +; Disassembled: +; block0: ; offset 0x0 +; lgr %r4, %r3 +; lgr %r3, %r2 +; mlgr %r2, %r4 +; vlvgp %v16, %r2, %r3 +; vlgvg %r2, %v16, 0 +; vlgvg %r5, %v16, 1 +; br %r14 + diff --git a/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif b/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif index 75937accc011..b80531782d16 100644 --- a/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif +++ b/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif @@ -40,16 +40,15 @@ block1: ; VCode: ; stmg %r6, %r15, 48(%r15) ; block0: -; lghi %r5, 1 -; lgr %r6, %r5 +; lghi %r13, 1 ; lghi %r3, 2 ; lghi %r4, 3 ; lghi %r5, 4 -; lghi %r13, 5 -; lghi %r14, 6 -; stg %r13, 0(%r2) -; stg %r14, 8(%r2) -; lgr %r2, %r6 +; lghi %r14, 5 +; lghi %r6, 6 +; stg %r14, 0(%r2) +; stg %r6, 8(%r2) +; lgr %r2, %r13 ; lmg %r6, %r15, 48(%r15) ; br %r14 ; @@ -57,16 +56,15 @@ block1: ; block0: ; offset 0x0 ; stmg %r6, %r15, 0x30(%r15) ; block1: ; offset 0x6 -; lghi %r5, 1 -; lgr %r6, %r5 +; lghi %r13, 1 ; lghi %r3, 2 ; lghi %r4, 3 ; lghi %r5, 4 -; lghi %r13, 5 -; lghi %r14, 6 -; stg %r13, 0(%r2) -; stg %r14, 8(%r2) -; lgr %r2, %r6 +; lghi %r14, 5 +; lghi %r6, 6 +; stg %r14, 0(%r2) +; stg %r6, 8(%r2) +; lgr %r2, %r13 ; lmg %r6, %r15, 0x30(%r15) ; br %r14 diff --git a/cranelift/filetests/filetests/isa/s390x/return-call-indirect.clif b/cranelift/filetests/filetests/isa/s390x/return-call-indirect.clif index 2145a60bf4b2..eb4bf5f5cc6f 100644 --- a/cranelift/filetests/filetests/isa/s390x/return-call-indirect.clif +++ b/cranelift/filetests/filetests/isa/s390x/return-call-indirect.clif @@ -278,16 +278,16 @@ block0: ; aghi %r15, -600 ; stg %r1, 0(%r15) ; block0: -; lghi %r2, 10 -; stg %r2, 272(%r15) -; lghi %r3, 15 -; stg %r3, 264(%r15) -; lghi %r4, 20 -; stg %r4, 256(%r15) -; lghi %r5, 25 -; stg %r5, 248(%r15) -; lghi %r6, 30 -; stg %r6, 240(%r15) +; lghi %r3, 10 +; stg %r3, 272(%r15) +; lghi %r4, 15 +; stg %r4, 264(%r15) +; lghi %r5, 20 +; stg %r5, 256(%r15) +; lghi %r6, 25 +; stg %r6, 248(%r15) +; lghi %r7, 30 +; stg %r7, 240(%r15) ; lghi %r7, 35 ; stg %r7, 232(%r15) ; lghi %r14, 40 @@ -356,8 +356,8 @@ block0: ; lg %r5, 248(%r15) ; lg %r6, 240(%r15) ; lg %r7, 232(%r15) -; lg %r13, 160(%r15) -; return_call_ind %r13 ; callee_pop_size 320 +; lg %r12, 160(%r15) +; return_call_ind %r12 ; callee_pop_size 320 ; ; Disassembled: ; block0: ; offset 0x0 @@ -366,16 +366,16 @@ block0: ; aghi %r15, -0x258 ; stg %r1, 0(%r15) ; block1: ; offset 0x14 -; lghi %r2, 0xa -; stg %r2, 0x110(%r15) -; lghi %r3, 0xf -; stg %r3, 0x108(%r15) -; lghi %r4, 0x14 -; stg %r4, 0x100(%r15) -; lghi %r5, 0x19 -; stg %r5, 0xf8(%r15) -; lghi %r6, 0x1e -; stg %r6, 0xf0(%r15) +; lghi %r3, 0xa +; stg %r3, 0x110(%r15) +; lghi %r4, 0xf +; stg %r4, 0x108(%r15) +; lghi %r5, 0x14 +; stg %r5, 0x100(%r15) +; lghi %r6, 0x19 +; stg %r6, 0xf8(%r15) +; lghi %r7, 0x1e +; stg %r7, 0xf0(%r15) ; lghi %r7, 0x23 ; stg %r7, 0xe8(%r15) ; lghi %r14, 0x28 @@ -449,8 +449,8 @@ block0: ; lg %r5, 0xf8(%r15) ; lg %r6, 0xf0(%r15) ; lg %r7, 0xe8(%r15) -; lg %r13, 0xa0(%r15) -; lgr %r1, %r13 +; lg %r12, 0xa0(%r15) +; lgr %r1, %r12 ; aghi %r15, 0x118 ; lmg %r8, %r14, 0x180(%r15) ; br %r1 diff --git a/cranelift/filetests/filetests/isa/s390x/return-call.clif b/cranelift/filetests/filetests/isa/s390x/return-call.clif index d5eb4772921d..bd521bc8d71a 100644 --- a/cranelift/filetests/filetests/isa/s390x/return-call.clif +++ b/cranelift/filetests/filetests/isa/s390x/return-call.clif @@ -105,45 +105,45 @@ block0(v0: i64): } ; VCode: -; stmg %r11, %r15, 88(%r15) +; stmg %r9, %r15, 72(%r15) ; lgr %r1, %r15 ; aghi %r15, -160 ; stg %r1, 0(%r15) ; block0: -; lgr %r11, %r2 -; lgr %r2, %r3 +; lgr %r9, %r2 ; bras %r1, 12 ; data %callee_i64 + 0 ; lg %r7, 0(%r1) +; lgr %r2, %r3 ; basr %r14, %r7 -; lgr %r3, %r2 ; bras %r1, 12 ; data %callee_i64_multiret + 0 ; lg %r7, 0(%r1) -; lgr %r2, %r11 +; lgr %r3, %r2 +; lgr %r2, %r9 ; return_call_ind %r7 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r11, %r15, 0x58(%r15) +; stmg %r9, %r15, 0x48(%r15) ; lgr %r1, %r15 ; aghi %r15, -0xa0 ; stg %r1, 0(%r15) ; block1: ; offset 0x14 -; lgr %r11, %r2 -; lgr %r2, %r3 -; bras %r1, 0x28 +; lgr %r9, %r2 +; bras %r1, 0x24 ; .byte 0x00, 0x00 ; reloc_external Abs8 %callee_i64 0 ; .byte 0x00, 0x00 ; .byte 0x00, 0x00 ; .byte 0x00, 0x00 ; lg %r7, 0(%r1) +; lgr %r2, %r3 ; basr %r14, %r7 -; lgr %r3, %r2 -; bras %r1, 0x40 +; bras %r1, 0x3c ; .byte 0x00, 0x00 ; reloc_external Abs8 %callee_i64_multiret 0 ; .byte 0x00, 0x00 ; .byte 0x00, 0x00 ; .byte 0x00, 0x00 ; lg %r7, 0(%r1) -; lgr %r2, %r11 -; lmg %r11, %r15, 0xf8(%r15) +; lgr %r3, %r2 +; lgr %r2, %r9 +; lmg %r9, %r15, 0xe8(%r15) ; br %r7 ;;;; Test colocated tail calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -350,19 +350,18 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v ; aghi %r15, -160 ; stg %r1, 0(%r15) ; block0: -; lgr %r14, %r5 -; lgr %r9, %r4 -; lgr %r4, %r6 -; lgr %r3, %r7 +; lgr %r9, %r7 +; lgr %r14, %r6 ; llgf %r6, 324(%r15) ; llgf %r7, 332(%r15) -; llgf %r5, 340(%r15) -; lg %r2, 344(%r15) -; stg %r2, 176(%r15) -; st %r5, 340(%r15) -; lgr %r5, %r3 -; lgr %r3, %r14 -; lgr %r2, %r9 +; llgf %r2, 340(%r15) +; lg %r3, 344(%r15) +; stg %r3, 176(%r15) +; st %r2, 340(%r15) +; lgr %r3, %r5 +; lgr %r5, %r9 +; lgr %r2, %r4 +; lgr %r4, %r14 ; return_call %one_stack_arg ; callee_pop_size 168 ; ; Disassembled: @@ -372,22 +371,21 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v ; aghi %r15, -0xa0 ; stg %r1, 0(%r15) ; block1: ; offset 0x14 -; lgr %r14, %r5 -; lgr %r9, %r4 -; lgr %r4, %r6 -; lgr %r3, %r7 +; lgr %r9, %r7 +; lgr %r14, %r6 ; llgf %r6, 0x144(%r15) ; llgf %r7, 0x14c(%r15) -; llgf %r5, 0x154(%r15) -; lg %r2, 0x158(%r15) -; stg %r2, 0xb0(%r15) -; st %r5, 0x154(%r15) -; lgr %r5, %r3 -; lgr %r3, %r14 -; lgr %r2, %r9 +; llgf %r2, 0x154(%r15) +; lg %r3, 0x158(%r15) +; stg %r3, 0xb0(%r15) +; st %r2, 0x154(%r15) +; lgr %r3, %r5 +; lgr %r5, %r9 +; lgr %r2, %r4 +; lgr %r4, %r14 ; aghi %r15, 0xb0 ; lmg %r9, %r14, 0xf0(%r15) -; jg 0x5c ; reloc_external PLTRel32Dbl %one_stack_arg 2 +; jg 0x58 ; reloc_external PLTRel32Dbl %one_stack_arg 2 function %call_zero_stack_args(i32, i32, i32, i32, i32, i32, i32, i32, i8) -> i8 tail { fn0 = colocated %callee_i8(i8) -> i8 tail @@ -427,51 +425,47 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32): } ; VCode: -; stmg %r9, %r15, 240(%r15) +; stmg %r8, %r15, 232(%r15) ; la %r1, 168(%r15) ; aghi %r15, -176 ; stg %r1, 0(%r15) ; block0: -; lgr %r14, %r5 -; lgr %r9, %r4 -; lgr %r4, %r6 -; lgr %r6, %r7 +; lgr %r8, %r7 ; llgf %r7, 340(%r15) -; lg %r5, 344(%r15) -; stg %r5, 160(%r15) +; lg %r10, 344(%r15) +; stg %r10, 160(%r15) ; st %r2, 324(%r15) ; st %r2, 332(%r15) ; st %r3, 340(%r15) -; lgr %r5, %r4 -; lgr %r4, %r14 ; lgr %r2, %r3 -; lgr %r3, %r9 +; lgr %r3, %r4 +; lgr %r4, %r5 +; lgr %r5, %r6 +; lgr %r6, %r8 ; return_call %call_one_stack_arg ; callee_pop_size 184 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r9, %r15, 0xf0(%r15) +; stmg %r8, %r15, 0xe8(%r15) ; la %r1, 0xa8(%r15) ; aghi %r15, -0xb0 ; stg %r1, 0(%r15) ; block1: ; offset 0x14 -; lgr %r14, %r5 -; lgr %r9, %r4 -; lgr %r4, %r6 -; lgr %r6, %r7 +; lgr %r8, %r7 ; llgf %r7, 0x154(%r15) -; lg %r5, 0x158(%r15) -; stg %r5, 0xa0(%r15) +; lg %r10, 0x158(%r15) +; stg %r10, 0xa0(%r15) ; st %r2, 0x144(%r15) ; st %r2, 0x14c(%r15) ; st %r3, 0x154(%r15) -; lgr %r5, %r4 -; lgr %r4, %r14 ; lgr %r2, %r3 -; lgr %r3, %r9 +; lgr %r3, %r4 +; lgr %r4, %r5 +; lgr %r5, %r6 +; lgr %r6, %r8 ; aghi %r15, 0xa0 -; lmg %r9, %r14, 0x100(%r15) -; jg 0x5c ; reloc_external PLTRel32Dbl %call_one_stack_arg 2 +; lmg %r8, %r14, 0xf8(%r15) +; jg 0x54 ; reloc_external PLTRel32Dbl %call_one_stack_arg 2 ;;;; Test passing many arguments on stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -542,16 +536,16 @@ block0: ; aghi %r15, -592 ; stg %r1, 0(%r15) ; block0: -; lghi %r2, 10 -; stg %r2, 264(%r15) -; lghi %r3, 15 -; stg %r3, 256(%r15) -; lghi %r4, 20 -; stg %r4, 248(%r15) -; lghi %r5, 25 -; stg %r5, 240(%r15) -; lghi %r6, 30 -; stg %r6, 232(%r15) +; lghi %r3, 10 +; stg %r3, 264(%r15) +; lghi %r4, 15 +; stg %r4, 256(%r15) +; lghi %r5, 20 +; stg %r5, 248(%r15) +; lghi %r6, 25 +; stg %r6, 240(%r15) +; lghi %r7, 30 +; stg %r7, 232(%r15) ; lghi %r7, 35 ; stg %r7, 224(%r15) ; lghi %r14, 40 @@ -628,16 +622,16 @@ block0: ; aghi %r15, -0x250 ; stg %r1, 0(%r15) ; block1: ; offset 0x14 -; lghi %r2, 0xa -; stg %r2, 0x108(%r15) -; lghi %r3, 0xf -; stg %r3, 0x100(%r15) -; lghi %r4, 0x14 -; stg %r4, 0xf8(%r15) -; lghi %r5, 0x19 -; stg %r5, 0xf0(%r15) -; lghi %r6, 0x1e -; stg %r6, 0xe8(%r15) +; lghi %r3, 0xa +; stg %r3, 0x108(%r15) +; lghi %r4, 0xf +; stg %r4, 0x100(%r15) +; lghi %r5, 0x14 +; stg %r5, 0xf8(%r15) +; lghi %r6, 0x19 +; stg %r6, 0xf0(%r15) +; lghi %r7, 0x1e +; stg %r7, 0xe8(%r15) ; lghi %r7, 0x23 ; stg %r7, 0xe0(%r15) ; lghi %r14, 0x28 diff --git a/cranelift/filetests/filetests/isa/s390x/struct-arg.clif b/cranelift/filetests/filetests/isa/s390x/struct-arg.clif index e34cf9058063..b7b8f20974d1 100644 --- a/cranelift/filetests/filetests/isa/s390x/struct-arg.clif +++ b/cranelift/filetests/filetests/isa/s390x/struct-arg.clif @@ -163,41 +163,41 @@ block0(v0: i64, v1: i64, v2: i64): } ; VCode: -; stmg %r7, %r15, 56(%r15) +; stmg %r8, %r15, 64(%r15) ; aghi %r15, -1248 ; block0: -; lgr %r7, %r2 -; lgr %r9, %r4 +; lgr %r8, %r2 +; lgr %r10, %r4 ; la %r2, 160(%r15) ; la %r3, 0(%r3) ; lghi %r4, 1024 ; brasl %r14, %Memcpy -; lgr %r4, %r9 +; lgr %r4, %r10 ; mvc 1184(63,%r15), 0(%r4) ; la %r3, 160(%r15) ; la %r4, 1184(%r15) -; lgr %r2, %r7 +; lgr %r2, %r8 ; brasl %r14, userextname0 -; lmg %r7, %r15, 1304(%r15) +; lmg %r8, %r15, 1312(%r15) ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r7, %r15, 0x38(%r15) +; stmg %r8, %r15, 0x40(%r15) ; aghi %r15, -0x4e0 ; block1: ; offset 0xa -; lgr %r7, %r2 -; lgr %r9, %r4 +; lgr %r8, %r2 +; lgr %r10, %r4 ; la %r2, 0xa0(%r15) ; la %r3, 0(%r3) ; lghi %r4, 0x400 ; brasl %r14, 0x1e ; reloc_external PLTRel32Dbl %Memcpy 2 -; lgr %r4, %r9 +; lgr %r4, %r10 ; mvc 0x4a0(0x40, %r15), 0(%r4) ; la %r3, 0xa0(%r15) ; la %r4, 0x4a0(%r15) -; lgr %r2, %r7 +; lgr %r2, %r8 ; brasl %r14, 0x3a ; reloc_external PLTRel32Dbl u0:0 2 -; lmg %r7, %r15, 0x518(%r15) +; lmg %r8, %r15, 0x520(%r15) ; br %r14 diff --git a/cranelift/filetests/filetests/isa/s390x/tls_elf.clif b/cranelift/filetests/filetests/isa/s390x/tls_elf.clif index 250f1c50c1c7..b31136506915 100644 --- a/cranelift/filetests/filetests/isa/s390x/tls_elf.clif +++ b/cranelift/filetests/filetests/isa/s390x/tls_elf.clif @@ -16,7 +16,7 @@ block0(v0: i32): ; block0: ; larl %r12, %ElfGlobalOffsetTable + 0 ; bras %r1, 12 ; data userextname0@tlsgd ; lg %r2, 0(%r1) -; brasl %r14, %ElfTlsGetOffset:tls_gdcall:userextname0 +; brasl %r14, tls_gdcall:userextname0 ; ear %r4, %a0 ; sllg %r3, %r4, 32 ; ear %r3, %a1 diff --git a/cranelift/filetests/filetests/isa/s390x/user_stack_maps.clif b/cranelift/filetests/filetests/isa/s390x/user_stack_maps.clif index 9ee6c7c1f8b1..053dde2c7217 100644 --- a/cranelift/filetests/filetests/isa/s390x/user_stack_maps.clif +++ b/cranelift/filetests/filetests/isa/s390x/user_stack_maps.clif @@ -32,73 +32,67 @@ block0: } ; VCode: -; stmg %r7, %r15, 56(%r15) +; stmg %r6, %r15, 48(%r15) ; aghi %r15, -176 ; block0: -; lhi %r2, 0 -; lgr %r11, %r2 -; lhi %r2, 1 -; lgr %r7, %r2 -; lhi %r2, 2 -; lgr %r9, %r2 +; lhi %r8, 0 +; lhi %r6, 1 +; lhi %r7, 2 ; la %r2, 160(%r15) ; mvhi 0(%r2), 0 ; la %r3, 164(%r15) ; mvhi 0(%r3), 1 ; la %r4, 168(%r15) ; mvhi 0(%r4), 2 -; lgr %r2, %r11 +; lgr %r2, %r8 ; brasl %r14, userextname0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4, 8})], sp_to_sized_stack_slots: None } ; la %r2, 160(%r15) ; mvhi 0(%r2), 1 ; la %r3, 164(%r15) ; mvhi 0(%r3), 2 -; lgr %r2, %r11 +; lgr %r2, %r8 ; brasl %r14, userextname0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4})], sp_to_sized_stack_slots: None } ; la %r5, 160(%r15) ; mvhi 0(%r5), 2 -; lgr %r2, %r7 +; lgr %r2, %r6 ; brasl %r14, userextname0 ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0})], sp_to_sized_stack_slots: None } -; lgr %r2, %r9 +; lgr %r2, %r7 ; brasl %r14, userextname0 -; lmg %r7, %r15, 232(%r15) +; lmg %r6, %r15, 224(%r15) ; br %r14 ; ; Disassembled: ; block0: ; offset 0x0 -; stmg %r7, %r15, 0x38(%r15) +; stmg %r6, %r15, 0x30(%r15) ; aghi %r15, -0xb0 ; block1: ; offset 0xa -; lhi %r2, 0 -; lgr %r11, %r2 -; lhi %r2, 1 -; lgr %r7, %r2 -; lhi %r2, 2 -; lgr %r9, %r2 +; lhi %r8, 0 +; lhi %r6, 1 +; lhi %r7, 2 ; la %r2, 0xa0(%r15) ; mvhi 0(%r2), 0 ; la %r3, 0xa4(%r15) ; mvhi 0(%r3), 1 ; la %r4, 0xa8(%r15) ; mvhi 0(%r4), 2 -; lgr %r2, %r11 -; brasl %r14, 0x44 ; reloc_external PLTRel32Dbl u0:0 2 +; lgr %r2, %r8 +; brasl %r14, 0x38 ; reloc_external PLTRel32Dbl u0:0 2 ; la %r2, 0xa0(%r15) ; mvhi 0(%r2), 1 ; la %r3, 0xa4(%r15) ; mvhi 0(%r3), 2 -; lgr %r2, %r11 -; brasl %r14, 0x62 ; reloc_external PLTRel32Dbl u0:0 2 +; lgr %r2, %r8 +; brasl %r14, 0x56 ; reloc_external PLTRel32Dbl u0:0 2 ; la %r5, 0xa0(%r15) ; mvhi 0(%r5), 2 +; lgr %r2, %r6 +; brasl %r14, 0x6a ; reloc_external PLTRel32Dbl u0:0 2 ; lgr %r2, %r7 -; brasl %r14, 0x76 ; reloc_external PLTRel32Dbl u0:0 2 -; lgr %r2, %r9 -; brasl %r14, 0x80 ; reloc_external PLTRel32Dbl u0:0 2 -; lmg %r7, %r15, 0xe8(%r15) +; brasl %r14, 0x74 ; reloc_external PLTRel32Dbl u0:0 2 +; lmg %r6, %r15, 0xe0(%r15) ; br %r14 function %different_types(i8, i16, i32, i64, f32, f64) -> i8, i16, i32, i64, f32, f64 { @@ -135,28 +129,28 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; block0: ; la %r9, 160(%r15) ; stc %r2, 0(%r9) -; lgr %r11, %r2 +; lgr %r9, %r2 ; la %r2, 168(%r15) ; sth %r3, 0(%r2) -; lgr %r9, %r3 +; lgr %r6, %r3 ; la %r2, 176(%r15) ; st %r4, 0(%r2) -; lgr %r7, %r4 +; lgr %r11, %r4 ; la %r2, 180(%r15) ; ste %f0, 0(%r2) ; vst %v0, 256(%r15) ; la %r2, 184(%r15) ; stg %r5, 0(%r2) -; lgr %r6, %r5 +; lgr %r8, %r5 ; la %r3, 192(%r15) ; std %f2, 0(%r3) ; vst %v2, 272(%r15) ; brasl %r14, userextname0 ; ; UserStackMap { by_type: [(types::I8, CompoundBitSet {0}), (types::I16, CompoundBitSet {8}), (types::I32, CompoundBitSet {16}), (types::F32, CompoundBitSet {20}), (types::I64, CompoundBitSet {24}), (types::F64, CompoundBitSet {32})], sp_to_sized_stack_slots: None } -; lgr %r2, %r11 -; lgr %r3, %r9 -; lgr %r4, %r7 -; lgr %r5, %r6 +; lgr %r2, %r9 +; lgr %r3, %r6 +; lgr %r4, %r11 +; lgr %r5, %r8 ; vl %v0, 256(%r15) ; vl %v2, 272(%r15) ; ld %f8, 288(%r15) @@ -185,27 +179,27 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; block1: ; offset 0x2a ; la %r9, 0xa0(%r15) ; stc %r2, 0(%r9) -; lgr %r11, %r2 +; lgr %r9, %r2 ; la %r2, 0xa8(%r15) ; sth %r3, 0(%r2) -; lgr %r9, %r3 +; lgr %r6, %r3 ; la %r2, 0xb0(%r15) ; st %r4, 0(%r2) -; lgr %r7, %r4 +; lgr %r11, %r4 ; la %r2, 0xb4(%r15) ; ste %f0, 0(%r2) ; vst %v0, 0x100(%r15) ; la %r2, 0xb8(%r15) ; stg %r5, 0(%r2) -; lgr %r6, %r5 +; lgr %r8, %r5 ; la %r3, 0xc0(%r15) ; std %f2, 0(%r3) ; vst %v2, 0x110(%r15) ; brasl %r14, 0x78 ; reloc_external PLTRel32Dbl u0:0 2 -; lgr %r2, %r11 -; lgr %r3, %r9 -; lgr %r4, %r7 -; lgr %r5, %r6 +; lgr %r2, %r9 +; lgr %r3, %r6 +; lgr %r4, %r11 +; lgr %r5, %r8 ; vl %v0, 0x100(%r15) ; vl %v2, 0x110(%r15) ; ld %f8, 0x120(%r15) diff --git a/cranelift/filetests/filetests/isa/x64/bmi2.clif b/cranelift/filetests/filetests/isa/x64/bmi2.clif index 134853ed393e..2d145fe531a8 100644 --- a/cranelift/filetests/filetests/isa/x64/bmi2.clif +++ b/cranelift/filetests/filetests/isa/x64/bmi2.clif @@ -1,4 +1,5 @@ test compile precise-output +set enable_llvm_abi_extensions=true target x86_64 has_bmi2 function %sarx_i32(i32, i32) -> i32 { @@ -346,3 +347,86 @@ block0(v0: i64, v1: i32): ; popq %rbp ; retq +function %extend_to_i128_mul_mulxq(i64, i64) -> i128 { +block0(v0: i64, v1: i64): + v2 = uextend.i128 v0 + v3 = uextend.i128 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rdx +; mulxq %rdx, %rsi, %rax, %rdx +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; movq %rdi, %rdx +; mulxq %rsi, %rax, %rdx +; movq %rbp, %rsp +; popq %rbp +; retq + +function %umulhi_mulxl(i32, i32) -> i32 { +block0(v0: i32, v1: i32): + v2 = umulhi v0, v1 + return v2 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rdx +; mulxl %edx, %esi, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; movq %rdi, %rdx +; mulxl %esi, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; retq + +function %umulhi_mulxq(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = umulhi v0, v1 + return v2 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rdx +; mulxq %rdx, %rsi, %rax, %rax +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; movq %rdi, %rdx +; mulxq %rsi, %rax, %rax +; movq %rbp, %rsp +; popq %rbp +; retq + diff --git a/cranelift/filetests/filetests/isa/x64/call-conv.clif b/cranelift/filetests/filetests/isa/x64/call-conv.clif index a3b06408892d..6b9deb3a5be1 100644 --- a/cranelift/filetests/filetests/isa/x64/call-conv.clif +++ b/cranelift/filetests/filetests/isa/x64/call-conv.clif @@ -193,11 +193,6 @@ block0( ; movq %rsp, %rbp ; subq %rsp, $144, %rsp ; block0: -; movq %rcx, %rax -; movq %rdx, %rcx -; movq %rsi, %rdx -; movq %rdi, %rsi -; movq %rax, %rdi ; movq rbp(stack args max - 32), %r10 ; movq rbp(stack args max - 24), %r11 ; movss rbp(stack args max - 16), %xmm11 @@ -216,9 +211,10 @@ block0( ; movl %r11d, 120(%rsp) ; movss %xmm11, 128(%rsp) ; movsd %xmm13, 136(%rsp) -; movq %rdi, %r9 -; movq %rcx, %r8 -; movq %rsi, %rcx +; movq %rcx, %r9 +; movq %rdx, %r8 +; movq %rsi, %rdx +; movq %rdi, %rcx ; call *%rcx ; addq %rsp, $144, %rsp ; movq %rbp, %rsp @@ -231,11 +227,6 @@ block0( ; movq %rsp, %rbp ; subq $0x90, %rsp ; block1: ; offset 0xb -; movq %rcx, %rax -; movq %rdx, %rcx -; movq %rsi, %rdx -; movq %rdi, %rsi -; movq %rax, %rdi ; movq 0x10(%rbp), %r10 ; movq 0x18(%rbp), %r11 ; movss 0x20(%rbp), %xmm11 @@ -254,9 +245,10 @@ block0( ; movl %r11d, 0x78(%rsp) ; movss %xmm11, 0x80(%rsp) ; movsd %xmm13, 0x88(%rsp) -; movq %rdi, %r9 -; movq %rcx, %r8 -; movq %rsi, %rcx +; movq %rcx, %r9 +; movq %rdx, %r8 +; movq %rsi, %rdx +; movq %rdi, %rcx ; callq *%rcx ; addq $0x90, %rsp ; movq %rbp, %rsp @@ -280,12 +272,11 @@ block0(v0: i64, v1:i64, v2:i64, v3:i64, v4:i64): ; movq %rsp, %rbp ; subq %rsp, $48, %rsp ; block0: -; movq %rdx, %r11 +; movq %r8, 32(%rsp) ; movq %rcx, %r9 +; movq %rdx, %r8 ; movq %rsi, %rdx ; movq %rdi, %rcx -; movq %r8, 32(%rsp) -; movq %r11, %r8 ; call *%rcx ; addq %rsp, $48, %rsp ; movq %rbp, %rsp @@ -298,12 +289,11 @@ block0(v0: i64, v1:i64, v2:i64, v3:i64, v4:i64): ; movq %rsp, %rbp ; subq $0x30, %rsp ; block1: ; offset 0x8 -; movq %rdx, %r11 +; movq %r8, 0x20(%rsp) ; movq %rcx, %r9 +; movq %rdx, %r8 ; movq %rsi, %rdx ; movq %rdi, %rcx -; movq %r8, 0x20(%rsp) -; movq %r11, %r8 ; callq *%rcx ; addq $0x30, %rsp ; movq %rbp, %rsp @@ -322,10 +312,6 @@ block0(v0: i32, v1: f32, v2: i64, v3: f64, v4: i32, v5: i32, v6: i32, v7: f32, v ; movq %rsp, %rbp ; subq %rsp, $96, %rsp ; block0: -; movq %rsi, %r9 -; movq %rdi, %rsi -; movdqa %xmm1, %xmm6 -; movdqa %xmm0, %xmm1 ; movl %edx, 32(%rsp) ; movl %ecx, 40(%rsp) ; movl %r8d, 48(%rsp) @@ -333,9 +319,10 @@ block0(v0: i32, v1: f32, v2: i64, v3: f64, v4: i32, v5: i32, v6: i32, v7: f32, v ; movsd %xmm3, 64(%rsp) ; movss %xmm4, 72(%rsp) ; movsd %xmm5, 80(%rsp) -; movq %rsi, %rcx -; movq %r9, %r8 -; movdqa %xmm6, %xmm3 +; movq %rdi, %rcx +; movq %rsi, %r8 +; movdqa %xmm1, %xmm3 +; movdqa %xmm0, %xmm1 ; call *%rcx ; addq %rsp, $96, %rsp ; movq %rbp, %rsp @@ -348,10 +335,6 @@ block0(v0: i32, v1: f32, v2: i64, v3: f64, v4: i32, v5: i32, v6: i32, v7: f32, v ; movq %rsp, %rbp ; subq $0x60, %rsp ; block1: ; offset 0x8 -; movq %rsi, %r9 -; movq %rdi, %rsi -; movdqa %xmm1, %xmm6 -; movdqa %xmm0, %xmm1 ; movl %edx, 0x20(%rsp) ; movl %ecx, 0x28(%rsp) ; movl %r8d, 0x30(%rsp) @@ -359,9 +342,10 @@ block0(v0: i32, v1: f32, v2: i64, v3: f64, v4: i32, v5: i32, v6: i32, v7: f32, v ; movsd %xmm3, 0x40(%rsp) ; movss %xmm4, 0x48(%rsp) ; movsd %xmm5, 0x50(%rsp) -; movq %rsi, %rcx -; movq %r9, %r8 -; movdqa %xmm6, %xmm3 +; movq %rdi, %rcx +; movq %rsi, %r8 +; movdqa %xmm1, %xmm3 +; movdqa %xmm0, %xmm1 ; callq *%rcx ; addq $0x60, %rsp ; movq %rbp, %rsp @@ -415,12 +399,12 @@ block0(v0: i32, v1: i32, v2: i8x16, v3: i64, v4: i8x16): ; movq %rsp, %rbp ; subq %rsp, $64, %rsp ; block0: -; movq %rsi, %rcx ; movq %rdx, %r8 ; lea 32(%rsp), %rdx ; movdqu %xmm0, 0(%rdx) ; lea 48(%rsp), %r9 ; movdqu %xmm1, 0(%r9) +; movq %rsi, %rcx ; call *%rdi ; paddb %xmm0, %xmm0, %xmm0 ; addq %rsp, $64, %rsp @@ -434,12 +418,12 @@ block0(v0: i32, v1: i32, v2: i8x16, v3: i64, v4: i8x16): ; movq %rsp, %rbp ; subq $0x40, %rsp ; block1: ; offset 0x8 -; movq %rsi, %rcx ; movq %rdx, %r8 ; leaq 0x20(%rsp), %rdx ; movdqu %xmm0, (%rdx) ; leaq 0x30(%rsp), %r9 ; movdqu %xmm1, (%r9) +; movq %rsi, %rcx ; callq *%rdi ; paddb %xmm0, %xmm0 ; addq $0x40, %rsp @@ -459,10 +443,10 @@ block0(v0: i32, v1: i8x16): ; movq %rsp, %rbp ; subq %rsp, $64, %rsp ; block0: -; movq %rdi, %r9 ; lea 48(%rsp), %rcx ; movdqu %xmm0, 0(%rcx) ; movq %rcx, 32(%rsp) +; movq %rdi, %r9 ; movq %r9, %rcx ; movq %r9, %rdx ; movq %r9, %r8 @@ -478,10 +462,10 @@ block0(v0: i32, v1: i8x16): ; movq %rsp, %rbp ; subq $0x40, %rsp ; block1: ; offset 0x8 -; movq %rdi, %r9 ; leaq 0x30(%rsp), %rcx ; movdqu %xmm0, (%rcx) ; movq %rcx, 0x20(%rsp) +; movq %rdi, %r9 ; movq %r9, %rcx ; movq %r9, %rdx ; movq %r9, %r8 @@ -503,13 +487,13 @@ block0(v0: i32, v1: i8x16): ; movq %rsp, %rbp ; subq %rsp, $80, %rsp ; block0: -; movq %rdi, %r9 ; lea 48(%rsp), %rcx ; movdqu %xmm0, 0(%rcx) ; movq %rcx, 32(%rsp) ; lea 64(%rsp), %r10 ; movdqu %xmm0, 0(%r10) ; movq %r10, 40(%rsp) +; movq %rdi, %r9 ; movq %r9, %rcx ; movq %r9, %rdx ; movq %r9, %r8 @@ -525,13 +509,13 @@ block0(v0: i32, v1: i8x16): ; movq %rsp, %rbp ; subq $0x50, %rsp ; block1: ; offset 0x8 -; movq %rdi, %r9 ; leaq 0x30(%rsp), %rcx ; movdqu %xmm0, (%rcx) ; movq %rcx, 0x20(%rsp) ; leaq 0x40(%rsp), %r10 ; movdqu %xmm0, (%r10) ; movq %r10, 0x28(%rsp) +; movq %rdi, %r9 ; movq %r9, %rcx ; movq %r9, %rdx ; movq %r9, %r8 @@ -553,16 +537,15 @@ block0(v0: i32, v1: i8x16): ; movq %rsp, %rbp ; subq %rsp, $96, %rsp ; block0: -; movq %rdi, %r10 ; lea 48(%rsp), %rdx ; movdqu %xmm0, 0(%rdx) ; lea 64(%rsp), %r9 ; movdqu %xmm0, 0(%r9) ; movq %r9, 32(%rsp) -; lea 80(%rsp), %rdi -; movdqu %xmm0, 0(%rdi) -; movq %rdi, 40(%rsp) -; movq %r10, %r9 +; lea 80(%rsp), %rax +; movdqu %xmm0, 0(%rax) +; movq %rax, 40(%rsp) +; movq %rdi, %r9 ; movq %r9, %rcx ; movq %r9, %r8 ; call *%r9 @@ -577,16 +560,15 @@ block0(v0: i32, v1: i8x16): ; movq %rsp, %rbp ; subq $0x60, %rsp ; block1: ; offset 0x8 -; movq %rdi, %r10 ; leaq 0x30(%rsp), %rdx ; movdqu %xmm0, (%rdx) ; leaq 0x40(%rsp), %r9 ; movdqu %xmm0, (%r9) ; movq %r9, 0x20(%rsp) -; leaq 0x50(%rsp), %rdi -; movdqu %xmm0, (%rdi) -; movq %rdi, 0x28(%rsp) -; movq %r10, %r9 +; leaq 0x50(%rsp), %rax +; movdqu %xmm0, (%rax) +; movq %rax, 0x28(%rsp) +; movq %rdi, %r9 ; movq %r9, %rcx ; movq %r9, %r8 ; callq *%r9 diff --git a/cranelift/filetests/filetests/isa/x64/fastcall.clif b/cranelift/filetests/filetests/isa/x64/fastcall.clif index 44b42f9621fe..b12e5452234e 100644 --- a/cranelift/filetests/filetests/isa/x64/fastcall.clif +++ b/cranelift/filetests/filetests/isa/x64/fastcall.clif @@ -245,8 +245,8 @@ block0(v0: i64): ; cvtsi2sd %xmm3, %rcx, %xmm3 ; movq %rcx, 32(%rsp) ; movq %rcx, 40(%rsp) -; movq %rcx, %rdx ; load_ext_name %g+0, %r11 +; movq %rcx, %rdx ; movdqa %xmm3, %xmm2 ; call *%r11 ; addq %rsp, $48, %rsp @@ -264,8 +264,8 @@ block0(v0: i64): ; cvtsi2sdq %rcx, %xmm3 ; movq %rcx, 0x20(%rsp) ; movq %rcx, 0x28(%rsp) -; movq %rcx, %rdx ; movabsq $0, %r11 ; reloc_external Abs8 %g 0 +; movq %rcx, %rdx ; movdqa %xmm3, %xmm2 ; callq *%r11 ; addq $0x30, %rsp diff --git a/cranelift/filetests/filetests/isa/x64/fma-call.clif b/cranelift/filetests/filetests/isa/x64/fma-call.clif index 8b19a8e9455e..5572974f00c1 100644 --- a/cranelift/filetests/filetests/isa/x64/fma-call.clif +++ b/cranelift/filetests/filetests/isa/x64/fma-call.clif @@ -187,9 +187,9 @@ block0(v0: f64x2, v1: f64x2, v2: f64x2): ; pshufd $238, %xmm2, %xmm2 ; load_ext_name %FmaF64+0, %r9 ; call *%r9 -; movdqa %xmm0, %xmm7 +; movdqa %xmm0, %xmm6 ; movdqu rsp(48 + virtual offset), %xmm0 -; movlhps %xmm0, %xmm7, %xmm0 +; movlhps %xmm0, %xmm6, %xmm0 ; addq %rsp, $64, %rsp ; movq %rbp, %rsp ; popq %rbp @@ -215,9 +215,9 @@ block0(v0: f64x2, v1: f64x2, v2: f64x2): ; pshufd $0xee, %xmm2, %xmm2 ; movabsq $0, %r9 ; reloc_external Abs8 %FmaF64 0 ; callq *%r9 -; movdqa %xmm0, %xmm7 +; movdqa %xmm0, %xmm6 ; movdqu 0x30(%rsp), %xmm0 -; movlhps %xmm7, %xmm0 +; movlhps %xmm6, %xmm0 ; addq $0x40, %rsp ; movq %rbp, %rsp ; popq %rbp diff --git a/cranelift/filetests/filetests/isa/x64/i128.clif b/cranelift/filetests/filetests/isa/x64/i128.clif index 62df9b43a993..9c1b901673c7 100644 --- a/cranelift/filetests/filetests/isa/x64/i128.clif +++ b/cranelift/filetests/filetests/isa/x64/i128.clif @@ -202,13 +202,13 @@ block0(v0: i128, v1: i128): ; movq %rdi, %rdx ; imulq %rdx, %rcx, %rdx ; movq %rax, %rcx -; movq %rdi, %rax ; imulq %rsi, %rcx, %rsi ; addq %rdx, %rsi, %rdx -; movq %rdx, %r9 +; movq %rdi, %rax +; movq %rdx, %r8 ; mulq %rax, %rcx, %rax, %rdx ; movq %rdx, %rcx -; movq %r9, %rdx +; movq %r8, %rdx ; addq %rdx, %rcx, %rdx ; movq %rbp, %rsp ; popq %rbp @@ -223,13 +223,13 @@ block0(v0: i128, v1: i128): ; movq %rdi, %rdx ; imulq %rcx, %rdx ; movq %rax, %rcx -; movq %rdi, %rax ; imulq %rcx, %rsi ; addq %rsi, %rdx -; movq %rdx, %r9 +; movq %rdi, %rax +; movq %rdx, %r8 ; mulq %rcx ; movq %rdx, %rcx -; movq %r9, %rdx +; movq %r8, %rdx ; addq %rcx, %rdx ; movq %rbp, %rsp ; popq %rbp @@ -564,8 +564,8 @@ block0(v0: i64): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; movq %rbp, %rsp ; popq %rbp ; ret @@ -575,8 +575,8 @@ block0(v0: i64): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; movq %rbp, %rsp ; popq %rbp ; retq @@ -1251,8 +1251,8 @@ block0(v0: i128): ; movq %rdi, 32(%rdx) ; movq %rsi, 40(%rdx) ; movq %rdi, 48(%rdx) -; movq %rdi, %rcx ; movq %rsi, 56(%rdx) +; movq %rdi, %rcx ; movq %rsi, %rdx ; movq %rcx, %rax ; movq %rbp, %rsp @@ -1271,8 +1271,8 @@ block0(v0: i128): ; movq %rdi, 0x20(%rdx) ; movq %rsi, 0x28(%rdx) ; movq %rdi, 0x30(%rdx) -; movq %rdi, %rcx ; movq %rsi, 0x38(%rdx) +; movq %rdi, %rcx ; movq %rsi, %rdx ; movq %rcx, %rax ; movq %rbp, %rsp diff --git a/cranelift/filetests/filetests/isa/x64/mul.clif b/cranelift/filetests/filetests/isa/x64/mul.clif index f12a73f05919..ec771cddbaef 100644 --- a/cranelift/filetests/filetests/isa/x64/mul.clif +++ b/cranelift/filetests/filetests/isa/x64/mul.clif @@ -487,3 +487,62 @@ block0(v0: i64): ; popq %rbp ; retq + +function %widening_smul_from_8bit(i8, i8) -> i16 { +block0(v0: i8, v1: i8): + v2 = sextend.i16 v0 + v3 = sextend.i16 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; imulb %al, %sil, %al +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; movq %rdi, %rax +; imulb %sil +; movq %rbp, %rsp +; popq %rbp +; retq + +function %widening_umul_from_8bit(i8, i8) -> i16 { +block0(v0: i8, v1: i8): + v2 = uextend.i16 v0 + v3 = uextend.i16 v1 + v4 = imul v2, v3 + return v4 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; mulb %al, %sil, %al +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; movq %rdi, %rax +; mulb %sil +; movq %rbp, %rsp +; popq %rbp +; retq + diff --git a/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif b/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif index 22ba0bb94307..d8889e147673 100644 --- a/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif +++ b/cranelift/filetests/filetests/isa/x64/return-call-indirect.clif @@ -260,16 +260,16 @@ block0: ; movq %r14, 136(%rsp) ; movq %r15, 144(%rsp) ; block0: -; movl $10, %edi -; movq %rdi, rsp(104 + virtual offset) -; movl $15, %esi -; movq %rsi, rsp(96 + virtual offset) -; movl $20, %edx -; movq %rdx, rsp(88 + virtual offset) -; movl $25, %ecx -; movq %rcx, rsp(80 + virtual offset) -; movl $30, %r8d -; movq %r8, rsp(72 + virtual offset) +; movl $10, %esi +; movq %rsi, rsp(104 + virtual offset) +; movl $15, %edx +; movq %rdx, rsp(96 + virtual offset) +; movl $20, %ecx +; movq %rcx, rsp(88 + virtual offset) +; movl $25, %r8d +; movq %r8, rsp(80 + virtual offset) +; movl $30, %r9d +; movq %r9, rsp(72 + virtual offset) ; movl $35, %r9d ; movq %r9, rsp(64 + virtual offset) ; movl $40, %eax @@ -354,16 +354,16 @@ block0: ; movq %r14, 0x88(%rsp) ; movq %r15, 0x90(%rsp) ; block1: ; offset 0x50 -; movl $0xa, %edi -; movq %rdi, 0x68(%rsp) -; movl $0xf, %esi -; movq %rsi, 0x60(%rsp) -; movl $0x14, %edx -; movq %rdx, 0x58(%rsp) -; movl $0x19, %ecx -; movq %rcx, 0x50(%rsp) -; movl $0x1e, %r8d -; movq %r8, 0x48(%rsp) +; movl $0xa, %esi +; movq %rsi, 0x68(%rsp) +; movl $0xf, %edx +; movq %rdx, 0x60(%rsp) +; movl $0x14, %ecx +; movq %rcx, 0x58(%rsp) +; movl $0x19, %r8d +; movq %r8, 0x50(%rsp) +; movl $0x1e, %r9d +; movq %r9, 0x48(%rsp) ; movl $0x23, %r9d ; movq %r9, 0x40(%rsp) ; movl $0x28, %eax diff --git a/cranelift/filetests/filetests/isa/x64/return-call.clif b/cranelift/filetests/filetests/isa/x64/return-call.clif index f6f4250b3546..e20657ff82e3 100644 --- a/cranelift/filetests/filetests/isa/x64/return-call.clif +++ b/cranelift/filetests/filetests/isa/x64/return-call.clif @@ -233,15 +233,16 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rcx, %r10 -; movq %rdx, %rdi -; movq %r8, %rdx -; movq %r9, %rcx +; movq %r8, %r10 +; movq %r9, %r11 ; movq rbp(stack args max - 32), %r8 ; movq rbp(stack args max - 24), %r9 ; movq rbp(stack args max - 16), %rsi ; movl %esi, rbp(stack args max - 16) -; movq %r10, %rsi +; movq %rdx, %rdi +; movq %rcx, %rsi +; movq %r10, %rdx +; movq %r11, %rcx ; return_call_known TestCase(%one_stack_arg) (16) tmp=%r11 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9 ; ; Disassembled: @@ -249,21 +250,22 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32, v ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rcx, %r10 -; movq %rdx, %rdi -; movq %r8, %rdx -; movq %r9, %rcx +; movq %r8, %r10 +; movq %r9, %r11 ; movq 0x10(%rbp), %r8 ; movq 0x18(%rbp), %r9 ; movq 0x20(%rbp), %rsi ; movl %esi, 0x20(%rbp) -; movq %r10, %rsi +; movq %rdx, %rdi +; movq %rcx, %rsi +; movq %r10, %rdx +; movq %r11, %rcx ; movq %rbp, %rsp ; popq %rbp ; movq (%rsp), %r11 ; movq %r11, 0x10(%rsp) ; addq $0x10, %rsp -; jmp 0x38 ; reloc_external CallPCRel4 %one_stack_arg -4 +; jmp 0x3b ; reloc_external CallPCRel4 %one_stack_arg -4 function %call_zero_stack_args(i32, i32, i32, i32, i32, i32, i32, i32, i8) -> i8 tail { fn0 = colocated %callee_i8(i8) -> i8 tail @@ -311,16 +313,16 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32): ; movq 24(%rsp), %r11 ; movq %r11, 8(%rsp) ; block0: -; movq %rdx, %r10 -; movq %rcx, %rdx -; movq %r8, %rcx -; movq %r9, %r8 +; movq %r9, %r10 ; movq rbp(stack args max - 16), %r9 ; movl %edi, rbp(stack args max - 32) ; movl %edi, rbp(stack args max - 24) ; movl %esi, rbp(stack args max - 16) ; movq %rsi, %rdi -; movq %r10, %rsi +; movq %rdx, %rsi +; movq %rcx, %rdx +; movq %r8, %rcx +; movq %r10, %r8 ; return_call_known TestCase(%call_one_stack_arg) (32) tmp=%r11 %rdi=%rdi %rsi=%rsi %rdx=%rdx %rcx=%rcx %r8=%r8 %r9=%r9 ; ; Disassembled: @@ -334,16 +336,16 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32): ; movq 0x18(%rsp), %r11 ; movq %r11, 8(%rsp) ; block1: ; offset 0x1e -; movq %rdx, %r10 -; movq %rcx, %rdx -; movq %r8, %rcx -; movq %r9, %r8 +; movq %r9, %r10 ; movq 0x20(%rbp), %r9 ; movl %edi, 0x10(%rbp) ; movl %edi, 0x18(%rbp) ; movl %esi, 0x20(%rbp) ; movq %rsi, %rdi -; movq %r10, %rsi +; movq %rdx, %rsi +; movq %rcx, %rdx +; movq %r8, %rcx +; movq %r10, %r8 ; movq %rbp, %rsp ; popq %rbp ; jmp 0x46 ; reloc_external CallPCRel4 %call_one_stack_arg -4 @@ -423,16 +425,16 @@ block0: ; movq %r14, 136(%rsp) ; movq %r15, 144(%rsp) ; block0: -; movl $10, %edi -; movq %rdi, rsp(96 + virtual offset) -; movl $15, %esi -; movq %rsi, rsp(88 + virtual offset) -; movl $20, %edx -; movq %rdx, rsp(80 + virtual offset) -; movl $25, %ecx -; movq %rcx, rsp(72 + virtual offset) -; movl $30, %r8d -; movq %r8, rsp(64 + virtual offset) +; movl $10, %esi +; movq %rsi, rsp(96 + virtual offset) +; movl $15, %edx +; movq %rdx, rsp(88 + virtual offset) +; movl $20, %ecx +; movq %rcx, rsp(80 + virtual offset) +; movl $25, %r8d +; movq %r8, rsp(72 + virtual offset) +; movl $30, %r9d +; movq %r9, rsp(64 + virtual offset) ; movl $35, %r9d ; movq %r9, rsp(56 + virtual offset) ; movl $40, %eax @@ -515,16 +517,16 @@ block0: ; movq %r14, 0x88(%rsp) ; movq %r15, 0x90(%rsp) ; block1: ; offset 0x50 -; movl $0xa, %edi -; movq %rdi, 0x60(%rsp) -; movl $0xf, %esi -; movq %rsi, 0x58(%rsp) -; movl $0x14, %edx -; movq %rdx, 0x50(%rsp) -; movl $0x19, %ecx -; movq %rcx, 0x48(%rsp) -; movl $0x1e, %r8d -; movq %r8, 0x40(%rsp) +; movl $0xa, %esi +; movq %rsi, 0x60(%rsp) +; movl $0xf, %edx +; movq %rdx, 0x58(%rsp) +; movl $0x14, %ecx +; movq %rcx, 0x50(%rsp) +; movl $0x19, %r8d +; movq %r8, 0x48(%rsp) +; movl $0x1e, %r9d +; movq %r9, 0x40(%rsp) ; movl $0x23, %r9d ; movq %r9, 0x38(%rsp) ; movl $0x28, %eax diff --git a/cranelift/filetests/filetests/isa/x64/struct-arg.clif b/cranelift/filetests/filetests/isa/x64/struct-arg.clif index d7d5ba7b2498..95b1c4f6bce7 100644 --- a/cranelift/filetests/filetests/isa/x64/struct-arg.clif +++ b/cranelift/filetests/filetests/isa/x64/struct-arg.clif @@ -114,16 +114,16 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; subq %rsp, $80, %rsp -; movq %r13, 64(%rsp) +; movq %r14, 64(%rsp) ; block0: -; movq %rdi, %r13 +; movq %rdi, %r14 ; lea 0(%rsp), %rdi ; movl $64, %edx ; load_ext_name %Memcpy+0, %r10 ; call *%r10 -; movq %r13, %rdi +; movq %r14, %rdi ; call User(userextname0) -; movq 64(%rsp), %r13 +; movq 64(%rsp), %r14 ; addq %rsp, $80, %rsp ; movq %rbp, %rsp ; popq %rbp @@ -134,16 +134,16 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; subq $0x50, %rsp -; movq %r13, 0x40(%rsp) +; movq %r14, 0x40(%rsp) ; block1: ; offset 0xd -; movq %rdi, %r13 +; movq %rdi, %r14 ; leaq (%rsp), %rdi ; movl $0x40, %edx ; movabsq $0, %r10 ; reloc_external Abs8 %Memcpy 0 ; callq *%r10 -; movq %r13, %rdi +; movq %r14, %rdi ; callq 0x2e ; reloc_external CallPCRel4 u0:0 -4 -; movq 0x40(%rsp), %r13 +; movq 0x40(%rsp), %r14 ; addq $0x50, %rsp ; movq %rbp, %rsp ; popq %rbp @@ -196,11 +196,11 @@ block0(v0: i64, v1: i64, v2: i64): ; pushq %rbp ; movq %rsp, %rbp ; subq %rsp, $208, %rsp -; movq %r12, 192(%rsp) -; movq %r14, 200(%rsp) +; movq %rbx, 192(%rsp) +; movq %r13, 200(%rsp) ; block0: -; movq %rdi, %r12 -; movq %rdx, %r14 +; movq %rdx, %rbx +; movq %rdi, %r13 ; lea 0(%rsp), %rdi ; movl $128, %edx ; load_ext_name %Memcpy+0, %r11 @@ -208,12 +208,12 @@ block0(v0: i64, v1: i64, v2: i64): ; lea 128(%rsp), %rdi ; movl $64, %edx ; load_ext_name %Memcpy+0, %r9 -; movq %r14, %rsi +; movq %rbx, %rsi ; call *%r9 -; movq %r12, %rdi +; movq %r13, %rdi ; call User(userextname0) -; movq 192(%rsp), %r12 -; movq 200(%rsp), %r14 +; movq 192(%rsp), %rbx +; movq 200(%rsp), %r13 ; addq %rsp, $208, %rsp ; movq %rbp, %rsp ; popq %rbp @@ -224,11 +224,11 @@ block0(v0: i64, v1: i64, v2: i64): ; pushq %rbp ; movq %rsp, %rbp ; subq $0xd0, %rsp -; movq %r12, 0xc0(%rsp) -; movq %r14, 0xc8(%rsp) +; movq %rbx, 0xc0(%rsp) +; movq %r13, 0xc8(%rsp) ; block1: ; offset 0x1b -; movq %rdi, %r12 -; movq %rdx, %r14 +; movq %rdx, %rbx +; movq %rdi, %r13 ; leaq (%rsp), %rdi ; movl $0x80, %edx ; movabsq $0, %r11 ; reloc_external Abs8 %Memcpy 0 @@ -236,12 +236,12 @@ block0(v0: i64, v1: i64, v2: i64): ; leaq 0x80(%rsp), %rdi ; movl $0x40, %edx ; movabsq $0, %r9 ; reloc_external Abs8 %Memcpy 0 -; movq %r14, %rsi +; movq %rbx, %rsi ; callq *%r9 -; movq %r12, %rdi +; movq %r13, %rdi ; callq 0x5c ; reloc_external CallPCRel4 u0:0 -4 -; movq 0xc0(%rsp), %r12 -; movq 0xc8(%rsp), %r14 +; movq 0xc0(%rsp), %rbx +; movq 0xc8(%rsp), %r13 ; addq $0xd0, %rsp ; movq %rbp, %rsp ; popq %rbp diff --git a/cranelift/filetests/filetests/isa/x64/struct-ret.clif b/cranelift/filetests/filetests/isa/x64/struct-ret.clif index 1947901dd0b7..2664c459c589 100644 --- a/cranelift/filetests/filetests/isa/x64/struct-ret.clif +++ b/cranelift/filetests/filetests/isa/x64/struct-ret.clif @@ -41,8 +41,8 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rsi, %rdi ; load_ext_name %f2+0, %rcx +; movq %rsi, %rdi ; call *%rcx ; movq %rdx, %rax ; movq %rbp, %rsp @@ -54,8 +54,8 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rsi, %rdi ; movabsq $0, %rcx ; reloc_external Abs8 %f2 0 +; movq %rsi, %rdi ; callq *%rcx ; movq %rdx, %rax ; movq %rbp, %rsp diff --git a/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif b/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif index 56a16e31cda2..c919e5ce872d 100644 --- a/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif +++ b/cranelift/filetests/filetests/isa/x64/tail-call-conv.clif @@ -62,8 +62,8 @@ block0: ; movq %r14, 120(%rsp) ; movq %r15, 128(%rsp) ; block0: -; movl $10, %edi -; movq %rdi, rsp(0 + virtual offset) +; movl $10, %esi +; movq %rsi, rsp(0 + virtual offset) ; movl $15, %esi ; movl $20, %edx ; movl $25, %ecx @@ -111,8 +111,8 @@ block0: ; movq %r14, 0x78(%rsp) ; movq %r15, 0x80(%rsp) ; block1: ; offset 0x27 -; movl $0xa, %edi -; movq %rdi, 0x50(%rsp) +; movl $0xa, %esi +; movq %rsi, 0x50(%rsp) ; movl $0xf, %esi ; movl $0x14, %edx ; movl $0x19, %ecx @@ -193,29 +193,29 @@ block0: ; movq %r14, 136(%rsp) ; movq %r15, 144(%rsp) ; block0: -; movl $10, %eax -; movq %rax, rsp(104 + virtual offset) -; movl $15, %ecx -; movq %rcx, rsp(96 + virtual offset) -; movl $20, %edx -; movq %rdx, rsp(88 + virtual offset) -; movl $25, %esi -; movq %rsi, rsp(80 + virtual offset) -; movl $30, %esi -; movq %rsi, rsp(72 + virtual offset) -; movl $35, %r8d -; movq %r8, rsp(64 + virtual offset) -; movl $40, %r9d -; movq %r9, rsp(56 + virtual offset) -; movl $45, %r10d -; movq %r10, rsp(48 + virtual offset) +; movl $10, %ecx +; movq %rcx, rsp(104 + virtual offset) +; movl $15, %edx +; movq %rdx, rsp(96 + virtual offset) +; movl $20, %esi +; movq %rsi, rsp(88 + virtual offset) +; movl $25, %r8d +; movq %r8, rsp(80 + virtual offset) +; movl $30, %eax +; movq %rax, rsp(72 + virtual offset) +; movl $35, %r9d +; movq %r9, rsp(64 + virtual offset) +; movl $40, %r10d +; movq %r10, rsp(56 + virtual offset) +; movl $45, %r11d +; movq %r11, rsp(48 + virtual offset) ; movl $50, %r11d ; movq %r11, rsp(40 + virtual offset) -; movl $55, %r13d -; movl $60, %r14d -; movl $65, %r15d -; movl $70, %ebx -; movl $75, %r12d +; movl $55, %r14d +; movl $60, %r15d +; movl $65, %ebx +; movl $70, %r12d +; movl $75, %r13d ; movl $80, %eax ; movl $85, %ecx ; movl $90, %edx @@ -233,11 +233,11 @@ block0: ; movq %rsi, rsp(8 + virtual offset) ; movl $135, %esi ; movq %rsi, rsp(0 + virtual offset) -; movq %r13, 0(%rdi) -; movq %r14, 8(%rdi) -; movq %r15, 16(%rdi) -; movq %rbx, 24(%rdi) -; movq %r12, 32(%rdi) +; movq %r14, 0(%rdi) +; movq %r15, 8(%rdi) +; movq %rbx, 16(%rdi) +; movq %r12, 24(%rdi) +; movq %r13, 32(%rdi) ; movq %rax, 40(%rdi) ; movq %rcx, 48(%rdi) ; movq %rdx, 56(%rdi) @@ -285,29 +285,29 @@ block0: ; movq %r14, 0x88(%rsp) ; movq %r15, 0x90(%rsp) ; block1: ; offset 0x2d -; movl $0xa, %eax -; movq %rax, 0x68(%rsp) -; movl $0xf, %ecx -; movq %rcx, 0x60(%rsp) -; movl $0x14, %edx -; movq %rdx, 0x58(%rsp) -; movl $0x19, %esi -; movq %rsi, 0x50(%rsp) -; movl $0x1e, %esi -; movq %rsi, 0x48(%rsp) -; movl $0x23, %r8d -; movq %r8, 0x40(%rsp) -; movl $0x28, %r9d -; movq %r9, 0x38(%rsp) -; movl $0x2d, %r10d -; movq %r10, 0x30(%rsp) +; movl $0xa, %ecx +; movq %rcx, 0x68(%rsp) +; movl $0xf, %edx +; movq %rdx, 0x60(%rsp) +; movl $0x14, %esi +; movq %rsi, 0x58(%rsp) +; movl $0x19, %r8d +; movq %r8, 0x50(%rsp) +; movl $0x1e, %eax +; movq %rax, 0x48(%rsp) +; movl $0x23, %r9d +; movq %r9, 0x40(%rsp) +; movl $0x28, %r10d +; movq %r10, 0x38(%rsp) +; movl $0x2d, %r11d +; movq %r11, 0x30(%rsp) ; movl $0x32, %r11d ; movq %r11, 0x28(%rsp) -; movl $0x37, %r13d -; movl $0x3c, %r14d -; movl $0x41, %r15d -; movl $0x46, %ebx -; movl $0x4b, %r12d +; movl $0x37, %r14d +; movl $0x3c, %r15d +; movl $0x41, %ebx +; movl $0x46, %r12d +; movl $0x4b, %r13d ; movl $0x50, %eax ; movl $0x55, %ecx ; movl $0x5a, %edx @@ -325,11 +325,11 @@ block0: ; movq %rsi, 8(%rsp) ; movl $0x87, %esi ; movq %rsi, (%rsp) -; movq %r13, (%rdi) -; movq %r14, 8(%rdi) -; movq %r15, 0x10(%rdi) -; movq %rbx, 0x18(%rdi) -; movq %r12, 0x20(%rdi) +; movq %r14, (%rdi) +; movq %r15, 8(%rdi) +; movq %rbx, 0x10(%rdi) +; movq %r12, 0x18(%rdi) +; movq %r13, 0x20(%rdi) ; movq %rax, 0x28(%rdi) ; movq %rcx, 0x30(%rdi) ; movq %rdx, 0x38(%rdi) @@ -457,10 +457,10 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v ; movq %rcx, rsp(24 + virtual offset) ; movq %r8, rsp(32 + virtual offset) ; movq %r9, rsp(40 + virtual offset) -; movq rbp(stack args max - 176), %r9 -; movq %r9, rsp(48 + virtual offset) -; movq rbp(stack args max - 168), %r10 -; movq %r10, rsp(56 + virtual offset) +; movq rbp(stack args max - 176), %r10 +; movq %r10, rsp(48 + virtual offset) +; movq rbp(stack args max - 168), %r11 +; movq %r11, rsp(56 + virtual offset) ; movq rbp(stack args max - 160), %r11 ; movq %r11, rsp(64 + virtual offset) ; movq rbp(stack args max - 152), %rdx @@ -473,17 +473,17 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v ; movq rbp(stack args max - 112), %r9 ; movq rbp(stack args max - 104), %rsi ; movq %rsi, rsp(88 + virtual offset) -; movq rbp(stack args max - 96), %r13 -; movq rbp(stack args max - 88), %r15 -; movq rbp(stack args max - 80), %r12 -; movq rbp(stack args max - 72), %r14 +; movq rbp(stack args max - 96), %rdi +; movq rbp(stack args max - 88), %rcx +; movq rbp(stack args max - 80), %r8 +; movq rbp(stack args max - 72), %rsi ; movq rbp(stack args max - 64), %rbx -; movq rbp(stack args max - 56), %rdi -; movq %rdi, rsp(96 + virtual offset) -; movq rbp(stack args max - 48), %rcx -; movq rbp(stack args max - 40), %r8 -; movq rbp(stack args max - 32), %rdi -; movq rbp(stack args max - 24), %rsi +; movq rbp(stack args max - 56), %r13 +; movq rbp(stack args max - 48), %r15 +; movq rbp(stack args max - 40), %r12 +; movq rbp(stack args max - 32), %r14 +; movq rbp(stack args max - 24), %rax +; movq %rax, rsp(96 + virtual offset) ; movq rbp(stack args max - 16), %rax ; movq %rdx, 0(%rax) ; movq rsp(72 + virtual offset), %rdx @@ -495,16 +495,16 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v ; movq %r9, 40(%rax) ; movq rsp(88 + virtual offset), %r10 ; movq %r10, 48(%rax) -; movq %r13, 56(%rax) -; movq %r15, 64(%rax) -; movq %r12, 72(%rax) -; movq %r14, 80(%rax) +; movq %rdi, 56(%rax) +; movq %rcx, 64(%rax) +; movq %r8, 72(%rax) +; movq %rsi, 80(%rax) ; movq %rbx, 88(%rax) -; movq rsp(96 + virtual offset), %rdx -; movq %rdx, 96(%rax) -; movq %rcx, 104(%rax) -; movq %r8, 112(%rax) -; movq %rdi, 120(%rax) +; movq %r13, 96(%rax) +; movq %r15, 104(%rax) +; movq %r12, 112(%rax) +; movq %r14, 120(%rax) +; movq rsp(96 + virtual offset), %rsi ; movq %rsi, 128(%rax) ; movq rsp(0 + virtual offset), %rax ; movq rsp(8 + virtual offset), %rcx @@ -542,10 +542,10 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v ; movq %rcx, 0x18(%rsp) ; movq %r8, 0x20(%rsp) ; movq %r9, 0x28(%rsp) -; movq 0x10(%rbp), %r9 -; movq %r9, 0x30(%rsp) -; movq 0x18(%rbp), %r10 -; movq %r10, 0x38(%rsp) +; movq 0x10(%rbp), %r10 +; movq %r10, 0x30(%rsp) +; movq 0x18(%rbp), %r11 +; movq %r11, 0x38(%rsp) ; movq 0x20(%rbp), %r11 ; movq %r11, 0x40(%rsp) ; movq 0x28(%rbp), %rdx @@ -558,17 +558,17 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v ; movq 0x50(%rbp), %r9 ; movq 0x58(%rbp), %rsi ; movq %rsi, 0x58(%rsp) -; movq 0x60(%rbp), %r13 -; movq 0x68(%rbp), %r15 -; movq 0x70(%rbp), %r12 -; movq 0x78(%rbp), %r14 +; movq 0x60(%rbp), %rdi +; movq 0x68(%rbp), %rcx +; movq 0x70(%rbp), %r8 +; movq 0x78(%rbp), %rsi ; movq 0x80(%rbp), %rbx -; movq 0x88(%rbp), %rdi -; movq %rdi, 0x60(%rsp) -; movq 0x90(%rbp), %rcx -; movq 0x98(%rbp), %r8 -; movq 0xa0(%rbp), %rdi -; movq 0xa8(%rbp), %rsi +; movq 0x88(%rbp), %r13 +; movq 0x90(%rbp), %r15 +; movq 0x98(%rbp), %r12 +; movq 0xa0(%rbp), %r14 +; movq 0xa8(%rbp), %rax +; movq %rax, 0x60(%rsp) ; movq 0xb0(%rbp), %rax ; movq %rdx, (%rax) ; movq 0x48(%rsp), %rdx @@ -580,16 +580,16 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v ; movq %r9, 0x28(%rax) ; movq 0x58(%rsp), %r10 ; movq %r10, 0x30(%rax) -; movq %r13, 0x38(%rax) -; movq %r15, 0x40(%rax) -; movq %r12, 0x48(%rax) -; movq %r14, 0x50(%rax) +; movq %rdi, 0x38(%rax) +; movq %rcx, 0x40(%rax) +; movq %r8, 0x48(%rax) +; movq %rsi, 0x50(%rax) ; movq %rbx, 0x58(%rax) -; movq 0x60(%rsp), %rdx -; movq %rdx, 0x60(%rax) -; movq %rcx, 0x68(%rax) -; movq %r8, 0x70(%rax) -; movq %rdi, 0x78(%rax) +; movq %r13, 0x60(%rax) +; movq %r15, 0x68(%rax) +; movq %r12, 0x70(%rax) +; movq %r14, 0x78(%rax) +; movq 0x60(%rsp), %rsi ; movq %rsi, 0x80(%rax) ; movq (%rsp), %rax ; movq 8(%rsp), %rcx @@ -654,16 +654,16 @@ block0: ; movq %r14, 456(%rsp) ; movq %r15, 464(%rsp) ; block0: -; movl $10, %edi -; movq %rdi, rsp(96 + virtual offset) -; movl $15, %esi -; movq %rsi, rsp(88 + virtual offset) -; movl $20, %edx -; movq %rdx, rsp(80 + virtual offset) -; movl $25, %ecx -; movq %rcx, rsp(72 + virtual offset) -; movl $30, %r8d -; movq %r8, rsp(64 + virtual offset) +; movl $10, %esi +; movq %rsi, rsp(96 + virtual offset) +; movl $15, %edx +; movq %rdx, rsp(88 + virtual offset) +; movl $20, %ecx +; movq %rcx, rsp(80 + virtual offset) +; movl $25, %r8d +; movq %r8, rsp(72 + virtual offset) +; movl $30, %r9d +; movq %r9, rsp(64 + virtual offset) ; movl $35, %r9d ; movq %r9, rsp(56 + virtual offset) ; movl $40, %esi @@ -768,16 +768,16 @@ block0: ; movq %r14, 0x1c8(%rsp) ; movq %r15, 0x1d0(%rsp) ; block1: ; offset 0x33 -; movl $0xa, %edi -; movq %rdi, 0x1a0(%rsp) -; movl $0xf, %esi -; movq %rsi, 0x198(%rsp) -; movl $0x14, %edx -; movq %rdx, 0x190(%rsp) -; movl $0x19, %ecx -; movq %rcx, 0x188(%rsp) -; movl $0x1e, %r8d -; movq %r8, 0x180(%rsp) +; movl $0xa, %esi +; movq %rsi, 0x1a0(%rsp) +; movl $0xf, %edx +; movq %rdx, 0x198(%rsp) +; movl $0x14, %ecx +; movq %rcx, 0x190(%rsp) +; movl $0x19, %r8d +; movq %r8, 0x188(%rsp) +; movl $0x1e, %r9d +; movq %r9, 0x180(%rsp) ; movl $0x23, %r9d ; movq %r9, 0x178(%rsp) ; movl $0x28, %esi diff --git a/cranelift/filetests/filetests/isa/x64/udiv.clif b/cranelift/filetests/filetests/isa/x64/udiv.clif index 619cb79916b4..56b70ec88983 100644 --- a/cranelift/filetests/filetests/isa/x64/udiv.clif +++ b/cranelift/filetests/filetests/isa/x64/udiv.clif @@ -38,8 +38,8 @@ block0(v0: i16, v1: i16): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %ax, %dx, %si, %ax, %dx ; trap=int_divz ; movq %rbp, %rsp ; popq %rbp @@ -50,8 +50,8 @@ block0(v0: i16, v1: i16): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divw %si ; trap: int_divz ; movq %rbp, %rsp ; popq %rbp @@ -67,8 +67,8 @@ block0(v0: i32, v1: i32): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %eax, %edx, %esi, %eax, %edx ; trap=int_divz ; movq %rbp, %rsp ; popq %rbp @@ -79,8 +79,8 @@ block0(v0: i32, v1: i32): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divl %esi ; trap: int_divz ; movq %rbp, %rsp ; popq %rbp @@ -96,8 +96,8 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %rax, %rdx, %rsi, %rax, %rdx ; trap=int_divz ; movq %rbp, %rsp ; popq %rbp @@ -108,8 +108,8 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divq %rsi ; trap: int_divz ; movq %rbp, %rsp ; popq %rbp diff --git a/cranelift/filetests/filetests/isa/x64/udivrem.clif b/cranelift/filetests/filetests/isa/x64/udivrem.clif index 1468447aa1da..eb1e5da9ea32 100644 --- a/cranelift/filetests/filetests/isa/x64/udivrem.clif +++ b/cranelift/filetests/filetests/isa/x64/udivrem.clif @@ -16,12 +16,12 @@ block0(v0: i8, v1: i8): ; block0: ; movzbl %dil, %eax ; div %al, %sil, %al ; trap=int_divz -; movq %rax, %r11 +; movq %rax, %rcx ; movzbl %dil, %eax ; div %al, %sil, %al ; trap=int_divz ; movq %rax, %rdx ; shrq $8, %rdx, %rdx -; movq %r11, %rax +; movq %rcx, %rax ; movq %rbp, %rsp ; popq %rbp ; ret @@ -33,12 +33,12 @@ block0(v0: i8, v1: i8): ; block1: ; offset 0x4 ; movzbl %dil, %eax ; divb %sil ; trap: int_divz -; movq %rax, %r11 +; movq %rax, %rcx ; movzbl %dil, %eax ; divb %sil ; trap: int_divz ; movq %rax, %rdx ; shrq $8, %rdx -; movq %r11, %rax +; movq %rcx, %rax ; movq %rbp, %rsp ; popq %rbp ; retq @@ -58,8 +58,8 @@ block0(v0: i16, v1: i16): ; movq %rdi, %rax ; div %ax, %dx, %si, %ax, %dx ; trap=int_divz ; movq %rax, %rcx -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %ax, %dx, %si, %ax, %dx ; trap=int_divz ; movq %rcx, %rax ; movq %rbp, %rsp @@ -75,8 +75,8 @@ block0(v0: i16, v1: i16): ; movq %rdi, %rax ; divw %si ; trap: int_divz ; movq %rax, %rcx -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divw %si ; trap: int_divz ; movq %rcx, %rax ; movq %rbp, %rsp @@ -98,8 +98,8 @@ block0(v0: i32, v1: i32): ; movq %rdi, %rax ; div %eax, %edx, %esi, %eax, %edx ; trap=int_divz ; movq %rax, %rcx -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %eax, %edx, %esi, %eax, %edx ; trap=int_divz ; movq %rcx, %rax ; movq %rbp, %rsp @@ -115,8 +115,8 @@ block0(v0: i32, v1: i32): ; movq %rdi, %rax ; divl %esi ; trap: int_divz ; movq %rax, %rcx -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divl %esi ; trap: int_divz ; movq %rcx, %rax ; movq %rbp, %rsp @@ -138,8 +138,8 @@ block0(v0: i64, v1: i64): ; movq %rdi, %rax ; div %rax, %rdx, %rsi, %rax, %rdx ; trap=int_divz ; movq %rax, %rcx -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %rax, %rdx, %rsi, %rax, %rdx ; trap=int_divz ; movq %rcx, %rax ; movq %rbp, %rsp @@ -155,8 +155,8 @@ block0(v0: i64, v1: i64): ; movq %rdi, %rax ; divq %rsi ; trap: int_divz ; movq %rax, %rcx -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divq %rsi ; trap: int_divz ; movq %rcx, %rax ; movq %rbp, %rsp diff --git a/cranelift/filetests/filetests/isa/x64/urem.clif b/cranelift/filetests/filetests/isa/x64/urem.clif index e886fcc94f25..50a63d9402a5 100644 --- a/cranelift/filetests/filetests/isa/x64/urem.clif +++ b/cranelift/filetests/filetests/isa/x64/urem.clif @@ -40,8 +40,8 @@ block0(v0: i16, v1: i16): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %ax, %dx, %si, %ax, %dx ; trap=int_divz ; movq %rdx, %rax ; movq %rbp, %rsp @@ -53,8 +53,8 @@ block0(v0: i16, v1: i16): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divw %si ; trap: int_divz ; movq %rdx, %rax ; movq %rbp, %rsp @@ -71,8 +71,8 @@ block0(v0: i32, v1: i32): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %eax, %edx, %esi, %eax, %edx ; trap=int_divz ; movq %rdx, %rax ; movq %rbp, %rsp @@ -84,8 +84,8 @@ block0(v0: i32, v1: i32): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divl %esi ; trap: int_divz ; movq %rdx, %rax ; movq %rbp, %rsp @@ -102,8 +102,8 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; xorq %rdx, %rdx, %rdx +; movq %rdi, %rax ; div %rax, %rdx, %rsi, %rax, %rdx ; trap=int_divz ; movq %rdx, %rax ; movq %rbp, %rsp @@ -115,8 +115,8 @@ block0(v0: i64, v1: i64): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; xorq %rdx, %rdx +; movq %rdi, %rax ; divq %rsi ; trap: int_divz ; movq %rdx, %rax ; movq %rbp, %rsp diff --git a/cranelift/filetests/filetests/isa/x64/user_stack_maps.clif b/cranelift/filetests/filetests/isa/x64/user_stack_maps.clif index dc258661bdf4..3ebdc9d5cc9c 100644 --- a/cranelift/filetests/filetests/isa/x64/user_stack_maps.clif +++ b/cranelift/filetests/filetests/isa/x64/user_stack_maps.clif @@ -36,40 +36,37 @@ block0: ; movq %rsp, %rbp ; subq %rsp, $48, %rsp ; movq %rbx, 16(%rsp) -; movq %r13, 24(%rsp) +; movq %r14, 24(%rsp) ; movq %r15, 32(%rsp) ; block0: -; xorl %edi, %edi, %edi -; movq %rdi, %r15 -; movl $1, %edi -; movq %rdi, %rbx -; movl $2, %edi -; movq %rdi, %r13 +; xorl %ebx, %ebx, %ebx +; movl $1, %r14d +; movl $2, %r15d ; lea rsp(0 + virtual offset), %r11 ; movl $0, 0(%r11) ; lea rsp(4 + virtual offset), %rsi ; movl $1, 0(%rsi) ; lea rsp(8 + virtual offset), %rdi ; movl $2, 0(%rdi) -; movq %r15, %rdi +; movq %rbx, %rdi ; call User(userextname0) ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4, 8})], sp_to_sized_stack_slots: None } ; lea rsp(0 + virtual offset), %rcx ; movl $1, 0(%rcx) ; lea rsp(4 + virtual offset), %rdx ; movl $2, 0(%rdx) -; movq %r15, %rdi +; movq %rbx, %rdi ; call User(userextname0) ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0, 4})], sp_to_sized_stack_slots: None } ; lea rsp(0 + virtual offset), %r9 ; movl $2, 0(%r9) -; movq %rbx, %rdi +; movq %r14, %rdi ; call User(userextname0) ; ; UserStackMap { by_type: [(types::I32, CompoundBitSet {0})], sp_to_sized_stack_slots: None } -; movq %r13, %rdi +; movq %r15, %rdi ; call User(userextname0) ; movq 16(%rsp), %rbx -; movq 24(%rsp), %r13 +; movq 24(%rsp), %r14 ; movq 32(%rsp), %r15 ; addq %rsp, $48, %rsp ; movq %rbp, %rsp @@ -82,37 +79,34 @@ block0: ; movq %rsp, %rbp ; subq $0x30, %rsp ; movq %rbx, 0x10(%rsp) -; movq %r13, 0x18(%rsp) +; movq %r14, 0x18(%rsp) ; movq %r15, 0x20(%rsp) ; block1: ; offset 0x17 -; xorl %edi, %edi -; movq %rdi, %r15 -; movl $1, %edi -; movq %rdi, %rbx -; movl $2, %edi -; movq %rdi, %r13 +; xorl %ebx, %ebx +; movl $1, %r14d +; movl $2, %r15d ; leaq (%rsp), %r11 ; movl $0, (%r11) ; leaq 4(%rsp), %rsi ; movl $1, (%rsi) ; leaq 8(%rsp), %rdi ; movl $2, (%rdi) -; movq %r15, %rdi -; callq 0x55 ; reloc_external CallPCRel4 u0:0 -4 +; movq %rbx, %rdi +; callq 0x4e ; reloc_external CallPCRel4 u0:0 -4 ; leaq (%rsp), %rcx ; movl $1, (%rcx) ; leaq 4(%rsp), %rdx ; movl $2, (%rdx) -; movq %r15, %rdi -; callq 0x72 ; reloc_external CallPCRel4 u0:0 -4 +; movq %rbx, %rdi +; callq 0x6b ; reloc_external CallPCRel4 u0:0 -4 ; leaq (%rsp), %r9 ; movl $2, (%r9) -; movq %rbx, %rdi -; callq 0x85 ; reloc_external CallPCRel4 u0:0 -4 -; movq %r13, %rdi -; callq 0x8d ; reloc_external CallPCRel4 u0:0 -4 +; movq %r14, %rdi +; callq 0x7e ; reloc_external CallPCRel4 u0:0 -4 +; movq %r15, %rdi +; callq 0x86 ; reloc_external CallPCRel4 u0:0 -4 ; movq 0x10(%rsp), %rbx -; movq 0x18(%rsp), %r13 +; movq 0x18(%rsp), %r14 ; movq 0x20(%rsp), %r15 ; addq $0x30, %rsp ; movq %rbp, %rsp @@ -152,31 +146,31 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; movq %r8, %r13 ; lea rsp(0 + virtual offset), %r8 ; movb %dil, 0(%r8) -; movq %rdi, %rbx +; movq %rdi, %r15 ; lea rsp(8 + virtual offset), %r8 ; movw %si, 0(%r8) -; movq %rsi, %r14 +; movq %rsi, %r12 ; lea rsp(16 + virtual offset), %r9 ; movl %edx, 0(%r9) -; movq %rdx, %r12 +; movq %rdx, %rbx ; lea rsp(20 + virtual offset), %r10 ; movss %xmm0, 0(%r10) ; movdqu %xmm0, rsp(96 + virtual offset) ; lea rsp(24 + virtual offset), %r11 ; movq %rcx, 0(%r11) -; movq %rcx, %r15 +; movq %rcx, %r14 ; lea rsp(32 + virtual offset), %rsi ; movsd %xmm1, 0(%rsi) ; movdqu %xmm1, rsp(112 + virtual offset) ; call User(userextname0) ; ; UserStackMap { by_type: [(types::I8, CompoundBitSet {0}), (types::I16, CompoundBitSet {8}), (types::I32, CompoundBitSet {16}), (types::F32, CompoundBitSet {20}), (types::I64, CompoundBitSet {24}), (types::F64, CompoundBitSet {32})], sp_to_sized_stack_slots: None } -; movq %r12, %rdx +; movq %rbx, %rdx ; movq %r13, %r8 ; movl %edx, 0(%r8) -; movq %r15, %rcx +; movq %r14, %rcx ; movq %rcx, 8(%r8) -; movq %rbx, %rax -; movq %r14, %rdx +; movq %r15, %rax +; movq %r12, %rdx ; movdqu rsp(96 + virtual offset), %xmm0 ; movdqu rsp(112 + virtual offset), %xmm1 ; movq 128(%rsp), %rbx @@ -203,30 +197,30 @@ block0(v0: i8, v1: i16, v2: i32, v3: i64, v4: f32, v5: f64): ; movq %r8, %r13 ; leaq (%rsp), %r8 ; movb %dil, (%r8) -; movq %rdi, %rbx +; movq %rdi, %r15 ; leaq 8(%rsp), %r8 ; movw %si, (%r8) -; movq %rsi, %r14 +; movq %rsi, %r12 ; leaq 0x10(%rsp), %r9 ; movl %edx, (%r9) -; movq %rdx, %r12 +; movq %rdx, %rbx ; leaq 0x14(%rsp), %r10 ; movss %xmm0, (%r10) ; movdqu %xmm0, 0x60(%rsp) ; leaq 0x18(%rsp), %r11 ; movq %rcx, (%r11) -; movq %rcx, %r15 +; movq %rcx, %r14 ; leaq 0x20(%rsp), %rsi ; movsd %xmm1, (%rsi) ; movdqu %xmm1, 0x70(%rsp) ; callq 0x86 ; reloc_external CallPCRel4 u0:0 -4 -; movq %r12, %rdx +; movq %rbx, %rdx ; movq %r13, %r8 ; movl %edx, (%r8) -; movq %r15, %rcx +; movq %r14, %rcx ; movq %rcx, 8(%r8) -; movq %rbx, %rax -; movq %r14, %rdx +; movq %r15, %rax +; movq %r12, %rdx ; movdqu 0x60(%rsp), %xmm0 ; movdqu 0x70(%rsp), %xmm1 ; movq 0x80(%rsp), %rbx diff --git a/cranelift/filetests/filetests/isa/x64/winch.clif b/cranelift/filetests/filetests/isa/x64/winch.clif index 9a9fce756b45..56d042e9cde4 100644 --- a/cranelift/filetests/filetests/isa/x64/winch.clif +++ b/cranelift/filetests/filetests/isa/x64/winch.clif @@ -132,10 +132,10 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64): ; pushq %rbp ; movq %rsp, %rbp ; block0: +; load_ext_name %g+0, %r10 ; movq %rdi, %rax ; movq %r9, %rdi ; movq %rax, %r9 -; load_ext_name %g+0, %r10 ; call *%r10 ; movq %rbp, %rsp ; popq %rbp @@ -146,10 +146,10 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 +; movabsq $0, %r10 ; reloc_external Abs8 %g 0 ; movq %rdi, %rax ; movq %r9, %rdi ; movq %rax, %r9 -; movabsq $0, %r10 ; reloc_external Abs8 %g 0 ; callq *%r10 ; movq %rbp, %rsp ; popq %rbp @@ -174,10 +174,10 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64): ; movq %r14, 24(%rsp) ; movq %r15, 32(%rsp) ; block0: +; load_ext_name %g+0, %r10 ; movq %rdi, %rax ; movq %r9, %rdi ; movq %rax, %r9 -; load_ext_name %g+0, %r10 ; call *%r10 ; movq 0(%rsp), %rbx ; movq 8(%rsp), %r12 @@ -200,10 +200,10 @@ block0(v0:i64, v1:i64, v2:i64, v3:i64, v4:i64, v5:i64): ; movq %r14, 0x18(%rsp) ; movq %r15, 0x20(%rsp) ; block1: ; offset 0x20 +; movabsq $0, %r10 ; reloc_external Abs8 %g 0 ; movq %rdi, %rax ; movq %r9, %rdi ; movq %rax, %r9 -; movabsq $0, %r10 ; reloc_external Abs8 %g 0 ; callq *%r10 ; movq (%rsp), %rbx ; movq 8(%rsp), %r12 @@ -349,10 +349,10 @@ block0(v0: i32, v1: i64, v2: i32, v3: i64): ; pushq %rbp ; movq %rsp, %rbp ; block0: -; movq %rdi, %rax ; movq %rcx, 12(%r8) ; movl %edx, 8(%r8) ; movq %rsi, 0(%r8) +; movq %rdi, %rax ; movq %rbp, %rsp ; popq %rbp ; ret @@ -362,10 +362,10 @@ block0(v0: i32, v1: i64, v2: i32, v3: i64): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; movq %rdi, %rax ; movq %rcx, 0xc(%r8) ; movl %edx, 8(%r8) ; movq %rsi, (%r8) +; movq %rdi, %rax ; movq %rbp, %rsp ; popq %rbp ; retq diff --git a/cranelift/filetests/filetests/parser/ternary.clif b/cranelift/filetests/filetests/parser/ternary.clif index b521aecc8cc9..2406fb293951 100644 --- a/cranelift/filetests/filetests/parser/ternary.clif +++ b/cranelift/filetests/filetests/parser/ternary.clif @@ -12,10 +12,10 @@ function %add_i96(i32, i32, i32, i32, i32, i32) -> i32, i32, i32 { block1(v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32): v10, v11 = uadd_overflow v1, v4 ;check: v10, v11 = uadd_overflow v1, v4 - v20, v21 = iadd_carry v2, v5, v11 - ; check: v20, v21 = iadd_carry v2, v5, v11 - v30 = iadd_cin v3, v6, v21 - ; check: v30 = iadd_cin v3, v6, v21 + v20, v21 = sadd_overflow_cin v2, v5, v11 + ; check: v20, v21 = sadd_overflow_cin v2, v5, v11 + v30, v31 = uadd_overflow_cin v3, v6, v21 + ; check: v30, v31 = uadd_overflow_cin v3, v6, v21 return v10, v20, v30 } @@ -23,9 +23,9 @@ function %sub_i96(i32, i32, i32, i32, i32, i32) -> i32, i32, i32 { block1(v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32): v10, v11 = usub_overflow v1, v4 ;check: v10, v11 = usub_overflow v1, v4 - v20, v21 = isub_borrow v2, v5, v11 - ; check: v20, v21 = isub_borrow v2, v5, v11 - v30 = isub_bin v3, v6, v21 - ; check: v30 = isub_bin v3, v6, v21 + v20, v21 = ssub_overflow_bin v2, v5, v11 + ; check: v20, v21 = ssub_overflow_bin v2, v5, v11 + v30, v31 = usub_overflow_bin v3, v6, v21 + ; check: v30, v31 = usub_overflow_bin v3, v6, v21 return v10, v20, v30 } diff --git a/cranelift/filetests/filetests/runtests/i128-arithmetic.clif b/cranelift/filetests/filetests/runtests/i128-arithmetic.clif index e0f0a246faa9..5a2703deccac 100644 --- a/cranelift/filetests/filetests/runtests/i128-arithmetic.clif +++ b/cranelift/filetests/filetests/runtests/i128-arithmetic.clif @@ -4,6 +4,7 @@ set enable_llvm_abi_extensions=true target aarch64 target s390x target x86_64 +target x86_64 has_bmi2 target riscv64 target riscv64 has_c has_zcb diff --git a/cranelift/filetests/filetests/runtests/iaddcarry.clif b/cranelift/filetests/filetests/runtests/iaddcarry.clif index 04fd38f124ba..512d13db8689 100644 --- a/cranelift/filetests/filetests/runtests/iaddcarry.clif +++ b/cranelift/filetests/filetests/runtests/iaddcarry.clif @@ -1,99 +1,115 @@ test interpret -function %iaddcarry_i8_v(i8, i8, i8) -> i8 { +function %sadd_overflow_cin_i8(i8, i8, i8) -> i8, i8 { block0(v0: i8, v1: i8, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v3 + v3, v4 = sadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i8_v(0, 1, 1) == 2 -; run: %iaddcarry_i8_v(0, 1, 0) == 1 -; run: %iaddcarry_i8_v(100, 27, 1) == -128 -; run: %iaddcarry_i8_v(100, 27, 0) == 127 -; run: %iaddcarry_i8_v(127, 127, 1) == -1 -; run: %iaddcarry_i8_v(127, 127, 0) == -2 -; run: %iaddcarry_i8_v(-128, -128, 0) == 0 +; run: %sadd_overflow_cin_i8(0, 1, 1) == [2, 0] +; run: %sadd_overflow_cin_i8(0, 1, 10) == [2, 0] +; run: %sadd_overflow_cin_i8(0, 1, 0) == [1, 0] +; run: %sadd_overflow_cin_i8(100, 27, 1) == [-128, 1] +; run: %sadd_overflow_cin_i8(100, 27, 0) == [127, 0] +; run: %sadd_overflow_cin_i8(127, 127, 1) == [-1, 1] +; run: %sadd_overflow_cin_i8(127, 127, 0) == [-2, 1] +; run: %sadd_overflow_cin_i8(-128, -128, 0) == [0, 1] -function %iaddcarry_i8_c(i8, i8, i8) -> i8 { -block0(v0: i8, v1: i8, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v4 +function %sadd_overflow_cin_i16(i16, i16, i8) -> i16, i8 { +block0(v0: i16, v1: i16, v2: i8): + v3, v4 = sadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i8_c(0, 1, 1) == 0 -; run: %iaddcarry_i8_c(0, 1, 0) == 0 -; run: %iaddcarry_i8_c(100, 27, 1) == 1 -; run: %iaddcarry_i8_c(100, 27, 0) == 0 -; run: %iaddcarry_i8_c(127, 127, 1) == 1 -; run: %iaddcarry_i8_c(127, 127, 0) == 1 -; run: %iaddcarry_i8_c(-128, -128, 0) == 1 +; run: %sadd_overflow_cin_i16(0, 1, 1) == [2, 0] +; run: %sadd_overflow_cin_i16(0, 1, 10) == [2, 0] +; run: %sadd_overflow_cin_i16(0, 1, 0) == [1, 0] +; run: %sadd_overflow_cin_i16(100, 27, 1) == [128, 0] +; run: %sadd_overflow_cin_i16(100, 27, 0) == [127, 0] +; run: %sadd_overflow_cin_i16(32000, 767, 1) == [-32768, 1] +; run: %sadd_overflow_cin_i16(32000, 767, 0) == [32767, 0] -function %iaddcarry_i16_v(i16, i16, i8) -> i16 { -block0(v0: i16, v1: i16, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v3 +function %sadd_overflow_cin_i32(i32, i32, i8) -> i32, i8 { +block0(v0: i32, v1: i32, v2: i8): + v3, v4 = sadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i16_v(0, 1, 1) == 2 -; run: %iaddcarry_i16_v(0, 1, 0) == 1 -; run: %iaddcarry_i16_v(100, 27, 1) == 128 -; run: %iaddcarry_i16_v(100, 27, 0) == 127 -; run: %iaddcarry_i16_v(32000, 767, 1) == -32768 -; run: %iaddcarry_i16_v(32000, 767, 0) == 32767 +; run: %sadd_overflow_cin_i32(0, 1, 1) == [2, 0] +; run: %sadd_overflow_cin_i32(0, 1, 10) == [2, 0] +; run: %sadd_overflow_cin_i32(0, 1, 0) == [1, 0] +; run: %sadd_overflow_cin_i32(100, 27, 1) == [128, 0] +; run: %sadd_overflow_cin_i32(100, 27, 0) == [127, 0] +; run: %sadd_overflow_cin_i32(2000000000, 147483647, 1) == [-2147483648, 1] +; run: %sadd_overflow_cin_i32(2000000000, 147483647, 0) == [2147483647, 0] -function %iaddcarry_i16_c(i16, i16, i8) -> i8 { -block0(v0: i16, v1: i16, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v4 +function %sadd_overflow_cin_i64(i64, i64, i8) -> i64, i8 { +block0(v0: i64, v1: i64, v2: i8): + v3, v4 = sadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i16_c(0, 1, 1) == 0 -; run: %iaddcarry_i16_c(0, 1, 0) == 0 -; run: %iaddcarry_i16_c(100, 27, 1) == 0 -; run: %iaddcarry_i16_c(100, 27, 0) == 0 -; run: %iaddcarry_i16_c(32000, 767, 1) == 1 -; run: %iaddcarry_i16_c(32000, 767, 0) == 0 +; run: %sadd_overflow_cin_i64(0, 1, 1) == [2, 0] +; run: %sadd_overflow_cin_i64(0, 1, 10) == [2, 0] +; run: %sadd_overflow_cin_i64(0, 1, 0) == [1, 0] +; run: %sadd_overflow_cin_i64(100, 27, 1) == [128, 0] +; run: %sadd_overflow_cin_i64(100, 27, 0) == [127, 0] +; run: %sadd_overflow_cin_i64(9000000000000000000, 223372036854775807, 1) == [-9223372036854775808, 1] +; run: %sadd_overflow_cin_i64(9000000000000000000, 223372036854775807, 0) == [9223372036854775807, 0] -function %iaddcarry_i32_v(i32, i32, i8) -> i32 { -block0(v0: i32, v1: i32, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v3 +function %uadd_overflow_cin_i8(i8, i8, i8) -> i8, i8 { +block0(v0: i8, v1: i8, v2: i8): + v3, v4 = uadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i32_v(0, 1, 1) == 2 -; run: %iaddcarry_i32_v(0, 1, 0) == 1 -; run: %iaddcarry_i32_v(100, 27, 1) == 128 -; run: %iaddcarry_i32_v(100, 27, 0) == 127 -; run: %iaddcarry_i32_v(2000000000, 147483647, 1) == -2147483648 -; run: %iaddcarry_i32_v(2000000000, 147483647, 0) == 2147483647 +; run: %uadd_overflow_cin_i8(0, 1, 1) == [2, 0] +; run: %uadd_overflow_cin_i8(0, 1, 10) == [2, 0] +; run: %uadd_overflow_cin_i8(0, 1, 0) == [1, 0] +; run: %uadd_overflow_cin_i8(100, 27, 1) == [-128, 0] +; run: %uadd_overflow_cin_i8(100, 27, 0) == [127, 0] +; run: %uadd_overflow_cin_i8(127, 127, 1) == [-1, 0] +; run: %uadd_overflow_cin_i8(127, 127, 0) == [-2, 0] +; run: %uadd_overflow_cin_i8(-128, -128, 0) == [0, 1] +; run: %uadd_overflow_cin_i8(-1, -1, 0) == [-2, 1] +; run: %uadd_overflow_cin_i8(-1, -1, 1) == [-1, 1] -function %iaddcarry_i32_c(i32, i32, i8) -> i8 { -block0(v0: i32, v1: i32, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v4 +function %uadd_overflow_cin_i16(i16, i16, i8) -> i16, i8 { +block0(v0: i16, v1: i16, v2: i8): + v3, v4 = uadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i32_c(0, 1, 1) == 0 -; run: %iaddcarry_i32_c(0, 1, 0) == 0 -; run: %iaddcarry_i32_c(100, 27, 1) == 0 -; run: %iaddcarry_i32_c(100, 27, 0) == 0 -; run: %iaddcarry_i32_c(2000000000, 147483647, 1) == 1 -; run: %iaddcarry_i32_c(2000000000, 147483647, 0) == 0 +; run: %uadd_overflow_cin_i16(0, 1, 1) == [2, 0] +; run: %uadd_overflow_cin_i16(0, 1, 10) == [2, 0] +; run: %uadd_overflow_cin_i16(0, 1, 0) == [1, 0] +; run: %uadd_overflow_cin_i16(100, 27, 1) == [128, 0] +; run: %uadd_overflow_cin_i16(100, 27, 0) == [127, 0] +; run: %uadd_overflow_cin_i16(32000, 767, 1) == [-32768, 0] +; run: %uadd_overflow_cin_i16(32000, 767, 0) == [32767, 0] +; run: %uadd_overflow_cin_i16(-1, -1, 0) == [-2, 1] +; run: %uadd_overflow_cin_i16(-1, -1, 1) == [-1, 1] -function %iaddcarry_i64_v(i64, i64, i8) -> i64 { -block0(v0: i64, v1: i64, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v3 +function %uadd_overflow_cin_i32(i32, i32, i8) -> i32, i8 { +block0(v0: i32, v1: i32, v2: i8): + v3, v4 = uadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i64_v(0, 1, 1) == 2 -; run: %iaddcarry_i64_v(0, 1, 0) == 1 -; run: %iaddcarry_i64_v(100, 27, 1) == 128 -; run: %iaddcarry_i64_v(100, 27, 0) == 127 -; run: %iaddcarry_i64_v(9000000000000000000, 223372036854775807, 1) == -9223372036854775808 -; run: %iaddcarry_i64_v(9000000000000000000, 223372036854775807, 0) == 9223372036854775807 +; run: %uadd_overflow_cin_i32(0, 1, 1) == [2, 0] +; run: %uadd_overflow_cin_i32(0, 1, 10) == [2, 0] +; run: %uadd_overflow_cin_i32(0, 1, 0) == [1, 0] +; run: %uadd_overflow_cin_i32(100, 27, 1) == [128, 0] +; run: %uadd_overflow_cin_i32(100, 27, 0) == [127, 0] +; run: %uadd_overflow_cin_i32(2000000000, 147483647, 1) == [-2147483648, 0] +; run: %uadd_overflow_cin_i32(2000000000, 147483647, 0) == [2147483647, 0] +; run: %uadd_overflow_cin_i32(-1, -1, 0) == [-2, 1] +; run: %uadd_overflow_cin_i32(-1, -1, 1) == [-1, 1] -function %iaddcarry_i64_c(i64, i64, i8) -> i8 { +function %uadd_overflow_cin_i64(i64, i64, i8) -> i64, i8 { block0(v0: i64, v1: i64, v2: i8): - v3, v4 = iadd_carry v0, v1, v2 - return v4 + v3, v4 = uadd_overflow_cin v0, v1, v2 + return v3, v4 } -; run: %iaddcarry_i64_c(0, 1, 1) == 0 -; run: %iaddcarry_i64_c(0, 1, 0) == 0 -; run: %iaddcarry_i64_c(100, 27, 1) == 0 -; run: %iaddcarry_i64_c(100, 27, 0) == 0 -; run: %iaddcarry_i64_c(9000000000000000000, 223372036854775807, 1) == 1 -; run: %iaddcarry_i64_c(9000000000000000000, 223372036854775807, 0) == 0 +; run: %uadd_overflow_cin_i64(0, 1, 1) == [2, 0] +; run: %uadd_overflow_cin_i64(0, 1, 10) == [2, 0] +; run: %uadd_overflow_cin_i64(0, 1, 0) == [1, 0] +; run: %uadd_overflow_cin_i64(100, 27, 1) == [128, 0] +; run: %uadd_overflow_cin_i64(100, 27, 0) == [127, 0] +; run: %uadd_overflow_cin_i64(9000000000000000000, 223372036854775807, 1) == [-9223372036854775808, 0] +; run: %uadd_overflow_cin_i64(9000000000000000000, 223372036854775807, 0) == [9223372036854775807, 0] +; run: %uadd_overflow_cin_i64(-1, -1, 0) == [-2, 1] +; run: %uadd_overflow_cin_i64(-1, -1, 1) == [-1, 1] diff --git a/cranelift/filetests/filetests/runtests/iaddcin.clif b/cranelift/filetests/filetests/runtests/iaddcin.clif deleted file mode 100644 index 5b185af2a88f..000000000000 --- a/cranelift/filetests/filetests/runtests/iaddcin.clif +++ /dev/null @@ -1,48 +0,0 @@ -test interpret - -function %iaddcin_i8(i8, i8, i8) -> i8 { -block0(v0: i8, v1: i8, v2: i8): - v3 = iadd_cin v0, v1, v2 - return v3 -} -; run: %iaddcin_i8(0, 1, 1) == 2 -; run: %iaddcin_i8(0, 1, 0) == 1 -; run: %iaddcin_i8(100, 27, 1) == -128 -; run: %iaddcin_i8(100, 27, 0) == 127 - -function %iaddcin_i16(i16, i16, i8) -> i16 { -block0(v0: i16, v1: i16, v2: i8): - v3 = iadd_cin v0, v1, v2 - return v3 -} -; run: %iaddcin_i16(0, 1, 1) == 2 -; run: %iaddcin_i16(0, 1, 0) == 1 -; run: %iaddcin_i16(100, 27, 1) == 128 -; run: %iaddcin_i16(100, 27, 0) == 127 -; run: %iaddcin_i16(32000, 767, 1) == -32768 -; run: %iaddcin_i16(32000, 767, 0) == 32767 - -function %iaddcin_i32(i32, i32, i8) -> i32 { -block0(v0: i32, v1: i32, v2: i8): - v3 = iadd_cin v0, v1, v2 - return v3 -} -; run: %iaddcin_i32(0, 1, 1) == 2 -; run: %iaddcin_i32(0, 1, 0) == 1 -; run: %iaddcin_i32(100, 27, 1) == 128 -; run: %iaddcin_i32(100, 27, 0) == 127 -; run: %iaddcin_i32(2000000000, 147483647, 1) == -2147483648 -; run: %iaddcin_i32(2000000000, 147483647, 0) == 2147483647 - - -function %iaddcin_i64(i64, i64, i8) -> i64 { -block0(v0: i64, v1: i64, v2: i8): - v3 = iadd_cin v0, v1, v2 - return v3 -} -; run: %iaddcin_i64(0, 1, 1) == 2 -; run: %iaddcin_i64(0, 1, 0) == 1 -; run: %iaddcin_i64(100, 27, 1) == 128 -; run: %iaddcin_i64(100, 27, 0) == 127 -; run: %iaddcin_i64(2000000000, 147483647, 1) == 2147483648 -; run: %iaddcin_i64(2000000000, 147483647, 0) == 2147483647 diff --git a/cranelift/filetests/filetests/runtests/isubbin.clif b/cranelift/filetests/filetests/runtests/isubbin.clif deleted file mode 100644 index 53ebcf116a92..000000000000 --- a/cranelift/filetests/filetests/runtests/isubbin.clif +++ /dev/null @@ -1,49 +0,0 @@ -test interpret - -function %isubbin_i8(i8, i8, i8) -> i8 { -block0(v0: i8, v1: i8, v2: i8): - v3 = isub_bin v0, v1, v2 - return v3 -} -; run: %isubbin_i8(0, 1, 1) == -2 -; run: %isubbin_i8(0, 1, 0) == -1 -; run: %isubbin_i8(100, 20, 1) == 79 -; run: %isubbin_i8(100, 20, 0) == 80 -; run: %isubbin_i8(-128, 1, 1) == 126 -; run: %isubbin_i8(-128, 1, 0) == 127 - -function %isubbin_i16(i16, i16, i8) -> i16 { -block0(v0: i16, v1: i16, v2: i8): - v3 = isub_bin v0, v1, v2 - return v3 -} -; run: %isubbin_i16(0, 1, 1) == -2 -; run: %isubbin_i16(0, 1, 0) == -1 -; run: %isubbin_i16(100, 20, 1) == 79 -; run: %isubbin_i16(100, 20, 0) == 80 -; run: %isubbin_i16(-32768, 1, 1) == 32766 -; run: %isubbin_i16(-32768, 1, 0) == 32767 - -function %isubbin_i32(i32, i32, i8) -> i32 { -block0(v0: i32, v1: i32, v2: i8): - v3 = isub_bin v0, v1, v2 - return v3 -} -; run: %isubbin_i32(0, 1, 1) == -2 -; run: %isubbin_i32(0, 1, 0) == -1 -; run: %isubbin_i32(100, 20, 1) == 79 -; run: %isubbin_i32(100, 20, 0) == 80 -; run: %isubbin_i32(-2147483648, 1, 1) == 2147483646 -; run: %isubbin_i32(-2147483648, 1, 0) == 2147483647 - -function %isubbin_i64(i64, i64, i8) -> i64 { -block0(v0: i64, v1: i64, v2: i8): - v3 = isub_bin v0, v1, v2 - return v3 -} -; run: %isubbin_i64(0, 1, 1) == -2 -; run: %isubbin_i64(0, 1, 0) == -1 -; run: %isubbin_i64(100, 20, 1) == 79 -; run: %isubbin_i64(100, 20, 0) == 80 -; run: %isubbin_i64(-2147483648, 1, 1) == -2147483650 -; run: %isubbin_i64(-2147483648, 1, 0) == -2147483649 diff --git a/cranelift/filetests/filetests/runtests/isubborrow.clif b/cranelift/filetests/filetests/runtests/isubborrow.clif index 90dd04c53bcc..4dcbf4190cae 100644 --- a/cranelift/filetests/filetests/runtests/isubborrow.clif +++ b/cranelift/filetests/filetests/runtests/isubborrow.clif @@ -1,98 +1,111 @@ test interpret -function %isubborrow_i8_v(i8, i8, i8) -> i8 { +function %ssub_overflow_bin_i8(i8, i8, i8) -> i8, i8 { block0(v0: i8, v1: i8, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v3 + v3, v4 = ssub_overflow_bin v0, v1, v2 + return v3, v4 } -; run: %isubborrow_i8_v(0, 1, 1) == -2 -; run: %isubborrow_i8_v(0, 1, 0) == -1 -; run: %isubborrow_i8_v(100, 20, 1) == 79 -; run: %isubborrow_i8_v(100, 20, 0) == 80 -; run: %isubborrow_i8_v(127, 127, 1) == -1 -; run: %isubborrow_i8_v(127, 127, 0) == 0 +; run: %ssub_overflow_bin_i8(0, 1, 1) == [-2, 0] +; run: %ssub_overflow_bin_i8(0, 1, 10) == [-2, 0] +; run: %ssub_overflow_bin_i8(0, 1, 0) == [-1, 0] +; run: %ssub_overflow_bin_i8(100, 20, 1) == [79, 0] +; run: %ssub_overflow_bin_i8(100, 20, 0) == [80, 0] +; run: %ssub_overflow_bin_i8(127, 127, 1) == [-1, 0] +; run: %ssub_overflow_bin_i8(127, 127, 0) == [0, 0] +; run: %ssub_overflow_bin_i8(-120, 8, 0) == [-128, 0] +; run: %ssub_overflow_bin_i8(-120, 8, 1) == [127, 1] +; run: %ssub_overflow_bin_i8(-120, 8, 10) == [127, 1] -function %isubborrow_i8_c(i8, i8, i8) -> i8 { -block0(v0: i8, v1: i8, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v4 -} -; run: %isubborrow_i8_c(0, 1, 1) == 1 -; run: %isubborrow_i8_c(0, 1, 0) == 1 -; run: %isubborrow_i8_c(100, 20, 1) == 0 -; run: %isubborrow_i8_c(100, 20, 0) == 0 -; run: %isubborrow_i8_c(127, 127, 1) == 0 -; run: %isubborrow_i8_c(127, 127, 0) == 0 - -function %isubborrow_i16_v(i16, i16, i8) -> i16 { +function %ssub_overflow_bin_i16(i16, i16, i8) -> i16, i8 { block0(v0: i16, v1: i16, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v3 + v3, v4 = ssub_overflow_bin v0, v1, v2 + return v3, v4 } -; run: %isubborrow_i16_v(0, 1, 1) == -2 -; run: %isubborrow_i16_v(0, 1, 0) == -1 -; run: %isubborrow_i16_v(100, 20, 1) == 79 -; run: %isubborrow_i16_v(100, 20, 0) == 80 -; run: %isubborrow_i16_v(-32000, 768, 1) == 32767 -; run: %isubborrow_i16_v(-32000, 768, 0) == -32768 +; run: %ssub_overflow_bin_i16(0, 1, 1) == [-2, 0] +; run: %ssub_overflow_bin_i16(0, 1, 10) == [-2, 0] +; run: %ssub_overflow_bin_i16(0, 1, 0) == [-1, 0] +; run: %ssub_overflow_bin_i16(100, 20, 1) == [79, 0] +; run: %ssub_overflow_bin_i16(100, 20, 0) == [80, 0] +; run: %ssub_overflow_bin_i16(-32000, 768, 1) == [32767, 1] +; run: %ssub_overflow_bin_i16(-32000, 768, 0) == [-32768, 0] -function %isubborrow_i16_c(i16, i16, i8) -> i8 { -block0(v0: i16, v1: i16, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v4 +function %ssub_overflow_bin_i32(i32, i32, i8) -> i32, i8 { +block0(v0: i32, v1: i32, v2: i8): + v3, v4 = ssub_overflow_bin v0, v1, v2 + return v3, v4 } -; run: %isubborrow_i16_c(0, 1, 1) == 1 -; run: %isubborrow_i16_c(0, 1, 0) == 1 -; run: %isubborrow_i16_c(100, 20, 1) == 0 -; run: %isubborrow_i16_c(100, 20, 0) == 0 -; run: %isubborrow_i16_c(-32000, 768, 1) == 1 -; run: %isubborrow_i16_c(-32000, 768, 0) == 1 +; run: %ssub_overflow_bin_i32(0, 1, 1) == [-2, 0] +; run: %ssub_overflow_bin_i32(0, 1, 10) == [-2, 0] +; run: %ssub_overflow_bin_i32(0, 1, 0) == [-1, 0] +; run: %ssub_overflow_bin_i32(100, 20, 1) == [79, 0] +; run: %ssub_overflow_bin_i32(100, 20, 0) == [80, 0] +; run: %ssub_overflow_bin_i32(-2147483640, 8, 1) == [2147483647, 1] +; run: %ssub_overflow_bin_i32(-2147483640, 8, 0) == [-2147483648, 0] -function %isubborrow_i32_v(i32, i32, i8) -> i32 { -block0(v0: i32, v1: i32, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v3 +function %ssub_overflow_bin_i64(i64, i64, i8) -> i64, i8 { +block0(v0: i64, v1: i64, v2: i8): + v3, v4 = ssub_overflow_bin v0, v1, v2 + return v3, v4 } -; run: %isubborrow_i32_v(0, 1, 1) == -2 -; run: %isubborrow_i32_v(0, 1, 0) == -1 -; run: %isubborrow_i32_v(100, 20, 1) == 79 -; run: %isubborrow_i32_v(100, 20, 0) == 80 -; run: %isubborrow_i32_v(-2147483640, 8, 1) == 2147483647 -; run: %isubborrow_i32_v(-2147483640, 8, 0) == -2147483648 +; run: %ssub_overflow_bin_i64(0, 1, 1) == [-2, 0] +; run: %ssub_overflow_bin_i64(0, 1, 10) == [-2, 0] +; run: %ssub_overflow_bin_i64(0, 1, 0) == [-1, 0] +; run: %ssub_overflow_bin_i64(100, 20, 1) == [79, 0] +; run: %ssub_overflow_bin_i64(100, 20, 0) == [80, 0] +; run: %ssub_overflow_bin_i64(-9223372036854775800, 8, 1) == [9223372036854775807, 1] +; run: %ssub_overflow_bin_i64(-9223372036854775800, 8, 0) == [-9223372036854775808, 0] -function %isubborrow_i32_c(i32, i32, i8) -> i8 { -block0(v0: i32, v1: i32, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v4 +function %usub_overflow_bin_i8(i8, i8, i8) -> i8, i8 { +block0(v0: i8, v1: i8, v2: i8): + v3, v4 = usub_overflow_bin v0, v1, v2 + return v3, v4 } -; run: %isubborrow_i32_c(0, 1, 1) == 1 -; run: %isubborrow_i32_c(0, 1, 0) == 1 -; run: %isubborrow_i32_c(100, 20, 1) == 0 -; run: %isubborrow_i32_c(100, 20, 0) == 0 -; run: %isubborrow_i32_c(-2147483640, 8, 1) == 1 -; run: %isubborrow_i32_c(-2147483640, 8, 0) == 1 +; run: %usub_overflow_bin_i8(0, 1, 1) == [-2, 1] +; run: %usub_overflow_bin_i8(0, 1, 10) == [-2, 1] +; run: %usub_overflow_bin_i8(0, 1, 0) == [-1, 1] +; run: %usub_overflow_bin_i8(100, 20, 1) == [79, 0] +; run: %usub_overflow_bin_i8(100, 20, 0) == [80, 0] +; run: %usub_overflow_bin_i8(127, 127, 1) == [-1, 1] +; run: %usub_overflow_bin_i8(127, 127, 0) == [0, 0] +; run: %usub_overflow_bin_i8(-120, 8, 0) == [-128, 0] +; run: %usub_overflow_bin_i8(-120, 8, 1) == [127, 0] +; run: %usub_overflow_bin_i8(-120, 8, 10) == [127, 0] +function %usub_overflow_bin_i16(i16, i16, i8) -> i16, i8 { +block0(v0: i16, v1: i16, v2: i8): + v3, v4 = usub_overflow_bin v0, v1, v2 + return v3, v4 +} +; run: %usub_overflow_bin_i16(0, 1, 1) == [-2, 1] +; run: %usub_overflow_bin_i16(0, 1, 10) == [-2, 1] +; run: %usub_overflow_bin_i16(0, 1, 0) == [-1, 1] +; run: %usub_overflow_bin_i16(100, 20, 1) == [79, 0] +; run: %usub_overflow_bin_i16(100, 20, 0) == [80, 0] +; run: %usub_overflow_bin_i16(-32000, 768, 1) == [32767, 0] +; run: %usub_overflow_bin_i16(-32000, 768, 0) == [-32768, 0] -function %isubborrow_i64_v(i64, i64, i8) -> i64 { -block0(v0: i64, v1: i64, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v3 +function %usub_overflow_bin_i32(i32, i32, i8) -> i32, i8 { +block0(v0: i32, v1: i32, v2: i8): + v3, v4 = usub_overflow_bin v0, v1, v2 + return v3, v4 } -; run: %isubborrow_i64_v(0, 1, 1) == -2 -; run: %isubborrow_i64_v(0, 1, 0) == -1 -; run: %isubborrow_i64_v(100, 20, 1) == 79 -; run: %isubborrow_i64_v(100, 20, 0) == 80 -; run: %isubborrow_i64_v(-9223372036854775800, 8, 1) == 9223372036854775807 -; run: %isubborrow_i64_v(-9223372036854775800, 8, 0) == -9223372036854775808 +; run: %usub_overflow_bin_i32(0, 1, 1) == [-2, 1] +; run: %usub_overflow_bin_i32(0, 1, 10) == [-2, 1] +; run: %usub_overflow_bin_i32(0, 1, 0) == [-1, 1] +; run: %usub_overflow_bin_i32(100, 20, 1) == [79, 0] +; run: %usub_overflow_bin_i32(100, 20, 0) == [80, 0] +; run: %usub_overflow_bin_i32(-2147483640, 8, 1) == [2147483647, 0] +; run: %usub_overflow_bin_i32(-2147483640, 8, 0) == [-2147483648, 0] -function %isubborrow_i64_c(i64, i64, i8) -> i8 { +function %usub_overflow_bin_i64(i64, i64, i8) -> i64, i8 { block0(v0: i64, v1: i64, v2: i8): - v3, v4 = isub_borrow v0, v1, v2 - return v4 + v3, v4 = usub_overflow_bin v0, v1, v2 + return v3, v4 } -; run: %isubborrow_i64_c(0, 1, 1) == 1 -; run: %isubborrow_i64_c(0, 1, 0) == 1 -; run: %isubborrow_i64_c(100, 20, 1) == 0 -; run: %isubborrow_i64_c(100, 20, 0) == 0 -; run: %isubborrow_i64_c(-9223372036854775800, 8, 1) == 1 -; run: %isubborrow_i64_c(-9223372036854775800, 8, 0) == 1 +; run: %usub_overflow_bin_i64(0, 1, 1) == [-2, 1] +; run: %usub_overflow_bin_i64(0, 1, 10) == [-2, 1] +; run: %usub_overflow_bin_i64(0, 1, 0) == [-1, 1] +; run: %usub_overflow_bin_i64(100, 20, 1) == [79, 0] +; run: %usub_overflow_bin_i64(100, 20, 0) == [80, 0] +; run: %usub_overflow_bin_i64(-9223372036854775800, 8, 1) == [9223372036854775807, 0] +; run: %usub_overflow_bin_i64(-9223372036854775800, 8, 0) == [-9223372036854775808, 0] diff --git a/cranelift/filetests/filetests/runtests/smul_overflow.clif b/cranelift/filetests/filetests/runtests/smul_overflow.clif index d61cae79b409..b70b8ca65abd 100644 --- a/cranelift/filetests/filetests/runtests/smul_overflow.clif +++ b/cranelift/filetests/filetests/runtests/smul_overflow.clif @@ -1,6 +1,7 @@ test interpret test run target x86_64 +target x86_64 has_bmi2 target aarch64 function %smulof_i64(i64, i64) -> i64, i8 { @@ -73,4 +74,4 @@ block0(v0: i8, v1: i8): ; run: %smulof_i8(0x7F, 0x7F) == [1, 1] ; run: %smulof_i8(0x80, 0x7F) == [0x80, 1] ; run: %smulof_i8(0x01, 0xFE) == [0xFE, 0] -; run: %smulof_i8(0xC0, 0xDE) == [0x80, 1] \ No newline at end of file +; run: %smulof_i8(0xC0, 0xDE) == [0x80, 1] diff --git a/cranelift/filetests/filetests/runtests/smulhi.clif b/cranelift/filetests/filetests/runtests/smulhi.clif index df9f13adf377..7cc05a1c0f18 100644 --- a/cranelift/filetests/filetests/runtests/smulhi.clif +++ b/cranelift/filetests/filetests/runtests/smulhi.clif @@ -2,6 +2,8 @@ test interpret test run target aarch64 target s390x +target x86_64 +target x86_64 has_bmi2 target x86_64 has_sse3 has_ssse3 has_sse41 target x86_64 has_sse3 has_ssse3 has_sse41 has_avx target riscv64 diff --git a/cranelift/filetests/filetests/runtests/umul_overflow.clif b/cranelift/filetests/filetests/runtests/umul_overflow.clif index a76feb267d07..6f765ab48868 100644 --- a/cranelift/filetests/filetests/runtests/umul_overflow.clif +++ b/cranelift/filetests/filetests/runtests/umul_overflow.clif @@ -1,6 +1,7 @@ test interpret test run target x86_64 +target x86_64 has_bmi2 target aarch64 function %umulof_i64(i64, i64) -> i64, i8 { @@ -65,4 +66,4 @@ block0(v0: i8, v1: i8): ; run: %umulof_i8(0x7F, 0x7F) == [1, 1] ; run: %umulof_i8(0x80, 0x7F) == [0x80, 1] ; run: %umulof_i8(0x01, 0xFE) == [0xFE, 0] -; run: %umulof_i8(0xC0, 0xDE) == [0x80, 1] \ No newline at end of file +; run: %umulof_i8(0xC0, 0xDE) == [0x80, 1] diff --git a/cranelift/filetests/filetests/runtests/umulhi.clif b/cranelift/filetests/filetests/runtests/umulhi.clif index 51d4eee45d92..2d6a1d5c3774 100644 --- a/cranelift/filetests/filetests/runtests/umulhi.clif +++ b/cranelift/filetests/filetests/runtests/umulhi.clif @@ -1,7 +1,9 @@ test interpret test run target aarch64 +target x86_64 target x86_64 has_sse3 has_ssse3 has_sse41 +target x86_64 has_bmi2 target s390x target riscv64 target riscv64 has_c has_zcb diff --git a/cranelift/filetests/src/test_wasm/env.rs b/cranelift/filetests/src/test_wasm/env.rs deleted file mode 100644 index dccc9c31fce2..000000000000 --- a/cranelift/filetests/src/test_wasm/env.rs +++ /dev/null @@ -1,712 +0,0 @@ -//! `cranelift_wasm` environments for translating Wasm to CLIF. -//! -//! Mostly wrappers around the dummy environments, but also supports -//! pre-configured heaps. - -use std::collections::{BTreeMap, HashSet}; - -use super::config::TestConfig; -use cranelift::prelude::EntityRef; -use cranelift_codegen::{ - ir, - isa::{TargetFrontendConfig, TargetIsa}, -}; -use cranelift_wasm::{ - DummyEnvironment, FuncEnvironment, FuncIndex, ModuleEnvironment, TargetEnvironment, - TypeConvert, TypeIndex, WasmHeapType, -}; - -pub struct ModuleEnv { - pub inner: DummyEnvironment, - pub config: TestConfig, - pub heap_access_spectre_mitigation: bool, - pub proof_carrying_code: bool, -} - -impl ModuleEnv { - pub fn new(target_isa: &dyn TargetIsa, config: TestConfig) -> Self { - let inner = DummyEnvironment::new(target_isa.frontend_config()); - Self { - inner, - config, - heap_access_spectre_mitigation: target_isa - .flags() - .enable_heap_access_spectre_mitigation(), - proof_carrying_code: target_isa.flags().enable_pcc(), - } - } -} - -impl<'data> ModuleEnvironment<'data> for ModuleEnv { - fn define_function_body( - &mut self, - mut validator: wasmparser::FuncValidator, - body: wasmparser::FunctionBody<'data>, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .func_bytecode_sizes - .push(body.get_binary_reader().bytes_remaining()); - - let func = { - let mut func_environ = FuncEnv::new( - &self.inner.info, - self.inner.expected_reachability.clone(), - self.config.clone(), - self.heap_access_spectre_mitigation, - self.proof_carrying_code, - ); - let func_index = FuncIndex::new( - self.inner.get_num_func_imports() + self.inner.info.function_bodies.len(), - ); - - let sig = func_environ - .inner - .vmctx_sig(self.inner.get_func_type(func_index)); - let mut func = ir::Function::with_name_signature( - ir::UserFuncName::user(0, func_index.as_u32()), - sig, - ); - - self.inner - .trans - .translate_body(&mut validator, body, &mut func, &mut func_environ)?; - func - }; - - self.inner.info.function_bodies.push(func); - - Ok(()) - } - - fn wasm_features(&self) -> wasmparser::WasmFeatures { - self.inner.wasm_features() - | wasmparser::WasmFeatures::MEMORY64 - | wasmparser::WasmFeatures::MULTI_MEMORY - | wasmparser::WasmFeatures::RELAXED_SIMD - } - - // ================================================================ - // ====== Everything below here is delegated to `self.inner` ====== - // ================================================================ - - fn declare_type_func( - &mut self, - wasm_func_type: cranelift_wasm::WasmFuncType, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_type_func(wasm_func_type) - } - - fn declare_func_import( - &mut self, - index: cranelift_wasm::TypeIndex, - module: &'data str, - field: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_func_import(index, module, field) - } - - fn declare_table_import( - &mut self, - table: cranelift_wasm::Table, - module: &'data str, - field: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_table_import(table, module, field) - } - - fn declare_memory_import( - &mut self, - memory: cranelift_wasm::Memory, - module: &'data str, - field: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_memory_import(memory, module, field) - } - - fn declare_global_import( - &mut self, - global: cranelift_wasm::Global, - module: &'data str, - field: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_global_import(global, module, field) - } - - fn declare_func_type( - &mut self, - index: cranelift_wasm::TypeIndex, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_func_type(index) - } - - fn declare_table(&mut self, table: cranelift_wasm::Table) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_table(table) - } - - fn declare_memory(&mut self, memory: cranelift_wasm::Memory) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_memory(memory) - } - - fn declare_global( - &mut self, - global: cranelift_wasm::Global, - init: cranelift_wasm::GlobalInit, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_global(global, init) - } - - fn declare_func_export( - &mut self, - func_index: cranelift_wasm::FuncIndex, - name: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_func_export(func_index, name) - } - - fn declare_table_export( - &mut self, - table_index: cranelift_wasm::TableIndex, - name: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_table_export(table_index, name) - } - - fn declare_memory_export( - &mut self, - memory_index: cranelift_wasm::MemoryIndex, - name: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_memory_export(memory_index, name) - } - - fn declare_global_export( - &mut self, - global_index: cranelift_wasm::GlobalIndex, - name: &'data str, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_global_export(global_index, name) - } - - fn declare_start_func( - &mut self, - index: cranelift_wasm::FuncIndex, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_start_func(index) - } - - fn declare_table_elements( - &mut self, - table_index: cranelift_wasm::TableIndex, - base: Option, - offset: u32, - elements: Box<[cranelift_wasm::FuncIndex]>, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .declare_table_elements(table_index, base, offset, elements) - } - - fn declare_passive_element( - &mut self, - index: cranelift_wasm::ElemIndex, - elements: Box<[cranelift_wasm::FuncIndex]>, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_passive_element(index, elements) - } - - fn declare_passive_data( - &mut self, - data_index: cranelift_wasm::DataIndex, - data: &'data [u8], - ) -> cranelift_wasm::WasmResult<()> { - self.inner.declare_passive_data(data_index, data) - } - - fn declare_data_initialization( - &mut self, - memory_index: cranelift_wasm::MemoryIndex, - base: Option, - offset: u64, - data: &'data [u8], - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .declare_data_initialization(memory_index, base, offset, data) - } -} - -impl TypeConvert for ModuleEnv { - fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType { - todo!() - } -} - -pub struct FuncEnv<'a> { - pub inner: cranelift_wasm::DummyFuncEnvironment<'a>, - pub config: TestConfig, - pub name_to_ir_global: BTreeMap, - pub next_heap: usize, - pub heap_access_spectre_mitigation: bool, - pub proof_carrying_code: bool, -} - -impl<'a> FuncEnv<'a> { - pub fn new( - mod_info: &'a cranelift_wasm::DummyModuleInfo, - expected_reachability: Option, - config: TestConfig, - heap_access_spectre_mitigation: bool, - proof_carrying_code: bool, - ) -> Self { - let inner = cranelift_wasm::DummyFuncEnvironment::new(mod_info, expected_reachability); - Self { - inner, - config, - name_to_ir_global: Default::default(), - next_heap: 0, - heap_access_spectre_mitigation, - proof_carrying_code, - } - } -} - -impl TypeConvert for FuncEnv<'_> { - fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType { - todo!() - } -} - -impl<'a> TargetEnvironment for FuncEnv<'a> { - fn target_config(&self) -> TargetFrontendConfig { - self.inner.target_config() - } - - fn heap_access_spectre_mitigation(&self) -> bool { - self.heap_access_spectre_mitigation - } - - fn proof_carrying_code(&self) -> bool { - self.proof_carrying_code - } -} - -impl<'a> FuncEnvironment for FuncEnv<'a> { - fn make_heap( - &mut self, - func: &mut ir::Function, - index: cranelift_wasm::MemoryIndex, - ) -> cranelift_wasm::WasmResult { - if self.next_heap < self.config.heaps.len() { - let heap = &self.config.heaps[self.next_heap]; - self.next_heap += 1; - - // Create all of the globals our test heap depends on in topological - // order. - let mut worklist: Vec<&str> = heap - .dependencies() - .filter(|g| !self.name_to_ir_global.contains_key(*g)) - .collect(); - let mut in_worklist: HashSet<&str> = worklist.iter().copied().collect(); - 'worklist_fixpoint: while let Some(global_name) = worklist.pop() { - let was_in_set = in_worklist.remove(global_name); - debug_assert!(was_in_set); - - let global = &self.config.globals[global_name]; - - // Check that all of this global's dependencies have already - // been created. If not, then enqueue them to be created - // first and re-enqueue this global. - for g in global.dependencies() { - if !self.name_to_ir_global.contains_key(g) { - if in_worklist.contains(&g) { - return Err(cranelift_wasm::WasmError::User(format!( - "dependency cycle between global '{global_name}' and global '{g}'" - ))); - } - - worklist.push(global_name); - let is_new_entry = in_worklist.insert(global_name); - debug_assert!(is_new_entry); - - worklist.push(g); - let is_new_entry = in_worklist.insert(g); - debug_assert!(is_new_entry); - - continue 'worklist_fixpoint; - } - } - - // All of this globals dependencies have already been - // created, we can create it now! - let data = global.to_ir(&self.name_to_ir_global); - let g = func.create_global_value(data); - self.name_to_ir_global.insert(global_name.to_string(), g); - } - - Ok(self.inner.heaps.push(heap.to_ir(&self.name_to_ir_global))) - } else { - self.inner.make_heap(func, index) - } - } - - // ================================================================ - // ====== Everything below here is delegated to `self.inner` ====== - // ================================================================ - - fn make_global( - &mut self, - func: &mut ir::Function, - index: cranelift_wasm::GlobalIndex, - ) -> cranelift_wasm::WasmResult { - self.inner.make_global(func, index) - } - - fn make_table( - &mut self, - func: &mut ir::Function, - index: cranelift_wasm::TableIndex, - ) -> cranelift_wasm::WasmResult { - self.inner.make_table(func, index) - } - - fn make_indirect_sig( - &mut self, - func: &mut ir::Function, - index: cranelift_wasm::TypeIndex, - ) -> cranelift_wasm::WasmResult { - self.inner.make_indirect_sig(func, index) - } - - fn make_direct_func( - &mut self, - func: &mut ir::Function, - index: FuncIndex, - ) -> cranelift_wasm::WasmResult { - self.inner.make_direct_func(func, index) - } - - fn translate_call_indirect( - &mut self, - builder: &mut cranelift_frontend::FunctionBuilder, - table_index: cranelift_wasm::TableIndex, - table: ir::Table, - sig_index: cranelift_wasm::TypeIndex, - sig_ref: ir::SigRef, - callee: ir::Value, - call_args: &[ir::Value], - ) -> cranelift_wasm::WasmResult { - self.inner.translate_call_indirect( - builder, - table_index, - table, - sig_index, - sig_ref, - callee, - call_args, - ) - } - - fn translate_return_call_indirect( - &mut self, - builder: &mut cranelift_frontend::FunctionBuilder, - table_index: cranelift_wasm::TableIndex, - table: ir::Table, - sig_index: TypeIndex, - sig_ref: ir::SigRef, - callee: ir::Value, - call_args: &[ir::Value], - ) -> cranelift_wasm::WasmResult<()> { - self.inner.translate_return_call_indirect( - builder, - table_index, - table, - sig_index, - sig_ref, - callee, - call_args, - ) - } - - fn translate_return_call_ref( - &mut self, - builder: &mut cranelift_frontend::FunctionBuilder, - sig_ref: ir::SigRef, - callee: ir::Value, - call_args: &[ir::Value], - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_return_call_ref(builder, sig_ref, callee, call_args) - } - - fn translate_memory_grow( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - index: cranelift_wasm::MemoryIndex, - heap: cranelift_wasm::Heap, - val: ir::Value, - ) -> cranelift_wasm::WasmResult { - self.inner.translate_memory_grow(pos, index, heap, val) - } - - fn translate_memory_size( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - index: cranelift_wasm::MemoryIndex, - heap: cranelift_wasm::Heap, - ) -> cranelift_wasm::WasmResult { - self.inner.translate_memory_size(pos, index, heap) - } - - fn translate_memory_copy( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - src_index: cranelift_wasm::MemoryIndex, - src_heap: cranelift_wasm::Heap, - dst_index: cranelift_wasm::MemoryIndex, - dst_heap: cranelift_wasm::Heap, - dst: ir::Value, - src: ir::Value, - len: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_memory_copy(pos, src_index, src_heap, dst_index, dst_heap, dst, src, len) - } - - fn translate_memory_fill( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - index: cranelift_wasm::MemoryIndex, - heap: cranelift_wasm::Heap, - dst: ir::Value, - val: ir::Value, - len: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_memory_fill(pos, index, heap, dst, val, len) - } - - fn translate_memory_init( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - index: cranelift_wasm::MemoryIndex, - heap: cranelift_wasm::Heap, - seg_index: u32, - dst: ir::Value, - src: ir::Value, - len: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_memory_init(pos, index, heap, seg_index, dst, src, len) - } - - fn translate_data_drop( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - seg_index: u32, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.translate_data_drop(pos, seg_index) - } - - fn translate_table_size( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - index: cranelift_wasm::TableIndex, - table: ir::Table, - ) -> cranelift_wasm::WasmResult { - self.inner.translate_table_size(pos, index, table) - } - - fn translate_table_grow( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - table_index: cranelift_wasm::TableIndex, - table: ir::Table, - delta: ir::Value, - init_value: ir::Value, - ) -> cranelift_wasm::WasmResult { - self.inner - .translate_table_grow(pos, table_index, table, delta, init_value) - } - - fn translate_table_get( - &mut self, - builder: &mut cranelift_frontend::FunctionBuilder, - table_index: cranelift_wasm::TableIndex, - table: ir::Table, - index: ir::Value, - ) -> cranelift_wasm::WasmResult { - self.inner - .translate_table_get(builder, table_index, table, index) - } - - fn translate_table_set( - &mut self, - builder: &mut cranelift_frontend::FunctionBuilder, - table_index: cranelift_wasm::TableIndex, - table: ir::Table, - value: ir::Value, - index: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_table_set(builder, table_index, table, value, index) - } - - fn translate_table_copy( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - dst_table_index: cranelift_wasm::TableIndex, - dst_table: ir::Table, - src_table_index: cranelift_wasm::TableIndex, - src_table: ir::Table, - dst: ir::Value, - src: ir::Value, - len: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.translate_table_copy( - pos, - dst_table_index, - dst_table, - src_table_index, - src_table, - dst, - src, - len, - ) - } - - fn translate_table_fill( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - table_index: cranelift_wasm::TableIndex, - dst: ir::Value, - val: ir::Value, - len: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_table_fill(pos, table_index, dst, val, len) - } - - fn translate_table_init( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - seg_index: u32, - table_index: cranelift_wasm::TableIndex, - table: ir::Table, - dst: ir::Value, - src: ir::Value, - len: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_table_init(pos, seg_index, table_index, table, dst, src, len) - } - - fn translate_elem_drop( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - seg_index: u32, - ) -> cranelift_wasm::WasmResult<()> { - self.inner.translate_elem_drop(pos, seg_index) - } - - fn translate_ref_func( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - func_index: FuncIndex, - ) -> cranelift_wasm::WasmResult { - self.inner.translate_ref_func(pos, func_index) - } - - fn translate_custom_global_get( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - global_index: cranelift_wasm::GlobalIndex, - ) -> cranelift_wasm::WasmResult { - self.inner.translate_custom_global_get(pos, global_index) - } - - fn translate_custom_global_set( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - global_index: cranelift_wasm::GlobalIndex, - val: ir::Value, - ) -> cranelift_wasm::WasmResult<()> { - self.inner - .translate_custom_global_set(pos, global_index, val) - } - - fn translate_atomic_wait( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - index: cranelift_wasm::MemoryIndex, - heap: cranelift_wasm::Heap, - addr: ir::Value, - expected: ir::Value, - timeout: ir::Value, - ) -> cranelift_wasm::WasmResult { - self.inner - .translate_atomic_wait(pos, index, heap, addr, expected, timeout) - } - - fn translate_atomic_notify( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor, - index: cranelift_wasm::MemoryIndex, - heap: cranelift_wasm::Heap, - addr: ir::Value, - count: ir::Value, - ) -> cranelift_wasm::WasmResult { - self.inner - .translate_atomic_notify(pos, index, heap, addr, count) - } - - fn heaps( - &self, - ) -> &cranelift_codegen::entity::PrimaryMap - { - self.inner.heaps() - } - - fn relaxed_simd_deterministic(&self) -> bool { - self.config.relaxed_simd_deterministic - } - - fn is_x86(&self) -> bool { - self.config.target.contains("x86_64") - } - - fn use_x86_pmaddubsw_for_dot(&self) -> bool { - self.config.target.contains("x86_64") - } - - fn translate_call_ref( - &mut self, - _builder: &mut cranelift_frontend::FunctionBuilder<'_>, - _ty: ir::SigRef, - _func: ir::Value, - _args: &[ir::Value], - ) -> cranelift_wasm::WasmResult { - unimplemented!() - } - - fn translate_ref_i31( - &mut self, - _pos: cranelift_codegen::cursor::FuncCursor, - _val: ir::Value, - ) -> cranelift_wasm::WasmResult { - unimplemented!() - } - - fn translate_i31_get_s( - &mut self, - _pos: cranelift_codegen::cursor::FuncCursor, - _i31ref: ir::Value, - ) -> cranelift_wasm::WasmResult { - unimplemented!() - } - - fn translate_i31_get_u( - &mut self, - _pos: cranelift_codegen::cursor::FuncCursor, - _i31ref: ir::Value, - ) -> cranelift_wasm::WasmResult { - unimplemented!() - } -} diff --git a/cranelift/frontend/Cargo.toml b/cranelift/frontend/Cargo.toml index 4352525dc607..ca8662afa12f 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.112.0" +version = "0.113.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 b7b1049ae3cc..d8145acfb4cc 100644 --- a/cranelift/fuzzgen/src/function_generator.rs +++ b/cranelift/fuzzgen/src/function_generator.rs @@ -512,6 +512,10 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) - } } + // This requires precise runtime integration so it's not supported at + // all in fuzzgen just yet. + Opcode::StackSwitch => return false, + _ => {} } @@ -921,11 +925,11 @@ static OPCODE_SIGNATURES: Lazy> = Lazy::new(|| { (Opcode::UremImm), (Opcode::SremImm), (Opcode::IrsubImm), - (Opcode::IaddCin), - (Opcode::IaddCarry), + (Opcode::UaddOverflowCin), + (Opcode::SaddOverflowCin), (Opcode::UaddOverflowTrap), - (Opcode::IsubBin), - (Opcode::IsubBorrow), + (Opcode::UsubOverflowBin), + (Opcode::SsubOverflowBin), (Opcode::BandImm), (Opcode::BorImm), (Opcode::BxorImm), diff --git a/cranelift/interpreter/Cargo.toml b/cranelift/interpreter/Cargo.toml index c914823974a4..9561216db946 100644 --- a/cranelift/interpreter/Cargo.toml +++ b/cranelift/interpreter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-interpreter" -version = "0.112.0" +version = "0.113.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 ef8b1b5f5ffc..eec476afe6b6 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -718,24 +718,24 @@ where let (sum, carry) = arg(0).smul_overflow(arg(1))?; assign_multiple(&[sum, DataValueExt::bool(carry, false, types::I8)?]) } - Opcode::IaddCin => choose( - DataValueExt::into_bool(arg(2))?, - DataValueExt::add( - DataValueExt::add(arg(0), arg(1))?, - DataValueExt::int(1, ctrl_ty)?, - )?, - DataValueExt::add(arg(0), arg(1))?, - ), - Opcode::IaddCarry => { - let mut sum = DataValueExt::add(arg(0), arg(1))?; - let mut carry = arg(0).sadd_checked(arg(1))?.is_none(); + Opcode::SaddOverflowCin => { + let (mut sum, mut carry) = arg(0).sadd_overflow(arg(1))?; if DataValueExt::into_bool(arg(2))? { - carry |= sum - .clone() - .sadd_checked(DataValueExt::int(1, ctrl_ty)?)? - .is_none(); - sum = DataValueExt::add(sum, DataValueExt::int(1, ctrl_ty)?)?; + let (sum2, carry2) = sum.sadd_overflow(DataValueExt::int(1, ctrl_ty)?)?; + carry |= carry2; + sum = sum2; + } + + assign_multiple(&[sum, DataValueExt::bool(carry, false, types::I8)?]) + } + Opcode::UaddOverflowCin => { + let (mut sum, mut carry) = arg(0).uadd_overflow(arg(1))?; + + if DataValueExt::into_bool(arg(2))? { + let (sum2, carry2) = sum.uadd_overflow(DataValueExt::int(1, ctrl_ty)?)?; + carry |= carry2; + sum = sum2; } assign_multiple(&[sum, DataValueExt::bool(carry, false, types::I8)?]) @@ -749,23 +749,27 @@ where assign(sum) } } - Opcode::IsubBin => choose( - DataValueExt::into_bool(arg(2))?, - DataValueExt::sub( - arg(0), - DataValueExt::add(arg(1), DataValueExt::int(1, ctrl_ty)?)?, - )?, - DataValueExt::sub(arg(0), arg(1))?, - ), - Opcode::IsubBorrow => { - let rhs = if DataValueExt::into_bool(arg(2))? { - DataValueExt::add(arg(1), DataValueExt::int(1, ctrl_ty)?)? - } else { - arg(1) - }; - let borrow = arg(0) < rhs; - let sum = DataValueExt::sub(arg(0), rhs)?; - assign_multiple(&[sum, DataValueExt::bool(borrow, false, types::I8)?]) + Opcode::SsubOverflowBin => { + let (mut sub, mut carry) = arg(0).ssub_overflow(arg(1))?; + + if DataValueExt::into_bool(arg(2))? { + let (sub2, carry2) = sub.ssub_overflow(DataValueExt::int(1, ctrl_ty)?)?; + carry |= carry2; + sub = sub2; + } + + assign_multiple(&[sub, DataValueExt::bool(carry, false, types::I8)?]) + } + Opcode::UsubOverflowBin => { + let (mut sub, mut carry) = arg(0).usub_overflow(arg(1))?; + + if DataValueExt::into_bool(arg(2))? { + let (sub2, carry2) = sub.usub_overflow(DataValueExt::int(1, ctrl_ty)?)?; + carry |= carry2; + sub = sub2; + } + + assign_multiple(&[sub, DataValueExt::bool(carry, false, types::I8)?]) } Opcode::Band => binary(DataValueExt::and, arg(0), arg(1))?, Opcode::Bor => binary(DataValueExt::or, arg(0), arg(1))?, diff --git a/cranelift/isle/isle/Cargo.toml b/cranelift/isle/isle/Cargo.toml index f96e9325a92a..05519e7978e4 100644 --- a/cranelift/isle/isle/Cargo.toml +++ b/cranelift/isle/isle/Cargo.toml @@ -7,7 +7,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.112.0" +version = "0.113.0" [lints] workspace = true diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml index 28ea982991cc..e8058d9deda7 100644 --- a/cranelift/jit/Cargo.toml +++ b/cranelift/jit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-jit" -version = "0.112.0" +version = "0.113.0" authors = ["The Cranelift Project Developers"] description = "A JIT library backed by Cranelift" repository = "https://github.com/bytecodealliance/wasmtime" diff --git a/cranelift/module/Cargo.toml b/cranelift/module/Cargo.toml index 7cd0a4bf7a92..e2c8e10d563c 100644 --- a/cranelift/module/Cargo.toml +++ b/cranelift/module/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-module" -version = "0.112.0" +version = "0.113.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 599536d27517..3b94c0d13f5c 100644 --- a/cranelift/native/Cargo.toml +++ b/cranelift/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-native" -version = "0.112.0" +version = "0.113.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 bbacba0d3122..3e83845528e5 100644 --- a/cranelift/object/Cargo.toml +++ b/cranelift/object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-object" -version = "0.112.0" +version = "0.113.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 29579bc8aa72..a0ea0935b70b 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.112.0" +version = "0.113.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 f37986220b73..5d1fefd4203c 100644 --- a/cranelift/serde/Cargo.toml +++ b/cranelift/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-serde" -version = "0.112.0" +version = "0.113.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 8da764de751a..7e6d2d1ba443 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.112.0" +version = "0.113.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 79d84ee4aaa3..c51f2e3a459f 100644 --- a/cranelift/wasm/Cargo.toml +++ b/cranelift/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cranelift-wasm" -version = "0.112.0" +version = "0.113.0" authors = ["The Cranelift Project Developers"] description = "Translator from WebAssembly to Cranelift IR" documentation = "https://docs.rs/cranelift-wasm" diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index 12a6d88f43c5..01f89c2c36fe 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -245,7 +245,7 @@ pub fn translate_operator( // We do nothing } Operator::Unreachable => { - builder.ins().trap(ir::TrapCode::UnreachableCodeReached); + environ.trap(builder, ir::TrapCode::UnreachableCodeReached); state.reachable = false; } /***************************** Control flow blocks ********************************** @@ -1016,19 +1016,19 @@ pub fn translate_operator( } Operator::I64TruncF64S | Operator::I64TruncF32S => { let val = state.pop1(); - state.push1(builder.ins().fcvt_to_sint(I64, val)); + state.push1(environ.translate_fcvt_to_sint(builder, I64, val)); } Operator::I32TruncF64S | Operator::I32TruncF32S => { let val = state.pop1(); - state.push1(builder.ins().fcvt_to_sint(I32, val)); + state.push1(environ.translate_fcvt_to_sint(builder, I32, val)); } Operator::I64TruncF64U | Operator::I64TruncF32U => { let val = state.pop1(); - state.push1(builder.ins().fcvt_to_uint(I64, val)); + state.push1(environ.translate_fcvt_to_uint(builder, I64, val)); } Operator::I32TruncF64U | Operator::I32TruncF32U => { let val = state.pop1(); - state.push1(builder.ins().fcvt_to_uint(I32, val)); + state.push1(environ.translate_fcvt_to_uint(builder, I32, val)); } Operator::I64TruncSatF64S | Operator::I64TruncSatF32S => { let val = state.pop1(); @@ -1155,19 +1155,19 @@ pub fn translate_operator( } Operator::I32DivS | Operator::I64DivS => { let (arg1, arg2) = state.pop2(); - state.push1(builder.ins().sdiv(arg1, arg2)); + state.push1(environ.translate_sdiv(builder, arg1, arg2)); } Operator::I32DivU | Operator::I64DivU => { let (arg1, arg2) = state.pop2(); - state.push1(builder.ins().udiv(arg1, arg2)); + state.push1(environ.translate_udiv(builder, arg1, arg2)); } Operator::I32RemS | Operator::I64RemS => { let (arg1, arg2) = state.pop2(); - state.push1(builder.ins().srem(arg1, arg2)); + state.push1(environ.translate_srem(builder, arg1, arg2)); } Operator::I32RemU | Operator::I64RemU => { let (arg1, arg2) = state.pop2(); - state.push1(builder.ins().urem(arg1, arg2)); + state.push1(environ.translate_urem(builder, arg1, arg2)); } Operator::F32Min | Operator::F64Min => { let (arg1, arg2) = state.pop2(); @@ -1255,9 +1255,7 @@ pub fn translate_operator( } else { let index_type = environ.heaps()[heap].index_type; let offset = builder.ins().iconst(index_type, memarg.offset as i64); - builder - .ins() - .uadd_overflow_trap(addr, offset, ir::TrapCode::HeapOutOfBounds) + environ.uadd_overflow_trap(builder, addr, offset, ir::TrapCode::HeapOutOfBounds) }; // `fn translate_atomic_wait` can inspect the type of `expected` to figure out what // code it needs to generate, if it wants. @@ -1281,9 +1279,7 @@ pub fn translate_operator( } else { let index_type = environ.heaps()[heap].index_type; let offset = builder.ins().iconst(index_type, memarg.offset as i64); - builder - .ins() - .uadd_overflow_trap(addr, offset, ir::TrapCode::HeapOutOfBounds) + environ.uadd_overflow_trap(builder, addr, offset, ir::TrapCode::HeapOutOfBounds) }; let res = environ.translate_atomic_notify( builder.cursor(), @@ -2480,7 +2476,7 @@ pub fn translate_operator( Operator::RefAsNonNull => { let r = state.pop1(); let is_null = environ.translate_ref_is_null(builder, r)?; - builder.ins().trapnz(is_null, ir::TrapCode::NullReference); + environ.trapnz(builder, is_null, ir::TrapCode::NullReference); state.push1(r); } @@ -2491,12 +2487,12 @@ pub fn translate_operator( } Operator::I31GetS => { let i31ref = state.pop1(); - let val = environ.translate_i31_get_s(builder.cursor(), i31ref)?; + let val = environ.translate_i31_get_s(builder, i31ref)?; state.push1(val); } Operator::I31GetU => { let i31ref = state.pop1(); - let val = environ.translate_i31_get_u(builder.cursor(), i31ref)?; + let val = environ.translate_i31_get_u(builder, i31ref)?; state.push1(val); } @@ -2930,9 +2926,7 @@ where Err(_) => { let offset = builder.ins().iconst(heap.index_type, memarg.offset as i64); let adjusted_index = - builder - .ins() - .uadd_overflow_trap(index, offset, ir::TrapCode::HeapOutOfBounds); + environ.uadd_overflow_trap(builder, index, offset, ir::TrapCode::HeapOutOfBounds); bounds_checks::bounds_check_and_compute_addr( builder, environ, @@ -2969,11 +2963,12 @@ where Ok(Reachability::Reachable((flags, index, addr))) } -fn align_atomic_addr( +fn align_atomic_addr( memarg: &MemArg, loaded_bytes: u8, builder: &mut FunctionBuilder, state: &mut FuncTranslationState, + environ: &mut FE, ) { // Atomic addresses must all be aligned correctly, and for now we check // alignment before we check out-of-bounds-ness. The order of this check may @@ -3000,7 +2995,7 @@ fn align_atomic_addr( .ins() .band_imm(effective_addr, i64::from(loaded_bytes - 1)); let f = builder.ins().icmp_imm(IntCC::NotEqual, misalignment, 0); - builder.ins().trapnz(f, ir::TrapCode::HeapMisaligned); + environ.trapnz(builder, f, ir::TrapCode::HeapMisaligned); } } @@ -3014,7 +3009,7 @@ fn prepare_atomic_addr( state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult> { - align_atomic_addr(memarg, loaded_bytes, builder, state); + align_atomic_addr(memarg, loaded_bytes, builder, state, environ); prepare_addr(memarg, loaded_bytes, builder, state, environ) } diff --git a/cranelift/wasm/src/code_translator/bounds_checks.rs b/cranelift/wasm/src/code_translator/bounds_checks.rs index c66eb8001acb..cd1ca3282a64 100644 --- a/cranelift/wasm/src/code_translator/bounds_checks.rs +++ b/cranelift/wasm/src/code_translator/bounds_checks.rs @@ -63,7 +63,8 @@ where let pcc = env.proof_carrying_code(); let host_page_size_log2 = env.target_config().page_size_align_log2; - let can_use_virtual_memory = heap.page_size_log2 >= host_page_size_log2; + let can_use_virtual_memory = + heap.page_size_log2 >= host_page_size_log2 && env.signals_based_traps(); let make_compare = |builder: &mut FunctionBuilder, compare_kind: IntCC, @@ -154,9 +155,9 @@ where Some(0), ); Reachable(explicit_check_oob_condition_and_compute_addr( - &mut builder.cursor(), + env, + builder, heap, - env.pointer_type(), index, offset, access_size, @@ -204,9 +205,9 @@ where Some(0), ); Reachable(explicit_check_oob_condition_and_compute_addr( - &mut builder.cursor(), + env, + builder, heap, - env.pointer_type(), index, offset, access_size, @@ -248,9 +249,9 @@ where Some(adjustment), ); Reachable(explicit_check_oob_condition_and_compute_addr( - &mut builder.cursor(), + env, + builder, heap, - env.pointer_type(), index, offset, access_size, @@ -275,7 +276,8 @@ where builder.func.dfg.facts[access_size_val] = Some(Fact::constant(pointer_bit_width, offset_and_size)); } - let adjusted_index = builder.ins().uadd_overflow_trap( + let adjusted_index = env.uadd_overflow_trap( + builder, index, access_size_val, ir::TrapCode::HeapOutOfBounds, @@ -297,9 +299,9 @@ where Some(0), ); Reachable(explicit_check_oob_condition_and_compute_addr( - &mut builder.cursor(), + env, + builder, heap, - env.pointer_type(), index, offset, access_size, @@ -323,7 +325,7 @@ where "static memories require the ability to use virtual memory" ); env.before_unconditionally_trapping_memory_access(builder)?; - builder.ins().trap(ir::TrapCode::HeapOutOfBounds); + env.trap(builder, ir::TrapCode::HeapOutOfBounds); Unreachable } @@ -423,9 +425,9 @@ where Some(0), ); Reachable(explicit_check_oob_condition_and_compute_addr( - &mut builder.cursor(), + env, + builder, heap, - env.pointer_type(), index, offset, access_size, @@ -550,10 +552,10 @@ impl AddrPcc { /// /// This function deduplicates explicit bounds checks and Spectre mitigations /// that inherently also implement bounds checking. -fn explicit_check_oob_condition_and_compute_addr( - pos: &mut FuncCursor, +fn explicit_check_oob_condition_and_compute_addr( + env: &mut FE, + builder: &mut FunctionBuilder, heap: &HeapData, - addr_ty: ir::Type, index: ir::Value, offset: u32, access_size: u8, @@ -567,22 +569,27 @@ fn explicit_check_oob_condition_and_compute_addr( oob_condition: ir::Value, ) -> ir::Value { if !spectre_mitigations_enabled { - pos.ins() - .trapnz(oob_condition, ir::TrapCode::HeapOutOfBounds); + env.trapnz(builder, oob_condition, ir::TrapCode::HeapOutOfBounds); } + let addr_ty = env.pointer_type(); - let mut addr = compute_addr(pos, heap, addr_ty, index, offset, pcc); + let mut addr = compute_addr(&mut builder.cursor(), heap, addr_ty, index, offset, pcc); if spectre_mitigations_enabled { - let null = pos.ins().iconst(addr_ty, 0); - addr = pos.ins().select_spectre_guard(oob_condition, null, addr); + // These mitigations rely on trapping when loading from NULL so + // signals-based traps must be allowed for this to be generated. + assert!(env.signals_based_traps()); + let null = builder.ins().iconst(addr_ty, 0); + addr = builder + .ins() + .select_spectre_guard(oob_condition, null, addr); match pcc { None => {} Some(AddrPcc::Static32(ty, size)) => { - pos.func.dfg.facts[null] = + builder.func.dfg.facts[null] = Some(Fact::constant(u16::try_from(addr_ty.bits()).unwrap(), 0)); - pos.func.dfg.facts[addr] = Some(Fact::Mem { + builder.func.dfg.facts[addr] = Some(Fact::Mem { ty, min_offset: 0, max_offset: size.checked_sub(u64::from(access_size)).unwrap(), @@ -590,9 +597,9 @@ fn explicit_check_oob_condition_and_compute_addr( }); } Some(AddrPcc::Dynamic(ty, gv)) => { - pos.func.dfg.facts[null] = + builder.func.dfg.facts[null] = Some(Fact::constant(u16::try_from(addr_ty.bits()).unwrap(), 0)); - pos.func.dfg.facts[addr] = Some(Fact::DynamicMem { + builder.func.dfg.facts[addr] = Some(Fact::DynamicMem { ty, min: Expr::constant(0), max: Expr::offset( diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs deleted file mode 100644 index cb4b09bcec44..000000000000 --- a/cranelift/wasm/src/environ/dummy.rs +++ /dev/null @@ -1,897 +0,0 @@ -//! "Dummy" implementations of `ModuleEnvironment` and `FuncEnvironment` for testing -//! wasm translation. For complete implementations of `ModuleEnvironment` and -//! `FuncEnvironment`, see [wasmtime-environ] in [Wasmtime]. -//! -//! [wasmtime-environ]: https://crates.io/crates/wasmtime-environ -//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime - -use crate::environ::{FuncEnvironment, GlobalVariable, ModuleEnvironment, TargetEnvironment}; -use crate::func_translator::FuncTranslator; -use crate::{ - DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Heap, - HeapData, HeapStyle, Memory, MemoryIndex, Table, TableIndex, TableSize, TypeConvert, TypeIndex, - WasmFuncType, WasmHeapType, WasmResult, -}; -use crate::{TableData, WasmValType}; -use cranelift_codegen::cursor::FuncCursor; -use cranelift_codegen::ir::immediates::Offset32; -use cranelift_codegen::ir::{self, InstBuilder}; -use cranelift_codegen::ir::{types::*, UserFuncName}; -use cranelift_codegen::isa::{CallConv, TargetFrontendConfig}; -use cranelift_entity::{EntityRef, PrimaryMap, SecondaryMap}; -use cranelift_frontend::FunctionBuilder; -use std::boxed::Box; -use std::string::String; -use std::vec::Vec; -use wasmparser::{FuncValidator, FunctionBody, ValidatorResources, WasmFeatures}; -use wasmtime_types::wasm_unsupported; - -/// A collection of names under which a given entity is exported. -pub struct Exportable { - /// A wasm entity. - pub entity: T, - - /// Names under which the entity is exported. - pub export_names: Vec, -} - -impl Exportable { - pub fn new(entity: T) -> Self { - Self { - entity, - export_names: Vec::new(), - } - } -} - -/// The main state belonging to a `DummyEnvironment`. This is split out from -/// `DummyEnvironment` to allow it to be borrowed separately from the -/// `FuncTranslator` field. -pub struct DummyModuleInfo { - /// Target description relevant to frontends producing Cranelift IR. - config: TargetFrontendConfig, - - /// Signatures as provided by `declare_signature`. - pub signatures: PrimaryMap, - - /// Module and field names of imported functions as provided by `declare_func_import`. - pub imported_funcs: Vec<(String, String)>, - - /// Module and field names of imported globals as provided by `declare_global_import`. - pub imported_globals: Vec<(String, String)>, - - /// Module and field names of imported tables as provided by `declare_table_import`. - pub imported_tables: Vec<(String, String)>, - - /// Module and field names of imported memories as provided by `declare_memory_import`. - pub imported_memories: Vec<(String, String)>, - - /// Functions, imported and local. - pub functions: PrimaryMap>, - - /// Function bodies. - pub function_bodies: PrimaryMap, - - /// Tables as provided by `declare_table`. - pub tables: PrimaryMap>, - - /// Memories as provided by `declare_memory`. - pub memories: PrimaryMap>, - - /// Globals as provided by `declare_global`. - pub globals: PrimaryMap>, - - /// The start function. - pub start_func: Option, -} - -impl DummyModuleInfo { - /// Creates a new `DummyModuleInfo` instance. - pub fn new(config: TargetFrontendConfig) -> Self { - Self { - config, - signatures: PrimaryMap::new(), - imported_funcs: Vec::new(), - imported_globals: Vec::new(), - imported_tables: Vec::new(), - imported_memories: Vec::new(), - functions: PrimaryMap::new(), - function_bodies: PrimaryMap::new(), - tables: PrimaryMap::new(), - memories: PrimaryMap::new(), - globals: PrimaryMap::new(), - start_func: None, - } - } -} - -/// This `ModuleEnvironment` implementation is a "naïve" one, doing essentially nothing and -/// emitting placeholders when forced to. Don't try to execute code translated for this -/// environment, essentially here for translation debug purposes. -pub struct DummyEnvironment { - /// Module information. - pub info: DummyModuleInfo, - - /// Function translation. - pub trans: FuncTranslator, - - /// Vector of wasm bytecode size for each function. - pub func_bytecode_sizes: Vec, - - /// Name of the module from the wasm file. - pub module_name: Option, - - /// Function names. - function_names: SecondaryMap, -} - -impl DummyEnvironment { - /// Creates a new `DummyEnvironment` instance. - pub fn new(config: TargetFrontendConfig) -> Self { - Self { - info: DummyModuleInfo::new(config), - trans: FuncTranslator::new(), - func_bytecode_sizes: Vec::new(), - module_name: None, - function_names: SecondaryMap::new(), - } - } - - /// Return a `DummyFuncEnvironment` for translating functions within this - /// `DummyEnvironment`. - pub fn func_env(&self) -> DummyFuncEnvironment { - DummyFuncEnvironment::new(&self.info) - } - - /// Get the type for the function at the given index. - pub fn get_func_type(&self, func_index: FuncIndex) -> TypeIndex { - self.info.functions[func_index].entity - } - - /// Return the number of imported functions within this `DummyEnvironment`. - pub fn get_num_func_imports(&self) -> usize { - self.info.imported_funcs.len() - } - - /// Return the name of the function, if a name for the function with - /// the corresponding index exists. - pub fn get_func_name(&self, func_index: FuncIndex) -> Option<&str> { - self.function_names.get(func_index).map(String::as_ref) - } -} - -/// The `FuncEnvironment` implementation for use by the `DummyEnvironment`. -pub struct DummyFuncEnvironment<'dummy_environment> { - /// This function environment's module info. - pub mod_info: &'dummy_environment DummyModuleInfo, - - /// Heaps we have created to implement Wasm linear memories. - pub heaps: PrimaryMap, - - /// Cranelift tables we have created to implement Wasm tables. - tables: SecondaryMap>, -} - -impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> { - /// Construct a new `DummyFuncEnvironment`. - pub fn new(mod_info: &'dummy_environment DummyModuleInfo) -> Self { - Self { - mod_info, - heaps: Default::default(), - tables: Default::default(), - } - } - - /// Create a signature for `sigidx` amended with a `vmctx` argument after - /// the standard wasm arguments. - pub fn vmctx_sig(&self, sigidx: TypeIndex) -> ir::Signature { - let mut sig = self.mod_info.signatures[sigidx].clone(); - sig.params.push(ir::AbiParam::special( - self.pointer_type(), - ir::ArgumentPurpose::VMContext, - )); - sig - } - - fn reference_type(&self) -> ir::Type { - self.pointer_type() - } - - fn ensure_table_exists(&mut self, func: &mut ir::Function, index: TableIndex) { - if self.tables[index].is_some() { - return; - } - - // Create a table whose base address is stored at `vmctx+0`. - let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); - let base_gv = func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: Offset32::new(0), - global_type: self.pointer_type(), - // When tables in wasm become "growable", revisit whether this can be readonly or not. - flags: ir::MemFlags::trusted().with_readonly(), - }); - - let table = &self.mod_info.tables[index].entity; - - let bound = if Some(table.minimum) == table.maximum { - TableSize::Static { - bound: table.minimum, - } - } else { - TableSize::Dynamic { - bound_gv: func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: Offset32::new(0), - global_type: I32, - flags: ir::MemFlags::trusted().with_readonly(), - }), - } - }; - - self.tables[index] = Some(TableData { - base_gv, - bound, - element_size: u32::from(self.pointer_bytes()) * 2, - }); - } -} - -impl<'dummy_environment> TypeConvert for DummyFuncEnvironment<'dummy_environment> { - fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType { - unimplemented!() - } -} - -impl<'dummy_environment> TargetEnvironment for DummyFuncEnvironment<'dummy_environment> { - fn target_config(&self) -> TargetFrontendConfig { - self.mod_info.config - } - - fn heap_access_spectre_mitigation(&self) -> bool { - false - } - - fn proof_carrying_code(&self) -> bool { - false - } -} - -impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> { - fn make_global( - &mut self, - func: &mut ir::Function, - index: GlobalIndex, - ) -> WasmResult { - // Just create a dummy `vmctx` global. - let offset = i32::try_from((index.index() * 8) + 8).unwrap().into(); - let vmctx = func.create_global_value(ir::GlobalValueData::VMContext {}); - Ok(GlobalVariable::Memory { - gv: vmctx, - offset, - ty: match self.mod_info.globals[index].entity.wasm_ty { - WasmValType::I32 => ir::types::I32, - WasmValType::I64 => ir::types::I64, - WasmValType::F32 => ir::types::F32, - WasmValType::F64 => ir::types::F64, - WasmValType::V128 => ir::types::I8X16, - WasmValType::Ref(_) => self.pointer_type(), - }, - }) - } - - fn heaps(&self) -> &PrimaryMap { - &self.heaps - } - - fn make_heap(&mut self, func: &mut ir::Function, _index: MemoryIndex) -> WasmResult { - // Create a static heap whose base address is stored at `vmctx+0`. - let addr = func.create_global_value(ir::GlobalValueData::VMContext); - let gv = func.create_global_value(ir::GlobalValueData::Load { - base: addr, - offset: Offset32::new(0), - global_type: self.pointer_type(), - flags: ir::MemFlags::trusted().with_readonly(), - }); - - Ok(self.heaps.push(HeapData { - base: gv, - min_size: 0, - max_size: None, - offset_guard_size: 0x8000_0000, - style: HeapStyle::Static { - bound: 0x1_0000_0000, - }, - index_type: I32, - memory_type: None, - })) - } - - fn make_indirect_sig( - &mut self, - func: &mut ir::Function, - index: TypeIndex, - ) -> WasmResult { - // A real implementation would probably change the calling convention and add `vmctx` and - // signature index arguments. - Ok(func.import_signature(self.vmctx_sig(index))) - } - - fn make_direct_func( - &mut self, - func: &mut ir::Function, - index: FuncIndex, - ) -> WasmResult { - let sigidx = self.mod_info.functions[index].entity; - // A real implementation would probably add a `vmctx` argument. - // And maybe attempt some signature de-duplication. - let signature = func.import_signature(self.vmctx_sig(sigidx)); - let name = - ir::ExternalName::User(func.declare_imported_user_function(ir::UserExternalName { - namespace: 0, - index: index.as_u32(), - })); - Ok(func.import_function(ir::ExtFuncData { - name, - signature, - colocated: false, - })) - } - - fn translate_call_indirect( - &mut self, - builder: &mut FunctionBuilder, - _table_index: TableIndex, - _sig_index: TypeIndex, - sig_ref: ir::SigRef, - callee: ir::Value, - call_args: &[ir::Value], - ) -> WasmResult> { - // Pass the current function's vmctx parameter on to the callee. - let vmctx = builder - .func - .special_param(ir::ArgumentPurpose::VMContext) - .expect("Missing vmctx parameter"); - - // The `callee` value is an index into a table of function pointers. - // Apparently, that table is stored at absolute address 0 in this dummy environment. - // TODO: Generate bounds checking code. - let ptr = self.pointer_type(); - let callee_offset = if ptr == I32 { - builder.ins().imul_imm(callee, 4) - } else { - let ext = builder.ins().uextend(I64, callee); - builder.ins().imul_imm(ext, 4) - }; - let mflags = ir::MemFlags::trusted(); - let func_ptr = builder.ins().load(ptr, mflags, callee_offset, 0); - - // Build a value list for the indirect call instruction containing the callee, call_args, - // and the vmctx parameter. - let mut args = ir::ValueList::default(); - args.push(func_ptr, &mut builder.func.dfg.value_lists); - args.extend(call_args.iter().cloned(), &mut builder.func.dfg.value_lists); - args.push(vmctx, &mut builder.func.dfg.value_lists); - - Ok(Some( - builder - .ins() - .CallIndirect(ir::Opcode::CallIndirect, INVALID, sig_ref, args) - .0, - )) - } - - fn translate_return_call_indirect( - &mut self, - _builder: &mut FunctionBuilder, - _table_index: TableIndex, - _sig_index: TypeIndex, - _sig_ref: ir::SigRef, - _callee: ir::Value, - _call_args: &[ir::Value], - ) -> WasmResult<()> { - unimplemented!() - } - - fn translate_return_call_ref( - &mut self, - _builder: &mut FunctionBuilder, - _sig_ref: ir::SigRef, - _callee: ir::Value, - _call_args: &[ir::Value], - ) -> WasmResult<()> { - unimplemented!() - } - - fn translate_call( - &mut self, - builder: &mut FunctionBuilder, - _callee_index: FuncIndex, - callee: ir::FuncRef, - call_args: &[ir::Value], - ) -> WasmResult { - // Pass the current function's vmctx parameter on to the callee. - let vmctx = builder - .func - .special_param(ir::ArgumentPurpose::VMContext) - .expect("Missing vmctx parameter"); - - // Build a value list for the call instruction containing the call_args and the vmctx - // parameter. - let mut args = ir::ValueList::default(); - args.extend(call_args.iter().cloned(), &mut builder.func.dfg.value_lists); - args.push(vmctx, &mut builder.func.dfg.value_lists); - - Ok(builder - .ins() - .Call(ir::Opcode::Call, INVALID, callee, args) - .0) - } - - fn translate_call_ref( - &mut self, - _builder: &mut FunctionBuilder, - _sig_ref: ir::SigRef, - _callee: ir::Value, - _call_args: &[ir::Value], - ) -> WasmResult { - todo!("Implement dummy translate_call_ref") - } - - fn translate_memory_grow( - &mut self, - mut pos: FuncCursor, - _index: MemoryIndex, - _heap: Heap, - _val: ir::Value, - ) -> WasmResult { - Ok(pos.ins().iconst(I32, -1i32 as u32 as i64)) - } - - fn translate_memory_size( - &mut self, - mut pos: FuncCursor, - _index: MemoryIndex, - _heap: Heap, - ) -> WasmResult { - Ok(pos.ins().iconst(I32, -1i32 as u32 as i64)) - } - - fn translate_memory_copy( - &mut self, - _pos: FuncCursor, - _src_index: MemoryIndex, - _src_heap: Heap, - _dst_index: MemoryIndex, - _dst_heap: Heap, - _dst: ir::Value, - _src: ir::Value, - _len: ir::Value, - ) -> WasmResult<()> { - Ok(()) - } - - fn translate_memory_fill( - &mut self, - _pos: FuncCursor, - _index: MemoryIndex, - _heap: Heap, - _dst: ir::Value, - _val: ir::Value, - _len: ir::Value, - ) -> WasmResult<()> { - Ok(()) - } - - fn translate_memory_init( - &mut self, - _pos: FuncCursor, - _index: MemoryIndex, - _heap: Heap, - _seg_index: u32, - _dst: ir::Value, - _src: ir::Value, - _len: ir::Value, - ) -> WasmResult<()> { - Ok(()) - } - - fn translate_data_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> { - Ok(()) - } - - fn translate_table_size( - &mut self, - mut pos: FuncCursor, - _index: TableIndex, - ) -> WasmResult { - Ok(pos.ins().iconst(I32, -1i32 as u32 as i64)) - } - - fn translate_table_grow( - &mut self, - mut pos: FuncCursor, - _table_index: TableIndex, - _delta: ir::Value, - _init_value: ir::Value, - ) -> WasmResult { - Ok(pos.ins().iconst(I32, -1i32 as u32 as i64)) - } - - fn translate_table_get( - &mut self, - builder: &mut FunctionBuilder, - table_index: TableIndex, - index: ir::Value, - ) -> WasmResult { - let pointer_type = self.pointer_type(); - self.ensure_table_exists(builder.func, table_index); - let table = self.tables[table_index].as_ref().unwrap(); - let (table_entry_addr, flags) = - table.prepare_table_addr(builder, index, pointer_type, true); - let value = builder - .ins() - .load(self.reference_type(), flags, table_entry_addr, 0); - Ok(value) - } - - fn translate_table_set( - &mut self, - builder: &mut FunctionBuilder, - table_index: TableIndex, - value: ir::Value, - index: ir::Value, - ) -> WasmResult<()> { - let pointer_type = self.pointer_type(); - self.ensure_table_exists(builder.func, table_index); - let table = self.tables[table_index].as_ref().unwrap(); - let (table_entry_addr, flags) = - table.prepare_table_addr(builder, index, pointer_type, true); - builder.ins().store(flags, value, table_entry_addr, 0); - Ok(()) - } - - fn translate_table_copy( - &mut self, - _pos: FuncCursor, - _dst_index: TableIndex, - _src_index: TableIndex, - _dst: ir::Value, - _src: ir::Value, - _len: ir::Value, - ) -> WasmResult<()> { - Ok(()) - } - - fn translate_table_fill( - &mut self, - _pos: FuncCursor, - _table_index: TableIndex, - _dst: ir::Value, - _val: ir::Value, - _len: ir::Value, - ) -> WasmResult<()> { - Ok(()) - } - - fn translate_table_init( - &mut self, - _pos: FuncCursor, - _seg_index: u32, - _table_index: TableIndex, - _dst: ir::Value, - _src: ir::Value, - _len: ir::Value, - ) -> WasmResult<()> { - Ok(()) - } - - fn translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> { - Ok(()) - } - - fn translate_ref_func( - &mut self, - mut pos: FuncCursor, - _func_index: FuncIndex, - ) -> WasmResult { - Ok(pos.ins().null(self.reference_type())) - } - - fn translate_custom_global_get( - &mut self, - mut pos: FuncCursor, - _global_index: GlobalIndex, - ) -> WasmResult { - Ok(pos.ins().iconst(I32, -1i32 as u32 as i64)) - } - - fn translate_custom_global_set( - &mut self, - _pos: FuncCursor, - _global_index: GlobalIndex, - _val: ir::Value, - ) -> WasmResult<()> { - Ok(()) - } - - fn translate_atomic_wait( - &mut self, - mut pos: FuncCursor, - _index: MemoryIndex, - _heap: Heap, - _addr: ir::Value, - _expected: ir::Value, - _timeout: ir::Value, - ) -> WasmResult { - Ok(pos.ins().iconst(I32, -1i32 as u32 as i64)) - } - - fn translate_atomic_notify( - &mut self, - mut pos: FuncCursor, - _index: MemoryIndex, - _heap: Heap, - _addr: ir::Value, - _count: ir::Value, - ) -> WasmResult { - Ok(pos.ins().iconst(I32, 0)) - } - - fn translate_ref_i31(&mut self, _pos: FuncCursor, _val: ir::Value) -> WasmResult { - Err(wasm_unsupported!("ref.i31")) - } - - fn translate_i31_get_s( - &mut self, - _pos: FuncCursor, - _i31ref: ir::Value, - ) -> WasmResult { - Err(wasm_unsupported!("i31.get_s")) - } - - fn translate_i31_get_u( - &mut self, - _pos: FuncCursor, - _i31ref: ir::Value, - ) -> WasmResult { - Err(wasm_unsupported!("i31.get_u")) - } -} - -impl TypeConvert for DummyEnvironment { - fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType { - unimplemented!() - } -} - -impl TargetEnvironment for DummyEnvironment { - fn target_config(&self) -> TargetFrontendConfig { - self.info.config - } - - fn heap_access_spectre_mitigation(&self) -> bool { - false - } - - fn proof_carrying_code(&self) -> bool { - false - } -} - -impl<'data> ModuleEnvironment<'data> for DummyEnvironment { - fn declare_type_func(&mut self, wasm: WasmFuncType) -> WasmResult<()> { - let mut sig = ir::Signature::new(CallConv::Fast); - let mut cvt = |ty: &WasmValType| { - ir::AbiParam::new(match ty { - WasmValType::I32 => ir::types::I32, - WasmValType::I64 => ir::types::I64, - WasmValType::F32 => ir::types::F32, - WasmValType::F64 => ir::types::F64, - WasmValType::V128 => ir::types::I8X16, - WasmValType::Ref(_) => self.pointer_type(), - }) - }; - sig.params.extend(wasm.params().iter().map(&mut cvt)); - sig.returns.extend(wasm.returns().iter().map(&mut cvt)); - self.info.signatures.push(sig); - Ok(()) - } - - fn declare_func_import( - &mut self, - index: TypeIndex, - module: &'data str, - field: &'data str, - ) -> WasmResult<()> { - assert_eq!( - self.info.functions.len(), - self.info.imported_funcs.len(), - "Imported functions must be declared first" - ); - self.info.functions.push(Exportable::new(index)); - self.info - .imported_funcs - .push((String::from(module), String::from(field))); - Ok(()) - } - - fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()> { - self.info.functions.push(Exportable::new(index)); - Ok(()) - } - - fn declare_global(&mut self, global: Global, _init: GlobalInit) -> WasmResult<()> { - self.info.globals.push(Exportable::new(global)); - Ok(()) - } - - fn declare_global_import( - &mut self, - global: Global, - module: &'data str, - field: &'data str, - ) -> WasmResult<()> { - self.info.globals.push(Exportable::new(global)); - self.info - .imported_globals - .push((String::from(module), String::from(field))); - Ok(()) - } - - fn declare_table(&mut self, table: Table) -> WasmResult<()> { - self.info.tables.push(Exportable::new(table)); - Ok(()) - } - - fn declare_table_import( - &mut self, - table: Table, - module: &'data str, - field: &'data str, - ) -> WasmResult<()> { - self.info.tables.push(Exportable::new(table)); - self.info - .imported_tables - .push((String::from(module), String::from(field))); - Ok(()) - } - - fn declare_table_elements( - &mut self, - _table_index: TableIndex, - _base: Option, - _offset: u32, - _elements: Box<[FuncIndex]>, - ) -> WasmResult<()> { - // We do nothing - Ok(()) - } - - fn declare_passive_element( - &mut self, - _elem_index: ElemIndex, - _segments: Box<[FuncIndex]>, - ) -> WasmResult<()> { - Ok(()) - } - - fn declare_passive_data( - &mut self, - _elem_index: DataIndex, - _segments: &'data [u8], - ) -> WasmResult<()> { - Ok(()) - } - - fn declare_memory(&mut self, memory: Memory) -> WasmResult<()> { - self.info.memories.push(Exportable::new(memory)); - Ok(()) - } - - fn declare_memory_import( - &mut self, - memory: Memory, - module: &'data str, - field: &'data str, - ) -> WasmResult<()> { - self.info.memories.push(Exportable::new(memory)); - self.info - .imported_memories - .push((String::from(module), String::from(field))); - Ok(()) - } - - fn declare_data_initialization( - &mut self, - _memory_index: MemoryIndex, - _base: Option, - _offset: u64, - _data: &'data [u8], - ) -> WasmResult<()> { - // We do nothing - Ok(()) - } - - fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()> { - self.info.functions[func_index] - .export_names - .push(String::from(name)); - Ok(()) - } - - fn declare_table_export( - &mut self, - table_index: TableIndex, - name: &'data str, - ) -> WasmResult<()> { - self.info.tables[table_index] - .export_names - .push(String::from(name)); - Ok(()) - } - - fn declare_memory_export( - &mut self, - memory_index: MemoryIndex, - name: &'data str, - ) -> WasmResult<()> { - self.info.memories[memory_index] - .export_names - .push(String::from(name)); - Ok(()) - } - - fn declare_global_export( - &mut self, - global_index: GlobalIndex, - name: &'data str, - ) -> WasmResult<()> { - self.info.globals[global_index] - .export_names - .push(String::from(name)); - Ok(()) - } - - fn declare_start_func(&mut self, func_index: FuncIndex) -> WasmResult<()> { - debug_assert!(self.info.start_func.is_none()); - self.info.start_func = Some(func_index); - Ok(()) - } - - fn define_function_body( - &mut self, - mut validator: FuncValidator, - body: FunctionBody<'data>, - ) -> WasmResult<()> { - self.func_bytecode_sizes - .push(body.get_binary_reader().bytes_remaining()); - let func = { - let mut func_environ = DummyFuncEnvironment::new(&self.info); - let func_index = - FuncIndex::new(self.get_num_func_imports() + self.info.function_bodies.len()); - - let sig = func_environ.vmctx_sig(self.get_func_type(func_index)); - let mut func = - ir::Function::with_name_signature(UserFuncName::user(0, func_index.as_u32()), sig); - - self.trans - .translate_body(&mut validator, body, &mut func, &mut func_environ)?; - func - }; - self.info.function_bodies.push(func); - Ok(()) - } - - fn declare_module_name(&mut self, name: &'data str) { - self.module_name = Some(String::from(name)); - } - - fn declare_func_name(&mut self, func_index: FuncIndex, name: &'data str) { - self.function_names[func_index] = String::from(name); - } - - fn wasm_features(&self) -> WasmFeatures { - WasmFeatures::default() - } -} diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index 60991c638065..f66de24c87d9 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -15,7 +15,7 @@ use crate::{ use cranelift_codegen::cursor::FuncCursor; use cranelift_codegen::ir::immediates::Offset32; use cranelift_codegen::ir::{self, InstBuilder, Type}; -use cranelift_codegen::isa::TargetFrontendConfig; +use cranelift_codegen::isa::{TargetFrontendConfig, TargetIsa}; use cranelift_entity::PrimaryMap; use cranelift_frontend::FunctionBuilder; use std::boxed::Box; @@ -511,10 +511,18 @@ pub trait FuncEnvironment: TargetEnvironment { fn translate_ref_i31(&mut self, pos: FuncCursor, val: ir::Value) -> WasmResult; /// Sign-extend an `i31ref` into an `i32`. - fn translate_i31_get_s(&mut self, pos: FuncCursor, i31ref: ir::Value) -> WasmResult; + fn translate_i31_get_s( + &mut self, + pos: &mut FunctionBuilder, + i31ref: ir::Value, + ) -> WasmResult; /// Zero-extend an `i31ref` into an `i32`. - fn translate_i31_get_u(&mut self, pos: FuncCursor, i31ref: ir::Value) -> WasmResult; + fn translate_i31_get_u( + &mut self, + pos: &mut FunctionBuilder, + i31ref: ir::Value, + ) -> WasmResult; /// Emit code at the beginning of every wasm loop. /// @@ -729,6 +737,101 @@ pub trait FuncEnvironment: TargetEnvironment { _mem_index: MemoryIndex, ) { } + + /// Optional hook for customizing how `trap` is lowered. + fn trap(&mut self, builder: &mut FunctionBuilder, code: ir::TrapCode) { + builder.ins().trap(code); + } + + /// Optional hook for customizing how `trapz` is lowered. + fn trapz(&mut self, builder: &mut FunctionBuilder, value: ir::Value, code: ir::TrapCode) { + builder.ins().trapz(value, code); + } + + /// Optional hook for customizing how `trapnz` is lowered. + fn trapnz(&mut self, builder: &mut FunctionBuilder, value: ir::Value, code: ir::TrapCode) { + builder.ins().trapnz(value, code); + } + + /// Optional hook for customizing how `uadd_overflow_trap` is lowered. + fn uadd_overflow_trap( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + code: ir::TrapCode, + ) -> ir::Value { + builder.ins().uadd_overflow_trap(lhs, rhs, code) + } + + /// Accesses the ISA that is being compiled for. + fn isa(&self) -> &dyn TargetIsa; + + /// Embedder-defined hook for indicating whether signals can be used to + /// indicate traps. + fn signals_based_traps(&self) -> bool { + true + } + + /// Optional hook for customizing `sdiv` instruction lowering. + fn translate_sdiv( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + builder.ins().sdiv(lhs, rhs) + } + + /// Optional hook for customizing `udiv` instruction lowering. + fn translate_udiv( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + builder.ins().udiv(lhs, rhs) + } + + /// Optional hook for customizing `srem` instruction lowering. + fn translate_srem( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + builder.ins().srem(lhs, rhs) + } + + /// Optional hook for customizing `urem` instruction lowering. + fn translate_urem( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + builder.ins().urem(lhs, rhs) + } + + /// Optional hook for customizing `fcvt_to_sint` instruction lowering. + fn translate_fcvt_to_sint( + &mut self, + builder: &mut FunctionBuilder, + ty: ir::Type, + val: ir::Value, + ) -> ir::Value { + builder.ins().fcvt_to_sint(ty, val) + } + + /// Optional hook for customizing `fcvt_to_uint` instruction lowering. + fn translate_fcvt_to_uint( + &mut self, + builder: &mut FunctionBuilder, + ty: ir::Type, + val: ir::Value, + ) -> ir::Value { + builder.ins().fcvt_to_uint(ty, val) + } } /// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the @@ -908,7 +1011,7 @@ pub trait ModuleEnvironment<'data>: TypeConvert { &mut self, table_index: TableIndex, base: Option, - offset: u32, + offset: u64, elements: Box<[FuncIndex]>, ) -> WasmResult<()>; diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs index e1700257c1b2..a622ae46dd64 100644 --- a/cranelift/wasm/src/sections_translator.rs +++ b/cranelift/wasm/src/sections_translator.rs @@ -14,7 +14,7 @@ use crate::{ TypeIndex, WasmError, WasmResult, }; use cranelift_entity::packed_option::ReservedValue; -use cranelift_entity::EntityRef; +use cranelift_entity::{EntityRef, Unsigned}; use std::boxed::Box; use std::vec::Vec; use wasmparser::{ @@ -191,7 +191,7 @@ pub fn parse_export_section<'data>( // The input has already been validated, so we should be able to // assume valid UTF-8 and use `from_utf8_unchecked` if performance // becomes a concern here. - let index = index as usize; + let index = usize::try_from(index)?; match *kind { ExternalKind::Func => environ.declare_func_export(FuncIndex::new(index), name)?, ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), name)?, @@ -258,7 +258,8 @@ pub fn parse_element_section<'data>( } => { let mut offset_expr_reader = offset_expr.get_binary_reader(); let (base, offset) = match offset_expr_reader.read_operator()? { - Operator::I32Const { value } => (None, value as u32), + Operator::I32Const { value } => (None, u64::from(value.unsigned())), + Operator::I64Const { value } => (None, value.unsigned()), Operator::GlobalGet { global_index } => { (Some(GlobalIndex::from_u32(global_index)), 0) } @@ -277,7 +278,7 @@ pub fn parse_element_section<'data>( )? } ElementKind::Passive => { - let index = ElemIndex::from_u32(index as u32); + let index = ElemIndex::from_u32(u32::try_from(index)?); environ.declare_passive_element(index, segments)?; } ElementKind::Declared => { @@ -308,8 +309,8 @@ pub fn parse_data_section<'data>( } => { let mut offset_expr_reader = offset_expr.get_binary_reader(); let (base, offset) = match offset_expr_reader.read_operator()? { - Operator::I32Const { value } => (None, value as u64), - Operator::I64Const { value } => (None, value as u64), + Operator::I32Const { value } => (None, u64::try_from(value)?), + Operator::I64Const { value } => (None, u64::try_from(value)?), Operator::GlobalGet { global_index } => { (Some(GlobalIndex::from_u32(global_index)), 0) } @@ -328,7 +329,7 @@ pub fn parse_data_section<'data>( )?; } DataKind::Passive => { - let index = DataIndex::from_u32(index as u32); + let index = DataIndex::from_u32(u32::try_from(index)?); environ.declare_passive_data(index, data)?; } } diff --git a/cranelift/wasm/src/table.rs b/cranelift/wasm/src/table.rs index bb5466670696..7d38924a09c9 100644 --- a/cranelift/wasm/src/table.rs +++ b/cranelift/wasm/src/table.rs @@ -1,5 +1,7 @@ +use crate::FuncEnvironment; use cranelift_codegen::cursor::FuncCursor; use cranelift_codegen::ir::{self, condcodes::IntCC, immediates::Imm64, InstBuilder}; +use cranelift_codegen::isa::TargetIsa; use cranelift_frontend::FunctionBuilder; /// Size of a WebAssembly table, in elements. @@ -8,7 +10,7 @@ pub enum TableSize { /// Non-resizable table. Static { /// Non-resizable tables have a constant size known at compile time. - bound: u32, + bound: u64, }, /// Resizable table. Dynamic { @@ -20,10 +22,21 @@ pub enum TableSize { impl TableSize { /// Get a CLIF value representing the current bounds of this table. - pub fn bound(&self, mut pos: FuncCursor, index_ty: ir::Type) -> ir::Value { + pub fn bound(&self, isa: &dyn TargetIsa, mut pos: FuncCursor, index_ty: ir::Type) -> ir::Value { match *self { - TableSize::Static { bound } => pos.ins().iconst(index_ty, Imm64::new(i64::from(bound))), - TableSize::Dynamic { bound_gv } => pos.ins().global_value(index_ty, bound_gv), + // Instead of `i64::try_from(bound)`, here we just want to direcly interpret `bound` as an i64. + TableSize::Static { bound } => pos.ins().iconst(index_ty, Imm64::new(bound as i64)), + TableSize::Dynamic { bound_gv } => { + let ty = pos.func.global_values[bound_gv].global_type(isa); + let gv = pos.ins().global_value(ty, bound_gv); + if index_ty == ty { + gv + } else if index_ty.bytes() < ty.bytes() { + pos.ins().ireduce(index_ty, gv) + } else { + pos.ins().uextend(index_ty, gv) + } + } } } } @@ -46,23 +59,23 @@ impl TableData { /// given index within this table. pub fn prepare_table_addr( &self, + env: &mut dyn FuncEnvironment, pos: &mut FunctionBuilder, mut index: ir::Value, - addr_ty: ir::Type, - enable_table_access_spectre_mitigation: bool, ) -> (ir::Value, ir::MemFlags) { let index_ty = pos.func.dfg.value_type(index); + let addr_ty = env.pointer_type(); // Start with the bounds check. Trap if `index + 1 > bound`. - let bound = self.bound.bound(pos.cursor(), index_ty); + let bound = self.bound.bound(env.isa(), pos.cursor(), index_ty); // `index > bound - 1` is the same as `index >= bound`. let oob = pos .ins() .icmp(IntCC::UnsignedGreaterThanOrEqual, index, bound); - if !enable_table_access_spectre_mitigation { - pos.ins().trapnz(oob, ir::TrapCode::TableOutOfBounds); + if !env.isa().flags().enable_table_access_spectre_mitigation() { + env.trapnz(pos, oob, ir::TrapCode::TableOutOfBounds); } // Convert `index` to `addr_ty`. @@ -88,7 +101,7 @@ impl TableData { let base_flags = ir::MemFlags::new() .with_aligned() .with_alias_region(Some(ir::AliasRegion::Table)); - if enable_table_access_spectre_mitigation { + if env.isa().flags().enable_table_access_spectre_mitigation() { // Short-circuit the computed table element address to a null pointer // when out-of-bounds. The consumer of this address will trap when // trying to access it. diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index 0cbae0c9738f..30b35b07de92 100644 --- a/crates/c-api/include/wasmtime.h +++ b/crates/c-api/include/wasmtime.h @@ -206,11 +206,11 @@ /** * \brief Wasmtime version string. */ -#define WASMTIME_VERSION "25.0.0" +#define WASMTIME_VERSION "26.0.0" /** * \brief Wasmtime major version number. */ -#define WASMTIME_VERSION_MAJOR 25 +#define WASMTIME_VERSION_MAJOR 26 /** * \brief Wasmtime minor version number. */ diff --git a/crates/c-api/include/wasmtime/table.h b/crates/c-api/include/wasmtime/table.h index 9ec8f3796c80..7a648691ca2a 100644 --- a/crates/c-api/include/wasmtime/table.h +++ b/crates/c-api/include/wasmtime/table.h @@ -57,7 +57,7 @@ wasmtime_table_type(const wasmtime_context_t *store, */ WASM_API_EXTERN bool wasmtime_table_get(wasmtime_context_t *store, const wasmtime_table_t *table, - uint32_t index, wasmtime_val_t *val); + uint64_t index, wasmtime_val_t *val); /** * \brief Sets a value in a table. @@ -74,12 +74,12 @@ WASM_API_EXTERN bool wasmtime_table_get(wasmtime_context_t *store, */ WASM_API_EXTERN wasmtime_error_t * wasmtime_table_set(wasmtime_context_t *store, const wasmtime_table_t *table, - uint32_t index, const wasmtime_val_t *value); + uint64_t index, const wasmtime_val_t *value); /** * \brief Returns the size, in elements, of the specified table */ -WASM_API_EXTERN uint32_t wasmtime_table_size(const wasmtime_context_t *store, +WASM_API_EXTERN uint64_t wasmtime_table_size(const wasmtime_context_t *store, const wasmtime_table_t *table); /** @@ -101,8 +101,8 @@ WASM_API_EXTERN uint32_t wasmtime_table_size(const wasmtime_context_t *store, */ WASM_API_EXTERN wasmtime_error_t * wasmtime_table_grow(wasmtime_context_t *store, const wasmtime_table_t *table, - uint32_t delta, const wasmtime_val_t *init, - uint32_t *prev_size); + uint64_t delta, const wasmtime_val_t *init, + uint64_t *prev_size); #ifdef __cplusplus } // extern "C" diff --git a/crates/c-api/src/store.rs b/crates/c-api/src/store.rs index bffe3c9a3463..90a7397db786 100644 --- a/crates/c-api/src/store.rs +++ b/crates/c-api/src/store.rs @@ -180,7 +180,7 @@ pub extern "C" fn wasmtime_store_limiter( limiter = limiter.memory_size(memory_size as usize); } if table_elements >= 0 { - limiter = limiter.table_elements(table_elements as u32); + limiter = limiter.table_elements(table_elements as usize); } if instances >= 0 { limiter = limiter.instances(instances as usize); diff --git a/crates/c-api/src/table.rs b/crates/c-api/src/table.rs index d7ff324580b8..63f451c14512 100644 --- a/crates/c-api/src/table.rs +++ b/crates/c-api/src/table.rs @@ -67,7 +67,7 @@ pub unsafe extern "C" fn wasm_table_get( index: wasm_table_size_t, ) -> Option> { let table = t.table(); - let r = table.get(t.ext.store.context_mut(), index)?; + let r = table.get(t.ext.store.context_mut(), u64::from(index))?; wasm_ref_t::new(r) } @@ -79,14 +79,16 @@ pub unsafe extern "C" fn wasm_table_set( ) -> bool { let table = t.table(); let val = option_wasm_ref_t_to_ref(r, &table.ty(t.ext.store.context())); - table.set(t.ext.store.context_mut(), index, val).is_ok() + table + .set(t.ext.store.context_mut(), u64::from(index), val) + .is_ok() } #[no_mangle] pub unsafe extern "C" fn wasm_table_size(t: &wasm_table_t) -> wasm_table_size_t { let table = t.table(); let store = t.ext.store.context(); - table.size(&store) + u32::try_from(table.size(&store)).unwrap() } #[no_mangle] @@ -97,7 +99,9 @@ pub unsafe extern "C" fn wasm_table_grow( ) -> bool { let table = t.table(); let init = option_wasm_ref_t_to_ref(init, &table.ty(t.ext.store.context())); - table.grow(t.ext.store.context_mut(), delta, init).is_ok() + table + .grow(t.ext.store.context_mut(), u64::from(delta), init) + .is_ok() } #[no_mangle] @@ -139,7 +143,7 @@ pub unsafe extern "C" fn wasmtime_table_type( pub extern "C" fn wasmtime_table_get( store: WasmtimeStoreContextMut<'_>, table: &Table, - index: u32, + index: u64, ret: &mut MaybeUninit, ) -> bool { let mut scope = RootScope::new(store); @@ -156,7 +160,7 @@ pub extern "C" fn wasmtime_table_get( pub unsafe extern "C" fn wasmtime_table_set( mut store: WasmtimeStoreContextMut<'_>, table: &Table, - index: u32, + index: u64, val: &wasmtime_val_t, ) -> Option> { let mut scope = RootScope::new(&mut store); @@ -170,7 +174,7 @@ pub unsafe extern "C" fn wasmtime_table_set( } #[no_mangle] -pub extern "C" fn wasmtime_table_size(store: WasmtimeStoreContext<'_>, table: &Table) -> u32 { +pub extern "C" fn wasmtime_table_size(store: WasmtimeStoreContext<'_>, table: &Table) -> u64 { table.size(store) } @@ -178,9 +182,9 @@ pub extern "C" fn wasmtime_table_size(store: WasmtimeStoreContext<'_>, table: &T pub unsafe extern "C" fn wasmtime_table_grow( mut store: WasmtimeStoreContextMut<'_>, table: &Table, - delta: u32, + delta: u64, val: &wasmtime_val_t, - prev_size: &mut u32, + prev_size: &mut u64, ) -> Option> { let mut scope = RootScope::new(&mut store); handle_result( diff --git a/crates/c-api/src/types/table.rs b/crates/c-api/src/types/table.rs index a31b5ef10720..0f0a87e70de8 100644 --- a/crates/c-api/src/types/table.rs +++ b/crates/c-api/src/types/table.rs @@ -74,8 +74,8 @@ pub extern "C" fn wasm_tabletype_element(tt: &wasm_tabletype_t) -> &wasm_valtype pub extern "C" fn wasm_tabletype_limits(tt: &wasm_tabletype_t) -> &wasm_limits_t { let tt = tt.ty(); tt.limits_cache.get_or_init(|| wasm_limits_t { - min: tt.ty.minimum(), - max: tt.ty.maximum().unwrap_or(u32::max_value()), + min: u32::try_from(tt.ty.minimum()).unwrap(), + max: u32::try_from(tt.ty.maximum().unwrap_or(u64::from(u32::MAX))).unwrap(), }) } diff --git a/crates/cli-flags/src/lib.rs b/crates/cli-flags/src/lib.rs index f309ca5d17c4..6d74ec0a9268 100644 --- a/crates/cli-flags/src/lib.rs +++ b/crates/cli-flags/src/lib.rs @@ -118,11 +118,14 @@ wasmtime_option_group! { /// The maximum table elements for any table defined in a module when /// using the pooling allocator. - pub pooling_table_elements: Option, + pub pooling_table_elements: Option, /// The maximum size, in bytes, allocated for a core instance's metadata /// when using the pooling allocator. pub pooling_max_core_instance_size: Option, + + /// Enable or disable the use of host signal handlers for traps. + pub signals_based_traps: Option, } enum Optimize { @@ -215,7 +218,7 @@ wasmtime_option_group! { /// WebAssembly modules to return -1 and fail. pub max_memory_size: Option, /// Maximum size, in table elements, that a table is allowed to reach. - pub max_table_elements: Option, + pub max_table_elements: Option, /// Maximum number of WebAssembly instances allowed to be created. pub max_instances: Option, /// Maximum number of WebAssembly tables allowed to be created. @@ -603,6 +606,9 @@ impl CommonOptions { if let Some(enable) = self.opts.memory_init_cow { config.memory_init_cow(enable); } + if let Some(enable) = self.opts.signals_based_traps { + config.signals_based_traps(enable); + } if let Some(wasmfx_stack_size) = self.wasm.wasmfx_stack_size { config.wasmfx_stack_size(wasmfx_stack_size); diff --git a/crates/component-macro/tests/expanded/char_async.rs b/crates/component-macro/tests/expanded/char_async.rs index 6fbcfca5517b..e2bb10590177 100644 --- a/crates/component-macro/tests/expanded/char_async.rs +++ b/crates/component-macro/tests/expanded/char_async.rs @@ -225,19 +225,23 @@ pub mod foo { move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (char,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::take_char(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::take_char(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "return-char", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_char(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_char(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/conventions_async.rs b/crates/component-macro/tests/expanded/conventions_async.rs index e03bae3f1012..f591169d80bf 100644 --- a/crates/component-macro/tests/expanded/conventions_async.rs +++ b/crates/component-macro/tests/expanded/conventions_async.rs @@ -270,102 +270,126 @@ pub mod foo { let mut inst = linker.instance("foo:foo/conventions")?; inst.func_wrap_async( "kebab-case", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::kebab_case(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::kebab_case(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "foo", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (LudicrousSpeed,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::foo(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::foo(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "function-with-dashes", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::function_with_dashes(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::function_with_dashes(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "function-with-no-weird-characters", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::function_with_no_weird_characters(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::function_with_no_weird_characters(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "apple", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::apple(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::apple(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "apple-pear", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::apple_pear(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::apple_pear(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "apple-pear-grape", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::apple_pear_grape(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::apple_pear_grape(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a0", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a0(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a0(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "is-XML", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::is_xml(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::is_xml(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "explicit", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::explicit(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::explicit(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "explicit-kebab", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::explicit_kebab(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::explicit_kebab(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "bool", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::bool(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::bool(host).await; + Ok(r) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/dead-code_async.rs b/crates/component-macro/tests/expanded/dead-code_async.rs index ab2ce33833d4..9ae5d387835d 100644 --- a/crates/component-macro/tests/expanded/dead-code_async.rs +++ b/crates/component-macro/tests/expanded/dead-code_async.rs @@ -228,11 +228,13 @@ pub mod a { let mut inst = linker.instance("a:b/interface-with-live-type")?; inst.func_wrap_async( "f", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::f(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::f(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/direct-import_async.rs b/crates/component-macro/tests/expanded/direct-import_async.rs index 59ee3fc7c68a..3eb3b163154f 100644 --- a/crates/component-macro/tests/expanded/direct-import_async.rs +++ b/crates/component-macro/tests/expanded/direct-import_async.rs @@ -194,11 +194,13 @@ const _: () = { linker .func_wrap_async( "foo", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = FooImports::foo(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = FooImports::foo(host).await; + Ok(r) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/flags_async.rs b/crates/component-macro/tests/expanded/flags_async.rs index 4ac5814dab67..d7f9786d0d75 100644 --- a/crates/component-macro/tests/expanded/flags_async.rs +++ b/crates/component-macro/tests/expanded/flags_async.rs @@ -342,77 +342,91 @@ pub mod foo { move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Flag1,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::roundtrip_flag1(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::roundtrip_flag1(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "roundtrip-flag2", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Flag2,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::roundtrip_flag2(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::roundtrip_flag2(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "roundtrip-flag4", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Flag4,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::roundtrip_flag4(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::roundtrip_flag4(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "roundtrip-flag8", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Flag8,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::roundtrip_flag8(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::roundtrip_flag8(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "roundtrip-flag16", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Flag16,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::roundtrip_flag16(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::roundtrip_flag16(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "roundtrip-flag32", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Flag32,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::roundtrip_flag32(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::roundtrip_flag32(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "roundtrip-flag64", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Flag64,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::roundtrip_flag64(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::roundtrip_flag64(host, arg0).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/floats_async.rs b/crates/component-macro/tests/expanded/floats_async.rs index 9747e1cb6eab..b6443832625f 100644 --- a/crates/component-macro/tests/expanded/floats_async.rs +++ b/crates/component-macro/tests/expanded/floats_async.rs @@ -222,35 +222,43 @@ pub mod foo { let mut inst = linker.instance("foo:foo/floats")?; inst.func_wrap_async( "float32-param", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (f32,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::float32_param(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (f32,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::float32_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "float64-param", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (f64,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::float64_param(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (f64,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::float64_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "float32-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::float32_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::float32_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "float64-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::float64_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::float64_result(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/integers_async.rs b/crates/component-macro/tests/expanded/integers_async.rs index 3b6c21f7ce21..e0dc621675bb 100644 --- a/crates/component-macro/tests/expanded/integers_async.rs +++ b/crates/component-macro/tests/expanded/integers_async.rs @@ -246,67 +246,83 @@ pub mod foo { let mut inst = linker.instance("foo:foo/integers")?; inst.func_wrap_async( "a1", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u8,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a1(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u8,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a1(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a2", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i8,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a2(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i8,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a2(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a3", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u16,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a3(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u16,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a3(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a4", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i16,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a4(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i16,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a4(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a5", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u32,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a5(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u32,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a5(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a6", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i32,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a6(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i32,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a6(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a7", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u64,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a7(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u64,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a7(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a8", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i64,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a8(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (i64,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a8(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "a9", @@ -322,94 +338,114 @@ pub mod foo { arg6, arg7, ): (u8, i8, u16, i16, u32, i32, u64, i64)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a9( - host, - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - arg6, - arg7, - ) - .await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a9( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + ) + .await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "r1", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r1(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r1(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "r2", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r2(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r2(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "r3", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r3(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r3(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "r4", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r4(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r4(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "r5", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r5(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r5(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "r6", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r6(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r6(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "r7", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r7(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r7(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "r8", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::r8(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::r8(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "pair-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::pair_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::pair_ret(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/lists_async.rs b/crates/component-macro/tests/expanded/lists_async.rs index 63d0fd7ff69f..141726cecaa1 100644 --- a/crates/component-macro/tests/expanded/lists_async.rs +++ b/crates/component-macro/tests/expanded/lists_async.rs @@ -518,201 +518,243 @@ pub mod foo { move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u8_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u8_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-u16-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u16_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u16_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-u32-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u32_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u32_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-u64-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u64_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u64_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-s8-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s8_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s8_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-s16-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s16_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s16_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-s32-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s32_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s32_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-s64-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s64_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s64_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-float32-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_float32_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_float32_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-float64-param", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_float64_param(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_float64_param(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-u8-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u8_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u8_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-u16-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u16_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u16_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-u32-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u32_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u32_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-u64-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_u64_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_u64_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-s8-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s8_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s8_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-s16-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s16_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s16_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-s32-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s32_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s32_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-s64-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_s64_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_s64_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-float32-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_float32_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_float32_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-float64-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_float64_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_float64_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "tuple-list", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec<(u8, i8)>,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::tuple_list(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::tuple_list(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "string-list-arg", @@ -725,19 +767,23 @@ pub mod foo { wasmtime::component::__internal::String, >, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::string_list_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::string_list_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "string-list-ret", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::string_list_ret(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::string_list_ret(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "tuple-string-list", @@ -750,11 +796,13 @@ pub mod foo { (u8, wasmtime::component::__internal::String), >, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::tuple_string_list(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::tuple_string_list(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "string-list", @@ -767,55 +815,65 @@ pub mod foo { wasmtime::component::__internal::String, >, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::string_list(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::string_list(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "record-list", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::record_list(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::record_list(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "record-list-reverse", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::record_list_reverse(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::record_list_reverse(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "variant-list", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::variant_list(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::variant_list(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "load-store-everything", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (LoadStoreAllSizes,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::load_store_everything(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::load_store_everything(host, arg0).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/many-arguments_async.rs b/crates/component-macro/tests/expanded/many-arguments_async.rs index 2411593f3fab..3a55a6565f58 100644 --- a/crates/component-macro/tests/expanded/many-arguments_async.rs +++ b/crates/component-macro/tests/expanded/many-arguments_async.rs @@ -356,41 +356,45 @@ pub mod foo { u64, u64, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::many_args( - host, - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - arg6, - arg7, - arg8, - arg9, - arg10, - arg11, - arg12, - arg13, - arg14, - arg15, - ) - .await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::many_args( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + ) + .await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "big-argument", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (BigStruct,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::big_argument(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::big_argument(host, arg0).await; + Ok(r) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/multi-return_async.rs b/crates/component-macro/tests/expanded/multi-return_async.rs index 77975ff6cb3d..d0c44c782757 100644 --- a/crates/component-macro/tests/expanded/multi-return_async.rs +++ b/crates/component-macro/tests/expanded/multi-return_async.rs @@ -225,43 +225,53 @@ pub mod foo { let mut inst = linker.instance("foo:foo/multi-return")?; inst.func_wrap_async( "mra", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::mra(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::mra(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "mrb", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::mrb(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::mrb(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "mrc", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::mrc(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::mrc(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "mrd", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::mrd(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::mrd(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "mre", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::mre(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::mre(host).await; + Ok(r) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/multiversion_async.rs b/crates/component-macro/tests/expanded/multiversion_async.rs index 08edeb34c3a7..9d730e2f643c 100644 --- a/crates/component-macro/tests/expanded/multiversion_async.rs +++ b/crates/component-macro/tests/expanded/multiversion_async.rs @@ -237,11 +237,13 @@ pub mod my { let mut inst = linker.instance("my:dep/a@0.1.0")?; inst.func_wrap_async( "x", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::x(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::x(host).await; + Ok(r) + }) + }, )?; Ok(()) } @@ -294,11 +296,13 @@ pub mod my { let mut inst = linker.instance("my:dep/a@0.2.0")?; inst.func_wrap_async( "x", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::x(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::x(host).await; + Ok(r) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/records_async.rs b/crates/component-macro/tests/expanded/records_async.rs index 287af7c19a78..a7c2e82c405c 100644 --- a/crates/component-macro/tests/expanded/records_async.rs +++ b/crates/component-macro/tests/expanded/records_async.rs @@ -378,106 +378,128 @@ pub mod foo { move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): ((char, u32),)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::tuple_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::tuple_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "tuple-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::tuple_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::tuple_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "empty-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Empty,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::empty_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::empty_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "empty-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::empty_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::empty_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "scalar-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Scalars,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::scalar_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::scalar_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "scalar-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::scalar_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::scalar_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "flags-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (ReallyFlags,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::flags_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::flags_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "flags-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::flags_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::flags_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "aggregate-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Aggregates,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::aggregate_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::aggregate_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "aggregate-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::aggregate_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::aggregate_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "typedef-inout", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (TupleTypedef2,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::typedef_inout(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::typedef_inout(host, arg0).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/rename_async.rs b/crates/component-macro/tests/expanded/rename_async.rs index 6d8de01759a5..e1966b08dc86 100644 --- a/crates/component-macro/tests/expanded/rename_async.rs +++ b/crates/component-macro/tests/expanded/rename_async.rs @@ -258,11 +258,13 @@ pub mod foo { let mut inst = linker.instance("foo:foo/red")?; inst.func_wrap_async( "foo", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::foo(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::foo(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/resources-import_async.rs b/crates/component-macro/tests/expanded/resources-import_async.rs index 1b8424df1eef..b54d0c283fdf 100644 --- a/crates/component-macro/tests/expanded/resources-import_async.rs +++ b/crates/component-macro/tests/expanded/resources-import_async.rs @@ -277,11 +277,13 @@ const _: () = { linker .func_wrap_async( "[constructor]world-resource", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = HostWorldResource::new(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = HostWorldResource::new(host).await; + Ok((r,)) + }) + }, )?; linker .func_wrap_async( @@ -289,29 +291,35 @@ const _: () = { move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::Resource,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = HostWorldResource::foo(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = HostWorldResource::foo(host, arg0).await; + Ok(r) + }) + }, )?; linker .func_wrap_async( "[static]world-resource.static-foo", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = HostWorldResource::static_foo(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = HostWorldResource::static_foo(host).await; + Ok(r) + }) + }, )?; linker .func_wrap_async( "some-world-func", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = TheWorldImports::some_world_func(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = TheWorldImports::some_world_func(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } @@ -557,150 +565,180 @@ pub mod foo { )?; inst.func_wrap_async( "[constructor]bar", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = HostBar::new(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = HostBar::new(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "[static]bar.static-a", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = HostBar::static_a(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = HostBar::static_a(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "[method]bar.method-a", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::Resource,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = HostBar::method_a(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = HostBar::method_a(host, arg0).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "bar-own-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::Resource,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::bar_own_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::bar_own_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "bar-borrow-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::Resource,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::bar_borrow_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::bar_borrow_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "bar-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::bar_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::bar_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "tuple-own-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): ((wasmtime::component::Resource, u32),)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::tuple_own_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::tuple_own_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "tuple-borrow-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): ((wasmtime::component::Resource, u32),)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::tuple_borrow_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::tuple_borrow_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "tuple-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::tuple_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::tuple_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "option-own-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Option>,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::option_own_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::option_own_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "option-borrow-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Option>,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::option_borrow_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::option_borrow_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "option-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::option_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::option_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "result-own-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Result, ()>,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::result_own_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::result_own_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "result-borrow-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Result, ()>,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::result_borrow_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::result_borrow_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "result-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::result_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::result_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "list-own-arg", @@ -713,11 +751,13 @@ pub mod foo { wasmtime::component::Resource, >, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_own_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_own_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-borrow-arg", @@ -730,60 +770,72 @@ pub mod foo { wasmtime::component::Resource, >, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_borrow_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_borrow_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "list-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::list_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::list_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "record-own-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (NestedOwn,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::record_own_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::record_own_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "record-borrow-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (NestedBorrow,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::record_borrow_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::record_borrow_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "record-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::record_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::record_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "func-with-handle-typedef", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (SomeHandle,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::func_with_handle_typedef(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::func_with_handle_typedef(host, arg0).await; + Ok(r) + }) + }, )?; Ok(()) } @@ -1088,11 +1140,13 @@ pub mod foo { let mut inst = linker.instance("foo:foo/long-use-chain4")?; inst.func_wrap_async( "foo", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::foo(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::foo(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/share-types_async.rs b/crates/component-macro/tests/expanded/share-types_async.rs index 09461c453bc2..a622e2d7eb80 100644 --- a/crates/component-macro/tests/expanded/share-types_async.rs +++ b/crates/component-macro/tests/expanded/share-types_async.rs @@ -311,11 +311,13 @@ pub mod http_fetch { let mut inst = linker.instance("http-fetch")?; inst.func_wrap_async( "fetch-request", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Request,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::fetch_request(host, arg0).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Request,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::fetch_request(host, arg0).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/simple-functions_async.rs b/crates/component-macro/tests/expanded/simple-functions_async.rs index 5d3da65402a9..eb10075d88c8 100644 --- a/crates/component-macro/tests/expanded/simple-functions_async.rs +++ b/crates/component-macro/tests/expanded/simple-functions_async.rs @@ -224,57 +224,69 @@ pub mod foo { let mut inst = linker.instance("foo:foo/simple")?; inst.func_wrap_async( "f1", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::f1(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::f1(host).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "f2", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u32,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::f2(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (u32,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::f2(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "f3", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0, arg1): (u32, u32)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::f3(host, arg0, arg1).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::f3(host, arg0, arg1).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "f4", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::f4(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::f4(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "f5", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::f5(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::f5(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "f6", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0, arg1, arg2): (u32, u32, u32)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::f6(host, arg0, arg1, arg2).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::f6(host, arg0, arg1, arg2).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/simple-lists_async.rs b/crates/component-macro/tests/expanded/simple-lists_async.rs index ad713fdbd19f..e04e3e3299ff 100644 --- a/crates/component-macro/tests/expanded/simple-lists_async.rs +++ b/crates/component-macro/tests/expanded/simple-lists_async.rs @@ -246,19 +246,23 @@ pub mod foo { move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::Vec,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::simple_list1(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::simple_list1(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "simple-list2", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::simple_list2(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::simple_list2(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "simple-list3", @@ -271,11 +275,13 @@ pub mod foo { wasmtime::component::__internal::Vec, wasmtime::component::__internal::Vec, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::simple_list3(host, arg0, arg1).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::simple_list3(host, arg0, arg1).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "simple-list4", @@ -288,11 +294,13 @@ pub mod foo { wasmtime::component::__internal::Vec, >, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::simple_list4(host, arg0).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::simple_list4(host, arg0).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/simple-wasi_async.rs b/crates/component-macro/tests/expanded/simple-wasi_async.rs index 3cb43fd26d6d..21f0e82575b3 100644 --- a/crates/component-macro/tests/expanded/simple-wasi_async.rs +++ b/crates/component-macro/tests/expanded/simple-wasi_async.rs @@ -269,19 +269,23 @@ pub mod foo { let mut inst = linker.instance("foo:foo/wasi-filesystem")?; inst.func_wrap_async( "create-directory-at", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::create_directory_at(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::create_directory_at(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "stat", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::stat(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::stat(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/small-anonymous_async.rs b/crates/component-macro/tests/expanded/small-anonymous_async.rs index 6fdeda81a976..94a45355742e 100644 --- a/crates/component-macro/tests/expanded/small-anonymous_async.rs +++ b/crates/component-macro/tests/expanded/small-anonymous_async.rs @@ -266,11 +266,13 @@ pub mod foo { let mut inst = linker.instance("foo:foo/anon")?; inst.func_wrap_async( "option-test", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::option_test(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::option_test(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/smoke_async.rs b/crates/component-macro/tests/expanded/smoke_async.rs index b826b5134ffd..bfc70a8646fb 100644 --- a/crates/component-macro/tests/expanded/smoke_async.rs +++ b/crates/component-macro/tests/expanded/smoke_async.rs @@ -204,11 +204,13 @@ pub mod imports { let mut inst = linker.instance("imports")?; inst.func_wrap_async( "y", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::y(host).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::y(host).await; + Ok(r) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/strings_async.rs b/crates/component-macro/tests/expanded/strings_async.rs index 63a20c32437d..a597bb7f52ac 100644 --- a/crates/component-macro/tests/expanded/strings_async.rs +++ b/crates/component-macro/tests/expanded/strings_async.rs @@ -228,19 +228,23 @@ pub mod foo { move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (wasmtime::component::__internal::String,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "b", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::b(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::b(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "c", @@ -253,11 +257,13 @@ pub mod foo { wasmtime::component::__internal::String, wasmtime::component::__internal::String, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::c(host, arg0, arg1).await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::c(host, arg0, arg1).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/unversioned-foo_async.rs b/crates/component-macro/tests/expanded/unversioned-foo_async.rs index 05fe578c832a..fc83094285b6 100644 --- a/crates/component-macro/tests/expanded/unversioned-foo_async.rs +++ b/crates/component-macro/tests/expanded/unversioned-foo_async.rs @@ -234,11 +234,13 @@ pub mod foo { let mut inst = linker.instance("foo:foo/a")?; inst.func_wrap_async( "g", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::g(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::g(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/use-paths_async.rs b/crates/component-macro/tests/expanded/use-paths_async.rs index 71860e460cef..0aaae7b509aa 100644 --- a/crates/component-macro/tests/expanded/use-paths_async.rs +++ b/crates/component-macro/tests/expanded/use-paths_async.rs @@ -225,11 +225,13 @@ pub mod foo { let mut inst = linker.instance("foo:foo/a")?; inst.func_wrap_async( "a", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } @@ -285,11 +287,13 @@ pub mod foo { let mut inst = linker.instance("foo:foo/b")?; inst.func_wrap_async( "a", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } @@ -345,11 +349,13 @@ pub mod foo { let mut inst = linker.instance("foo:foo/c")?; inst.func_wrap_async( "a", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::a(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::a(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } @@ -407,11 +413,13 @@ pub mod d { let mut inst = linker.instance("d")?; inst.func_wrap_async( "b", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::b(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::b(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/component-macro/tests/expanded/variants_async.rs b/crates/component-macro/tests/expanded/variants_async.rs index e329d7d3b8ec..36cf76daa580 100644 --- a/crates/component-macro/tests/expanded/variants_async.rs +++ b/crates/component-macro/tests/expanded/variants_async.rs @@ -560,54 +560,66 @@ pub mod foo { let mut inst = linker.instance("foo:foo/variants")?; inst.func_wrap_async( "e1-arg", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (E1,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::e1_arg(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (E1,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::e1_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "e1-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::e1_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::e1_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "v1-arg", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (V1,)| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::v1_arg(host, arg0).await; - Ok(r) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (V1,)| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::v1_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "v1-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::v1_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::v1_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "bool-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (bool,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::bool_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::bool_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "bool-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::bool_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::bool_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "option-arg", @@ -628,28 +640,32 @@ pub mod foo { Option, Option>, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::option_arg( - host, - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - ) - .await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::option_arg( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ) + .await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "option-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::option_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::option_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "casts", @@ -663,12 +679,14 @@ pub mod foo { arg4, arg5, ): (Casts1, Casts2, Casts3, Casts4, Casts5, Casts6)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::casts(host, arg0, arg1, arg2, arg3, arg4, arg5) - .await; - Ok((r,)) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::casts(host, arg0, arg1, arg2, arg3, arg4, arg5) + .await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "result-arg", @@ -692,119 +710,145 @@ pub mod foo { wasmtime::component::__internal::Vec, >, )| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::result_arg( - host, - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - ) - .await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::result_arg( + host, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + ) + .await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "result-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::result_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::result_result(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-result-sugar", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_result_sugar(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_result_sugar(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-result-sugar2", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_result_sugar2(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_result_sugar2(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-result-sugar3", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_result_sugar3(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_result_sugar3(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-result-sugar4", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_result_sugar4(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_result_sugar4(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-option-sugar", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_option_sugar(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_option_sugar(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-option-sugar2", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_option_sugar2(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_option_sugar2(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "result-simple", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::result_simple(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::result_simple(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "is-clone-arg", move | mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (IsClone,)| - wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::is_clone_arg(host, arg0).await; - Ok(r) - }), + { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::is_clone_arg(host, arg0).await; + Ok(r) + }) + }, )?; inst.func_wrap_async( "is-clone-return", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::is_clone_return(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::is_clone_return(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-named-option", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_named_option(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_named_option(host).await; + Ok((r,)) + }) + }, )?; inst.func_wrap_async( "return-named-result", - move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| wasmtime::component::__internal::Box::new(async move { - let host = &mut host_getter(caller.data_mut()); - let r = Host::return_named_result(host).await; - Ok((r,)) - }), + move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| { + wasmtime::component::__internal::Box::new(async move { + let host = &mut host_getter(caller.data_mut()); + let r = Host::return_named_result(host).await; + Ok((r,)) + }) + }, )?; Ok(()) } diff --git a/crates/cranelift/Cargo.toml b/crates/cranelift/Cargo.toml index 1fd6320b088b..700b096e269d 100644 --- a/crates/cranelift/Cargo.toml +++ b/crates/cranelift/Cargo.toml @@ -37,6 +37,7 @@ wasmtime-versioned-export-macros = { workspace = true } [features] all-arch = ["cranelift-codegen/all-arch"] host-arch = ["cranelift-codegen/host-arch"] +pulley = ["cranelift-codegen/pulley"] component-model = ["wasmtime-environ/component-model"] incremental-cache = ["cranelift-codegen/incremental-cache"] wmemcheck = ["wasmtime-environ/wmemcheck"] diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs index a25679b6e5e6..328aa940fab2 100644 --- a/crates/cranelift/src/compiler.rs +++ b/crates/cranelift/src/compiler.rs @@ -15,7 +15,9 @@ use cranelift_codegen::print_errors::pretty_error; use cranelift_codegen::{CompiledCode, Context}; use cranelift_entity::PrimaryMap; use cranelift_frontend::FunctionBuilder; -use cranelift_wasm::{DefinedFuncIndex, FuncTranslator, WasmFuncType, WasmValType}; +use cranelift_wasm::{ + DefinedFuncIndex, FuncEnvironment as _, FuncTranslator, WasmFuncType, WasmValType, +}; use object::write::{Object, StandardSegment, SymbolId}; use object::{RelocationEncoding, RelocationFlags, RelocationKind, SectionKind}; use std::any::Any; @@ -206,7 +208,11 @@ impl wasmtime_environ::Compiler for Compiler { global_type: isa.pointer_type(), flags: MemFlags::trusted(), }); - context.func.stack_limit = Some(stack_limit); + if func_env.signals_based_traps() { + context.func.stack_limit = Some(stack_limit); + } else { + func_env.stack_limit_at_function_entry = Some(stack_limit); + } let FunctionBodyData { validator, body } = input; let mut validator = validator.into_validator(mem::take(&mut compiler.cx.validator_allocations)); diff --git a/crates/cranelift/src/compiler/component.rs b/crates/cranelift/src/compiler/component.rs index 774eeb43f5ea..7223029e23e9 100644 --- a/crates/cranelift/src/compiler/component.rs +++ b/crates/cranelift/src/compiler/component.rs @@ -8,7 +8,7 @@ use cranelift_frontend::FunctionBuilder; use cranelift_wasm::ModuleInternedTypeIndex; use std::any::Any; use wasmtime_environ::component::*; -use wasmtime_environ::{PtrSize, WasmValType}; +use wasmtime_environ::{PtrSize, Tunables, WasmValType}; struct TrampolineCompiler<'a> { compiler: &'a Compiler, @@ -20,6 +20,7 @@ struct TrampolineCompiler<'a> { abi: Abi, block0: ir::Block, signature: ModuleInternedTypeIndex, + tunables: &'a Tunables, } #[derive(Copy, Clone)] @@ -36,6 +37,7 @@ impl<'a> TrampolineCompiler<'a> { types: &'a ComponentTypesBuilder, index: TrampolineIndex, abi: Abi, + tunables: &'a Tunables, ) -> TrampolineCompiler<'a> { let isa = &*compiler.isa; let signature = component.trampolines[index]; @@ -58,6 +60,7 @@ impl<'a> TrampolineCompiler<'a> { abi, block0, signature, + tunables, } } @@ -91,9 +94,7 @@ impl<'a> TrampolineCompiler<'a> { self.translate_lower_import(*index, options, *lower_ty); } Trampoline::AlwaysTrap => { - self.builder - .ins() - .trap(ir::TrapCode::User(ALWAYS_TRAP_CODE)); + self.translate_always_trap(); } Trampoline::ResourceNew(ty) => self.translate_resource_new(*ty), Trampoline::ResourceRep(ty) => self.translate_resource_rep(*ty), @@ -261,6 +262,34 @@ impl<'a> TrampolineCompiler<'a> { } } + fn translate_always_trap(&mut self) { + if self.tunables.signals_based_traps { + self.builder + .ins() + .trap(ir::TrapCode::User(ALWAYS_TRAP_CODE)); + return; + } + + let args = self.abi_load_params(); + let vmctx = args[0]; + + let (host_sig, offset) = host::trap(self.isa, &mut self.builder.func); + let host_fn = self.load_libcall(vmctx, offset); + + let code = self.builder.ins().iconst( + ir::types::I8, + i64::from(wasmtime_environ::Trap::AlwaysTrapAdapter as u8), + ); + self.builder + .ins() + .call_indirect(host_sig, host_fn, &[vmctx, code]); + // debug trap in case execution actually falls through, but this + // shouldn't ever get hit at runtime. + self.builder + .ins() + .trap(ir::TrapCode::User(crate::DEBUG_ASSERT_TRAP_CODE)); + } + fn translate_resource_new(&mut self, resource: TypeResourceTableIndex) { let args = self.abi_load_params(); let vmctx = args[0]; @@ -625,6 +654,7 @@ impl ComponentCompiler for Compiler { component: &ComponentTranslation, types: &ComponentTypesBuilder, index: TrampolineIndex, + tunables: &Tunables, ) -> Result>> { let compile = |abi: Abi| -> Result<_> { let mut compiler = self.function_compiler(); @@ -635,6 +665,7 @@ impl ComponentCompiler for Compiler { types, index, abi, + tunables, ); // If we are crossing the Wasm-to-native boundary, we need to save the @@ -907,6 +938,7 @@ mod host { (@ty $ptr:ident ptr_u8) => ($ptr); (@ty $ptr:ident ptr_u16) => ($ptr); (@ty $ptr:ident ptr_size) => ($ptr); + (@ty $ptr:ident u8) => (ir::types::I8); (@ty $ptr:ident u32) => (ir::types::I32); (@ty $ptr:ident u64) => (ir::types::I64); (@ty $ptr:ident vmctx) => ($ptr); diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs index 2fc62521b00b..6aabd11a1997 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs @@ -13,9 +13,9 @@ use cranelift_frontend::FunctionBuilder; use cranelift_frontend::Variable; use cranelift_wasm::{ EngineOrModuleTypeIndex, FuncEnvironment as _, FuncIndex, FuncTranslationState, GlobalIndex, - GlobalVariable, Heap, HeapData, HeapStyle, MemoryIndex, TableData, TableIndex, TableSize, - TagIndex, TargetEnvironment, TypeIndex, WasmFuncType, WasmHeapTopType, WasmHeapType, - WasmResult, WasmValType, + GlobalVariable, Heap, HeapData, HeapStyle, IndexType, Memory, MemoryIndex, Table, TableData, + TableIndex, TableSize, TagIndex, TargetEnvironment, TypeIndex, WasmFuncType, WasmHeapTopType, + WasmHeapType, WasmResult, WasmValType, }; use smallvec::SmallVec; use std::mem; @@ -152,6 +152,15 @@ pub struct FuncEnvironment<'module_environment> { #[cfg(feature = "wmemcheck")] wmemcheck: bool, + + /// A `GlobalValue` in CLIF which represents the stack limit. + /// + /// Typically this resides in the `stack_limit` value of `ir::Function` but + /// that requires signal handlers on the host and when that's disabled this + /// is here with an explicit check instead. Note that the explicit check is + /// always present even if this is a "leaf" function, as we have to call + /// into the host to trap when signal handlers are disabled. + pub(crate) stack_limit_at_function_entry: Option, } impl<'module_environment> FuncEnvironment<'module_environment> { @@ -196,6 +205,8 @@ impl<'module_environment> FuncEnvironment<'module_environment> { wmemcheck, #[cfg(feature = "wmemcheck")] translation, + + stack_limit_at_function_entry: None, } } @@ -683,27 +694,50 @@ impl<'module_environment> FuncEnvironment<'module_environment> { builder.switch_to_block(continuation_block); } - fn memory_index_type(&self, index: MemoryIndex) -> ir::Type { - if self.module.memory_plans[index].memory.memory64 { - I64 - } else { - I32 + /// Get the Memory for the given index. + fn memory(&self, index: MemoryIndex) -> Memory { + self.module.memory_plans[index].memory + } + + /// Get the Table for the given index. + fn table(&self, index: TableIndex) -> Table { + self.module.table_plans[index].table + } + + /// Cast the value to I64 and sign extend if necessary. + /// + /// Returns the value casted to I64. + fn cast_index_to_i64( + &self, + pos: &mut FuncCursor<'_>, + val: ir::Value, + index_type: IndexType, + ) -> ir::Value { + match index_type { + IndexType::I32 => pos.ins().uextend(I64, val), + IndexType::I64 => val, } } - /// Convert the target pointer-sized integer `val` that is holding a memory - /// length (or the `-1` `memory.grow`-failed sentinel) into the memory's - /// index type. + /// Convert the target pointer-sized integer `val` into the memory/table's index type. /// - /// This might involve extending or truncating it depending on the memory's + /// For memory, `val` is holding a memory length (or the `-1` `memory.grow`-failed sentinel). + /// For table, `val` is holding a table length. + /// + /// This might involve extending or truncating it depending on the memory/table's /// index type and the target's pointer type. - fn convert_memory_length_to_index_type( + fn convert_pointer_to_index_type( &self, mut pos: FuncCursor<'_>, val: ir::Value, - index: MemoryIndex, + index_type: IndexType, + // When it is a memory and the memory is using single-byte pages, + // we need to handle the tuncation differently. See comments below. + // + // When it is a table, this should be set to false. + single_byte_pages: bool, ) -> ir::Value { - let desired_type = self.memory_index_type(index); + let desired_type = index_type_to_ir_type(index_type); let pointer_type = self.pointer_type(); assert_eq!(pos.func.dfg.value_type(val), pointer_type); @@ -715,21 +749,24 @@ impl<'module_environment> FuncEnvironment<'module_environment> { } else if pointer_type.bits() > desired_type.bits() { pos.ins().ireduce(desired_type, val) } else { - // We have a 64-bit memory on a 32-bit host -- this combo doesn't + // We have a 64-bit memory/table on a 32-bit host -- this combo doesn't // really make a whole lot of sense to do from a user perspective // but that is neither here nor there. We want to logically do an // unsigned extend *except* when we are given the `-1` sentinel, // which we must preserve as `-1` in the wider type. - match self.module.memory_plans[index].memory.page_size_log2 { - 16 => { + match single_byte_pages { + false => { // In the case that we have default page sizes, we can // always sign extend, since valid memory lengths (in pages) // never have their sign bit set, and so if the sign bit is // set then this must be the `-1` sentinel, which we want to // preserve through the extension. + // + // When it comes to table, `single_byte_pages` should have always been set to false. + // Then we simply do a signed extension. pos.ins().sextend(desired_type, val) } - 0 => { + true => { // For single-byte pages, we have to explicitly check for // `-1` and choose whether to do an unsigned extension or // return a larger `-1` because there are valid memory @@ -739,24 +776,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> { let is_failure = pos.ins().icmp_imm(IntCC::Equal, val, -1); pos.ins().select(is_failure, neg_one, extended) } - _ => unreachable!("only page sizes 2**0 and 2**16 are currently valid"), } } } - fn cast_memory_index_to_i64( - &self, - pos: &mut FuncCursor<'_>, - val: ir::Value, - index: MemoryIndex, - ) -> ir::Value { - if self.memory_index_type(index) == I64 { - val - } else { - pos.ins().uextend(I64, val) - } - } - /// Set up the necessary preamble definitions in `func` to access the table identified /// by `index`. /// @@ -795,18 +818,18 @@ impl<'module_environment> FuncEnvironment<'module_environment> { }; let table = &self.module.table_plans[index].table; - let element_size = if table.wasm_ty.is_vmgcref_type() { + let element_size = if table.ref_type.is_vmgcref_type() { // For GC-managed references, tables store `Option`s. ir::types::I32.bytes() } else { - self.reference_type(table.wasm_ty.heap_type).0.bytes() + self.reference_type(table.ref_type.heap_type).0.bytes() }; let base_gv = func.create_global_value(ir::GlobalValueData::Load { base: ptr, offset: Offset32::new(base_offset), global_type: pointer_type, - flags: if Some(table.minimum) == table.maximum { + flags: if Some(table.limits.min) == table.limits.max { // A fixed-size table can't be resized so its base address won't // change. MemFlags::trusted().with_readonly() @@ -815,9 +838,9 @@ impl<'module_environment> FuncEnvironment<'module_environment> { }, }); - let bound = if Some(table.minimum) == table.maximum { + let bound = if Some(table.limits.min) == table.limits.max { TableSize::Static { - bound: table.minimum, + bound: table.limits.min, } } else { TableSize::Dynamic { @@ -850,18 +873,13 @@ impl<'module_environment> FuncEnvironment<'module_environment> { ) -> ir::Value { let pointer_type = self.pointer_type(); self.ensure_table_exists(builder.func, table_index); - let table_data = self.tables[table_index].as_ref().unwrap(); + let table_data = self.tables[table_index].clone().unwrap(); // To support lazy initialization of table // contents, we check for a null entry here, and // if null, we take a slow-path that invokes a // libcall. - let (table_entry_addr, flags) = table_data.prepare_table_addr( - builder, - index, - pointer_type, - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (table_entry_addr, flags) = table_data.prepare_table_addr(self, builder, index); let value = builder.ins().load(pointer_type, flags, table_entry_addr, 0); if !lazy_init { @@ -892,11 +910,13 @@ impl<'module_environment> FuncEnvironment<'module_environment> { builder.seal_block(null_block); builder.switch_to_block(null_block); + let index_type = self.table(table_index).idx_type; let table_index = builder.ins().iconst(I32, table_index.index() as i64); let lazy_init = self .builtin_functions .table_get_lazy_init_func_ref(builder.func); let vmctx = self.vmctx_val(&mut builder.cursor()); + let index = self.cast_index_to_i64(&mut builder.cursor(), index, index_type); let call_inst = builder.ins().call(lazy_init, &[vmctx, table_index, index]); let returned_entry = builder.func.dfg.inst_results(call_inst)[0]; builder.ins().jump(continuation_block, &[returned_entry]); @@ -1016,6 +1036,99 @@ impl<'module_environment> FuncEnvironment<'module_environment> { }); (pointee, mt) } + + /// Helper to emit a conditional trap based on `trap_cond`. + /// + /// This should only be used if `self.signals_based_traps()` is false, + /// otherwise native CLIF instructions should be used instead. + pub fn conditionally_trap( + &mut self, + builder: &mut FunctionBuilder, + trap_cond: ir::Value, + trap: ir::TrapCode, + ) { + assert!(!self.signals_based_traps()); + + let trap_block = builder.create_block(); + builder.set_cold_block(trap_block); + let continuation_block = builder.create_block(); + + builder + .ins() + .brif(trap_cond, trap_block, &[], continuation_block, &[]); + + builder.seal_block(trap_block); + builder.seal_block(continuation_block); + + builder.switch_to_block(trap_block); + self.trap(builder, trap); + builder.switch_to_block(continuation_block); + } + + /// Helper used when `!self.signals_based_traps()` is enabled to test + /// whether the divisor is zero. + fn guard_zero_divisor(&mut self, builder: &mut FunctionBuilder, rhs: ir::Value) { + if self.signals_based_traps() { + return; + } + self.trapz(builder, rhs, ir::TrapCode::IntegerDivisionByZero); + } + + /// Helper used when `!self.signals_based_traps()` is enabled to test + /// whether a signed division operation will raise a trap. + fn guard_signed_divide( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) { + if self.signals_based_traps() { + return; + } + self.trapz(builder, rhs, ir::TrapCode::IntegerDivisionByZero); + + let ty = builder.func.dfg.value_type(rhs); + let minus_one = builder.ins().iconst(ty, -1); + let rhs_is_minus_one = builder.ins().icmp(IntCC::Equal, rhs, minus_one); + let int_min = builder.ins().iconst( + ty, + match ty { + I32 => i64::from(i32::MIN), + I64 => i64::MIN, + _ => unreachable!(), + }, + ); + let lhs_is_int_min = builder.ins().icmp(IntCC::Equal, lhs, int_min); + let is_integer_overflow = builder.ins().band(rhs_is_minus_one, lhs_is_int_min); + self.conditionally_trap(builder, is_integer_overflow, ir::TrapCode::IntegerOverflow); + } + + /// Helper used when `!self.signals_based_traps()` is enabled to perform + /// trapping float-to-int conversions. + fn fcvt_to_int( + &mut self, + builder: &mut FunctionBuilder, + ty: ir::Type, + val: ir::Value, + i32: fn(&mut Self, &mut Function) -> ir::FuncRef, + i64: fn(&mut Self, &mut Function) -> ir::FuncRef, + ) -> ir::Value { + assert!(!self.signals_based_traps()); + let val_ty = builder.func.dfg.value_type(val); + let val = if val_ty == F64 { + val + } else { + builder.ins().fpromote(F64, val) + }; + let libcall = match ty { + I32 => i32(self, &mut builder.func), + I64 => i64(self, &mut builder.func), + _ => unreachable!(), + }; + let vmctx = self.vmctx_val(&mut builder.cursor()); + let call = builder.ins().call(libcall, &[vmctx, val]); + *builder.func.dfg.inst_results(call).first().unwrap() + } } struct Call<'a, 'func, 'module_env> { @@ -1219,7 +1332,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { // Test if a type check is necessary for this table. If this table is a // table of typed functions and that type matches `ty_index`, then // there's no need to perform a typecheck. - match table.table.wasm_ty.heap_type { + match table.table.ref_type.heap_type { // Functions do not have a statically known type in the table, a // typecheck is required. Fall through to below to perform the // actual typecheck. @@ -1235,7 +1348,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { let specified_ty = self.env.module.types[ty_index]; if specified_ty == table_ty { return CheckIndirectCallTypeSignature::StaticMatch { - may_be_null: table.table.wasm_ty.nullable, + may_be_null: table.table.ref_type.nullable, }; } @@ -1247,24 +1360,30 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { // type information. If that fails due to the function being a // null pointer, then this was a call to null. Otherwise if it // succeeds then we know it won't match, so trap anyway. - if table.table.wasm_ty.nullable { - let mem_flags = ir::MemFlags::trusted().with_readonly(); - self.builder.ins().load( - sig_id_type, - mem_flags.with_trap_code(Some(ir::TrapCode::IndirectCallToNull)), - funcref_ptr, - i32::from(self.env.offsets.ptr.vm_func_ref_type_index()), - ); + if table.table.ref_type.nullable { + if self.env.signals_based_traps() { + let mem_flags = ir::MemFlags::trusted().with_readonly(); + self.builder.ins().load( + sig_id_type, + mem_flags.with_trap_code(Some(ir::TrapCode::IndirectCallToNull)), + funcref_ptr, + i32::from(self.env.offsets.ptr.vm_func_ref_type_index()), + ); + } else { + self.env + .trapz(self.builder, funcref_ptr, ir::TrapCode::IndirectCallToNull); + } } - self.builder.ins().trap(ir::TrapCode::BadSignature); + self.env.trap(self.builder, ir::TrapCode::BadSignature); return CheckIndirectCallTypeSignature::StaticTrap; } // Tables of `nofunc` can only be inhabited by null, so go ahead and // trap with that. WasmHeapType::NoFunc => { - assert!(table.table.wasm_ty.nullable); - self.builder.ins().trap(ir::TrapCode::IndirectCallToNull); + assert!(table.table.ref_type.nullable); + self.env + .trap(self.builder, ir::TrapCode::IndirectCallToNull); return CheckIndirectCallTypeSignature::StaticTrap; } @@ -1316,10 +1435,16 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { // // Note that the callee may be null in which case this load may // trap. If so use the `IndirectCallToNull` trap code. - let mem_flags = ir::MemFlags::trusted().with_readonly(); + let mut mem_flags = ir::MemFlags::trusted().with_readonly(); + if self.env.signals_based_traps() { + mem_flags = mem_flags.with_trap_code(Some(ir::TrapCode::IndirectCallToNull)); + } else { + self.env + .trapz(self.builder, funcref_ptr, ir::TrapCode::IndirectCallToNull); + } let callee_sig_id = self.builder.ins().load( sig_id_type, - mem_flags.with_trap_code(Some(ir::TrapCode::IndirectCallToNull)), + mem_flags, funcref_ptr, i32::from(self.env.offsets.ptr.vm_func_ref_type_index()), ); @@ -1329,7 +1454,8 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { .builder .ins() .icmp(IntCC::Equal, callee_sig_id, caller_sig_id); - self.builder.ins().trapz(cmp, ir::TrapCode::BadSignature); + self.env + .trapz(self.builder, cmp, ir::TrapCode::BadSignature); CheckIndirectCallTypeSignature::Runtime } @@ -1382,9 +1508,17 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { // will handle the case where this is either already known to be // non-null or may trap. let mem_flags = ir::MemFlags::trusted().with_readonly(); + let mut callee_flags = mem_flags; + if self.env.signals_based_traps() { + callee_flags = callee_flags.with_trap_code(callee_load_trap_code); + } else { + if let Some(trap) = callee_load_trap_code { + self.env.trapz(self.builder, callee, trap); + } + } let func_addr = self.builder.ins().load( pointer_type, - mem_flags.with_trap_code(callee_load_trap_code), + callee_flags, callee, i32::from(self.env.offsets.ptr.vm_func_ref_wasm_call()), ); @@ -1564,10 +1698,12 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m delta: ir::Value, init_value: ir::Value, ) -> WasmResult { - let ty = self.module.table_plans[table_index].table.wasm_ty.heap_type; + let table = self.table(table_index); + let ty = table.ref_type.heap_type; let vmctx = self.vmctx_val(&mut builder.cursor()); + let index_type = table.idx_type; + let delta = self.cast_index_to_i64(&mut builder.cursor(), delta, index_type); let table_index_arg = builder.ins().iconst(I32, table_index.as_u32() as i64); - let mut args = vec![vmctx, table_index_arg, delta]; let grow = if ty.is_vmgcref_type() { args.push(init_value); @@ -1596,8 +1732,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m }; let call_inst = builder.ins().call(grow, &args); - - Ok(builder.func.dfg.first_result(call_inst)) + let result = builder.func.dfg.first_result(call_inst); + Ok(self.convert_pointer_to_index_type(builder.cursor(), result, index_type, false)) } fn translate_table_get( @@ -1607,34 +1743,25 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m index: ir::Value, ) -> WasmResult { let plan = &self.module.table_plans[table_index]; + let table = plan.table; self.ensure_table_exists(builder.func, table_index); - let table_data = self.tables[table_index].as_ref().unwrap(); - let heap_ty = plan.table.wasm_ty.heap_type; + let table_data = self.tables[table_index].clone().unwrap(); + let heap_ty = table.ref_type.heap_type; match heap_ty.top() { // `i31ref`s never need barriers, and therefore don't need to go // through the GC compiler. WasmHeapTopType::Any if heap_ty == WasmHeapType::I31 => { - let (src, flags) = table_data.prepare_table_addr( - builder, - index, - self.pointer_type(), - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (src, flags) = table_data.prepare_table_addr(self, builder, index); gc::unbarriered_load_gc_ref(self, builder, WasmHeapType::I31, src, flags) } // GC-managed types. WasmHeapTopType::Any | WasmHeapTopType::Extern => { - let (src, flags) = table_data.prepare_table_addr( - builder, - index, - self.pointer_type(), - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (src, flags) = table_data.prepare_table_addr(self, builder, index); gc::gc_compiler(self).translate_read_gc_reference( self, builder, - plan.table.wasm_ty, + table.ref_type, src, flags, ) @@ -1655,16 +1782,9 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m // Continuation types. WasmHeapTopType::Cont => match plan.style { TableStyle::CallerChecksSignature { lazy_init: _ } => { - let pointer_type = self.pointer_type(); self.ensure_table_exists(builder.func, table_index); - let table_data = self.tables[table_index].as_ref().unwrap(); - - let (table_entry_addr, flags) = table_data.prepare_table_addr( - builder, - index, - pointer_type, - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (table_entry_addr, flags) = + table_data.prepare_table_addr(self, builder, index); Ok(builder.ins().load( wasmfx_impl::vm_contobj_type(self.pointer_type()), flags, @@ -1683,36 +1803,26 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m value: ir::Value, index: ir::Value, ) -> WasmResult<()> { - let pointer_type = self.pointer_type(); let plan = &self.module.table_plans[table_index]; + let table = plan.table; self.ensure_table_exists(builder.func, table_index); - let table_data = self.tables[table_index].as_ref().unwrap(); - let heap_ty = plan.table.wasm_ty.heap_type; + let table_data = self.tables[table_index].clone().unwrap(); + let heap_ty = table.ref_type.heap_type; match heap_ty.top() { // `i31ref`s never need GC barriers, and therefore don't need to go // through the GC compiler. WasmHeapTopType::Any if heap_ty == WasmHeapType::I31 => { - let (addr, flags) = table_data.prepare_table_addr( - builder, - index, - self.pointer_type(), - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (addr, flags) = table_data.prepare_table_addr(self, builder, index); gc::unbarriered_store_gc_ref(self, builder, WasmHeapType::I31, addr, value, flags) } // GC-managed types. WasmHeapTopType::Any | WasmHeapTopType::Extern => { - let (dst, flags) = table_data.prepare_table_addr( - builder, - index, - self.pointer_type(), - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (dst, flags) = table_data.prepare_table_addr(self, builder, index); gc::gc_compiler(self).translate_write_gc_reference( self, builder, - plan.table.wasm_ty, + table.ref_type, dst, value, flags, @@ -1723,12 +1833,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m WasmHeapTopType::Func => { match plan.style { TableStyle::CallerChecksSignature { lazy_init } => { - let (elem_addr, flags) = table_data.prepare_table_addr( - builder, - index, - pointer_type, - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (elem_addr, flags) = + table_data.prepare_table_addr(self, builder, index); // Set the "initialized bit". See doc-comment on // `FUNCREF_INIT_BIT` in // crates/environ/src/ref_bits.rs for details. @@ -1750,12 +1856,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m // Continuation types. WasmHeapTopType::Cont => match plan.style { TableStyle::CallerChecksSignature { lazy_init: _ } => { - let (elem_addr, flags) = table_data.prepare_table_addr( - builder, - index, - pointer_type, - self.isa.flags().enable_table_access_spectre_mitigation(), - ); + let (elem_addr, flags) = table_data.prepare_table_addr(self, builder, index); builder.ins().store(flags, value, elem_addr, 0); Ok(()) } @@ -1771,9 +1872,13 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m val: ir::Value, len: ir::Value, ) -> WasmResult<()> { - let ty = self.module.table_plans[table_index].table.wasm_ty.heap_type; + let table = self.table(table_index); + let ty = table.ref_type.heap_type; let vmctx = self.vmctx_val(&mut builder.cursor()); + let index_type = table.idx_type; let table_index_arg = builder.ins().iconst(I32, table_index.as_u32() as i64); + let dst = self.cast_index_to_i64(&mut builder.cursor(), dst, index_type); + let len = self.cast_index_to_i64(&mut builder.cursor(), len, index_type); let mut args = vec![vmctx, table_index_arg, dst]; let libcall = if ty.is_vmgcref_type() { args.push(val); @@ -1814,20 +1919,20 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m fn translate_i31_get_s( &mut self, - mut pos: FuncCursor, + builder: &mut FunctionBuilder, i31ref: ir::Value, ) -> WasmResult { - pos.ins().trapz(i31ref, ir::TrapCode::NullI31Ref); - Ok(pos.ins().sshr_imm(i31ref, 1)) + self.trapz(builder, i31ref, ir::TrapCode::NullI31Ref); + Ok(builder.ins().sshr_imm(i31ref, 1)) } fn translate_i31_get_u( &mut self, - mut pos: FuncCursor, + builder: &mut FunctionBuilder, i31ref: ir::Value, ) -> WasmResult { - pos.ins().trapz(i31ref, ir::TrapCode::NullI31Ref); - Ok(pos.ins().ushr_imm(i31ref, 1)) + self.trapz(builder, i31ref, ir::TrapCode::NullI31Ref); + Ok(builder.ins().ushr_imm(i31ref, 1)) } fn translate_ref_null( @@ -1891,21 +1996,25 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m ty.is_vmgcref_type(), "We only use GlobalVariable::Custom for VMGcRef types" ); + let cranelift_wasm::WasmValType::Ref(ty) = ty else { + unreachable!() + }; - // TODO: use `GcCompiler::translate_read_gc_reference` for GC-reference - // globals instead of a libcall. - let libcall = gc::gc_ref_global_get_builtin(ty, self, &mut builder.func)?; - - let vmctx = self.vmctx_val(&mut builder.cursor()); - - let global_index_arg = builder.ins().iconst(I32, index.as_u32() as i64); - let call_inst = builder.ins().call(libcall, &[vmctx, global_index_arg]); + let (gv, offset) = self.get_global_location(builder.func, index); + let gv = builder.ins().global_value(self.pointer_type(), gv); + let src = builder.ins().iadd_imm(gv, i64::from(offset)); - let val = builder.func.dfg.first_result(call_inst); - if ty.is_vmgcref_type_and_not_i31() { - builder.declare_value_needs_stack_map(val); + if let WasmHeapType::I31 = ty.heap_type { + gc::unbarriered_load_gc_ref(self, builder, ty.heap_type, src, ir::MemFlags::trusted()) + } else { + gc::gc_compiler(self).translate_read_gc_reference( + self, + builder, + ty, + src, + ir::MemFlags::trusted(), + ) } - Ok(val) } fn translate_custom_global_set( @@ -1919,19 +2028,33 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m ty.is_vmgcref_type(), "We only use GlobalVariable::Custom for VMGcRef types" ); + let cranelift_wasm::WasmValType::Ref(ty) = ty else { + unreachable!() + }; - // TODO: use `GcCompiler::translate_write_gc_reference` for GC-reference - // globals instead of a libcall. - let libcall = gc::gc_ref_global_set_builtin(ty, self, &mut builder.func)?; - - let vmctx = self.vmctx_val(&mut builder.cursor()); + let (gv, offset) = self.get_global_location(builder.func, index); + let gv = builder.ins().global_value(self.pointer_type(), gv); + let src = builder.ins().iadd_imm(gv, i64::from(offset)); - let global_index_arg = builder.ins().iconst(I32, index.as_u32() as i64); - builder - .ins() - .call(libcall, &[vmctx, global_index_arg, value]); - - Ok(()) + if let WasmHeapType::I31 = ty.heap_type { + gc::unbarriered_store_gc_ref( + self, + builder, + ty.heap_type, + src, + value, + ir::MemFlags::trusted(), + ) + } else { + gc::gc_compiler(self).translate_write_gc_reference( + self, + builder, + ty, + src, + value, + ir::MemFlags::trusted(), + ) + } } fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> WasmResult { @@ -1946,7 +2069,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m // integer is the maximum memory64 size (2^64) which is one // larger than `u64::MAX` (2^64 - 1). In this case, just say the // minimum heap size is `u64::MAX`. - debug_assert_eq!(self.module.memory_plans[index].memory.minimum, 1 << 48); + debug_assert_eq!(self.module.memory_plans[index].memory.limits.min, 1 << 48); debug_assert_eq!(self.module.memory_plans[index].memory.page_size(), 1 << 16); u64::MAX }); @@ -2172,7 +2295,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m max_size, offset_guard_size, style: heap_style, - index_type: self.memory_index_type(index), + index_type: index_type_to_ir_type(self.memory(index).idx_type), memory_type, page_size_log2, })) @@ -2339,10 +2462,16 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let memory_index = pos.ins().iconst(I32, index_arg as i64); let vmctx = self.vmctx_val(&mut pos); - let val = self.cast_memory_index_to_i64(&mut pos, val, index); + let index_type = self.memory(index).idx_type; + let val = self.cast_index_to_i64(&mut pos, val, index_type); let call_inst = pos.ins().call(memory_grow, &[vmctx, val, memory_index]); let result = *pos.func.dfg.inst_results(call_inst).first().unwrap(); - Ok(self.convert_memory_length_to_index_type(pos, result, index)) + let single_byte_pages = match self.memory(index).page_size_log2 { + 16 => false, + 0 => true, + _ => unreachable!("only page sizes 2**0 and 2**16 are currently valid"), + }; + Ok(self.convert_pointer_to_index_type(pos, result, index_type, single_byte_pages)) } fn translate_memory_size( @@ -2417,8 +2546,17 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let page_size_log2 = i64::from(self.module.memory_plans[index].memory.page_size_log2); let current_length_in_pages = pos.ins().ushr_imm(current_length_in_bytes, page_size_log2); - - Ok(self.convert_memory_length_to_index_type(pos, current_length_in_pages, index)) + let single_byte_pages = match page_size_log2 { + 16 => false, + 0 => true, + _ => unreachable!("only page sizes 2**0 and 2**16 are currently valid"), + }; + Ok(self.convert_pointer_to_index_type( + pos, + current_length_in_pages, + self.memory(index).idx_type, + single_byte_pages, + )) } fn translate_memory_copy( @@ -2435,15 +2573,15 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let vmctx = self.vmctx_val(&mut pos); let memory_copy = self.builtin_functions.memory_copy(&mut pos.func); - let dst = self.cast_memory_index_to_i64(&mut pos, dst, dst_index); - let src = self.cast_memory_index_to_i64(&mut pos, src, src_index); + let dst = self.cast_index_to_i64(&mut pos, dst, self.memory(dst_index).idx_type); + let src = self.cast_index_to_i64(&mut pos, src, self.memory(src_index).idx_type); // The length is 32-bit if either memory is 32-bit, but if they're both // 64-bit then it's 64-bit. Our intrinsic takes a 64-bit length for // compatibility across all memories, so make sure that it's cast // correctly here (this is a bit special so no generic helper unlike for // `dst`/`src` above) - let len = if self.memory_index_type(dst_index) == I64 - && self.memory_index_type(src_index) == I64 + let len = if index_type_to_ir_type(self.memory(dst_index).idx_type) == I64 + && index_type_to_ir_type(self.memory(src_index).idx_type) == I64 { len } else { @@ -2467,8 +2605,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m len: ir::Value, ) -> WasmResult<()> { let memory_fill = self.builtin_functions.memory_fill(&mut pos.func); - let dst = self.cast_memory_index_to_i64(&mut pos, dst, memory_index); - let len = self.cast_memory_index_to_i64(&mut pos, len, memory_index); + let dst = self.cast_index_to_i64(&mut pos, dst, self.memory(memory_index).idx_type); + let len = self.cast_index_to_i64(&mut pos, len, self.memory(memory_index).idx_type); let memory_index_arg = pos.ins().iconst(I32, i64::from(memory_index.as_u32())); let vmctx = self.vmctx_val(&mut pos); @@ -2496,7 +2634,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let vmctx = self.vmctx_val(&mut pos); - let dst = self.cast_memory_index_to_i64(&mut pos, dst, memory_index); + let dst = self.cast_index_to_i64(&mut pos, dst, self.memory(memory_index).idx_type); pos.ins().call( memory_init, @@ -2521,7 +2659,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m ) -> WasmResult { self.ensure_table_exists(pos.func, table_index); let table_data = self.tables[table_index].as_ref().unwrap(); - Ok(table_data.bound.bound(pos, ir::types::I32)) + let index_type = index_type_to_ir_type(self.table(table_index).idx_type); + Ok(table_data.bound.bound(&*self.isa, pos, index_type)) } fn translate_table_copy( @@ -2536,6 +2675,15 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let (table_copy, dst_table_index_arg, src_table_index_arg) = self.get_table_copy_func(&mut pos.func, dst_table_index, src_table_index); + let dst = self.cast_index_to_i64(&mut pos, dst, self.table(dst_table_index).idx_type); + let src = self.cast_index_to_i64(&mut pos, src, self.table(src_table_index).idx_type); + let len = if index_type_to_ir_type(self.table(dst_table_index).idx_type) == I64 + && index_type_to_ir_type(self.table(src_table_index).idx_type) == I64 + { + len + } else { + pos.ins().uextend(I64, len) + }; let dst_table_index_arg = pos.ins().iconst(I32, dst_table_index_arg as i64); let src_table_index_arg = pos.ins().iconst(I32, src_table_index_arg as i64); let vmctx = self.vmctx_val(&mut pos); @@ -2567,6 +2715,11 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m let table_index_arg = pos.ins().iconst(I32, i64::from(table_index.as_u32())); let seg_index_arg = pos.ins().iconst(I32, i64::from(seg_index)); let vmctx = self.vmctx_val(&mut pos); + let index_type = self.table(table_index).idx_type; + let dst = self.cast_index_to_i64(&mut pos, dst, index_type); + let src = pos.ins().uextend(I64, src); + let len = pos.ins().uextend(I64, len); + pos.ins().call( table_init, &[vmctx, table_index_arg, seg_index_arg, dst, src, len], @@ -2594,7 +2747,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m ) -> WasmResult { #[cfg(feature = "threads")] { - let addr = self.cast_memory_index_to_i64(&mut pos, addr, memory_index); + let addr = self.cast_index_to_i64(&mut pos, addr, self.memory(memory_index).idx_type); let implied_ty = pos.func.dfg.value_type(expected); let (wait_func, memory_index) = self.get_memory_atomic_wait(&mut pos.func, memory_index, implied_ty); @@ -2629,7 +2782,7 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m ) -> WasmResult { #[cfg(feature = "threads")] { - let addr = self.cast_memory_index_to_i64(&mut pos, addr, memory_index); + let addr = self.cast_index_to_i64(&mut pos, addr, self.memory(memory_index).idx_type); let atomic_notify = self.builtin_functions.memory_atomic_notify(&mut pos.func); let memory_index_arg = pos.ins().iconst(I32, memory_index.index() as i64); @@ -2705,6 +2858,15 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m builder: &mut FunctionBuilder, _state: &FuncTranslationState, ) -> WasmResult<()> { + // If an explicit stack limit is requested, emit one here at the start + // of the function. + if let Some(gv) = self.stack_limit_at_function_entry { + let limit = builder.ins().global_value(self.pointer_type(), gv); + let sp = builder.ins().get_stack_pointer(self.pointer_type()); + let overflow = builder.ins().icmp(IntCC::UnsignedLessThan, sp, limit); + self.conditionally_trap(builder, overflow, ir::TrapCode::StackOverflow); + } + // If the `vmruntime_limits_ptr` variable will get used then we initialize // it here. if self.tunables.consume_fuel || self.tunables.epoch_interruption { @@ -2944,4 +3106,169 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m builder.ins().call(update_mem_size, &[vmctx, num_pages]); } } + + fn isa(&self) -> &dyn TargetIsa { + &*self.isa + } + + fn trap(&mut self, builder: &mut FunctionBuilder, trap: ir::TrapCode) { + match ( + self.signals_based_traps(), + crate::clif_trap_to_env_trap(trap), + ) { + // If libcall traps are disabled or there's no wasmtime-defined trap + // code for this, then emit a native trap instruction. + (true, _) | (_, None) => { + builder.ins().trap(trap); + } + // ... otherwise with libcall traps explicitly enabled and a + // wasmtime-based trap code invoke the libcall to raise a trap and + // pass in our trap code. Leave a debug `unreachable` in place + // afterwards as a defense-in-depth measure. + (false, Some(trap)) => { + let libcall = self.builtin_functions.trap(&mut builder.func); + let vmctx = self.vmctx_val(&mut builder.cursor()); + let trap_code = builder.ins().iconst(I8, i64::from(trap as u8)); + builder.ins().call(libcall, &[vmctx, trap_code]); + builder + .ins() + .trap(ir::TrapCode::User(crate::DEBUG_ASSERT_TRAP_CODE)); + } + } + } + + fn trapz(&mut self, builder: &mut FunctionBuilder, value: ir::Value, trap: ir::TrapCode) { + if self.signals_based_traps() { + builder.ins().trapz(value, trap); + } else { + let ty = builder.func.dfg.value_type(value); + let zero = builder.ins().iconst(ty, 0); + let cmp = builder.ins().icmp(IntCC::Equal, value, zero); + self.conditionally_trap(builder, cmp, trap); + } + } + + fn trapnz(&mut self, builder: &mut FunctionBuilder, value: ir::Value, trap: ir::TrapCode) { + if self.signals_based_traps() { + builder.ins().trapnz(value, trap); + } else { + let ty = builder.func.dfg.value_type(value); + let zero = builder.ins().iconst(ty, 0); + let cmp = builder.ins().icmp(IntCC::NotEqual, value, zero); + self.conditionally_trap(builder, cmp, trap); + } + } + + fn uadd_overflow_trap( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + trap: ir::TrapCode, + ) -> ir::Value { + if self.signals_based_traps() { + builder.ins().uadd_overflow_trap(lhs, rhs, trap) + } else { + let (ret, overflow) = builder.ins().uadd_overflow(lhs, rhs); + self.conditionally_trap(builder, overflow, trap); + ret + } + } + + fn signals_based_traps(&self) -> bool { + self.tunables.signals_based_traps + } + + fn translate_sdiv( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + self.guard_signed_divide(builder, lhs, rhs); + builder.ins().sdiv(lhs, rhs) + } + + fn translate_udiv( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + self.guard_zero_divisor(builder, rhs); + builder.ins().udiv(lhs, rhs) + } + + fn translate_srem( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + self.guard_zero_divisor(builder, rhs); + builder.ins().srem(lhs, rhs) + } + + fn translate_urem( + &mut self, + builder: &mut FunctionBuilder, + lhs: ir::Value, + rhs: ir::Value, + ) -> ir::Value { + self.guard_zero_divisor(builder, rhs); + builder.ins().urem(lhs, rhs) + } + + fn translate_fcvt_to_sint( + &mut self, + builder: &mut FunctionBuilder, + ty: ir::Type, + val: ir::Value, + ) -> ir::Value { + // NB: for now avoid translating this entire instruction to CLIF and + // just do it in a libcall. + if self.signals_based_traps() { + builder.ins().fcvt_to_sint(ty, val) + } else { + self.fcvt_to_int( + builder, + ty, + val, + |me, func| me.builtin_functions.f64_to_i32(func), + |me, func| me.builtin_functions.f64_to_i64(func), + ) + } + } + + fn translate_fcvt_to_uint( + &mut self, + builder: &mut FunctionBuilder, + ty: ir::Type, + val: ir::Value, + ) -> ir::Value { + // NB: for now avoid translating this entire instruction to CLIF and + // just do it in a libcall. + if self.signals_based_traps() { + builder.ins().fcvt_to_uint(ty, val) + } else { + self.fcvt_to_int( + builder, + ty, + val, + |me, func| me.builtin_functions.f64_to_u32(func), + |me, func| me.builtin_functions.f64_to_u64(func), + ) + } + } +} + +// Helper function to convert an `IndexType` to an `ir::Type`. +// +// Implementing From/Into trait for `IndexType` or `ir::Type` would +// introduce an extra dependency between `wasmtime_types` and `cranelift_codegen`. +fn index_type_to_ir_type(index_type: IndexType) -> ir::Type { + match index_type { + IndexType::I32 => I32, + IndexType::I64 => I64, + } } diff --git a/crates/cranelift/src/gc.rs b/crates/cranelift/src/gc.rs index 0583dfee0221..8cc9f0d26165 100644 --- a/crates/cranelift/src/gc.rs +++ b/crates/cranelift/src/gc.rs @@ -8,7 +8,7 @@ use crate::func_environ::FuncEnvironment; use cranelift_codegen::ir; use cranelift_frontend::FunctionBuilder; -use cranelift_wasm::{WasmHeapType, WasmRefType, WasmResult, WasmValType}; +use cranelift_wasm::{WasmHeapType, WasmRefType, WasmResult}; #[cfg(feature = "gc")] mod enabled; @@ -19,6 +19,7 @@ use enabled as imp; mod disabled; #[cfg(not(feature = "gc"))] use disabled as imp; +use wasmtime_environ::GcTypeLayouts; /// Get the GC compiler configured for the given function environment. pub fn gc_compiler(func_env: &FuncEnvironment<'_>) -> Box { @@ -80,30 +81,12 @@ pub fn gc_ref_table_fill_builtin( imp::gc_ref_table_fill_builtin(ty, func_env, func) } -/// Get the index and signature of the built-in function for doing `global.get` -/// on a GC reference global. -pub fn gc_ref_global_get_builtin( - ty: WasmValType, - func_env: &mut FuncEnvironment<'_>, - func: &mut ir::Function, -) -> WasmResult { - debug_assert!(ty.is_vmgcref_type()); - imp::gc_ref_global_get_builtin(ty, func_env, func) -} - -/// Get the index and signature of the built-in function for doing `global.set` -/// on a GC reference global. -pub fn gc_ref_global_set_builtin( - ty: WasmValType, - func_env: &mut FuncEnvironment<'_>, - func: &mut ir::Function, -) -> WasmResult { - debug_assert!(ty.is_vmgcref_type()); - imp::gc_ref_global_set_builtin(ty, func_env, func) -} - /// A trait for different collectors to emit any GC barriers they might require. pub trait GcCompiler { + /// Get the GC type layouts for this GC compiler. + #[allow(dead_code)] // Used in future PRs. + fn layouts(&self) -> &dyn GcTypeLayouts; + /// Emit a read barrier for when we are cloning a GC reference onto the Wasm /// stack. /// diff --git a/crates/cranelift/src/gc/disabled.rs b/crates/cranelift/src/gc/disabled.rs index 308806299fde..ef6847ad19fb 100644 --- a/crates/cranelift/src/gc/disabled.rs +++ b/crates/cranelift/src/gc/disabled.rs @@ -4,7 +4,8 @@ use super::GcCompiler; use crate::func_environ::FuncEnvironment; use cranelift_codegen::ir; use cranelift_frontend::FunctionBuilder; -use cranelift_wasm::{wasm_unsupported, WasmHeapType, WasmRefType, WasmResult, WasmValType}; +use cranelift_wasm::{wasm_unsupported, WasmHeapType, WasmRefType, WasmResult}; +use wasmtime_environ::GcTypeLayouts; /// Get the default GC compiler. pub fn gc_compiler(_: &FuncEnvironment<'_>) -> Box { @@ -60,31 +61,16 @@ pub fn gc_ref_table_fill_builtin( )) } -pub fn gc_ref_global_get_builtin( - ty: WasmValType, - _func_env: &mut FuncEnvironment<'_>, - _func: &mut ir::Function, -) -> WasmResult { - Err(wasm_unsupported!( - "support for `{ty}` disabled at compile time because the `gc` cargo \ - feature was not enabled" - )) -} - -pub fn gc_ref_global_set_builtin( - ty: WasmValType, - _func_env: &mut FuncEnvironment<'_>, - _func: &mut ir::Function, -) -> WasmResult { - Err(wasm_unsupported!( - "support for `{ty}` disabled at compile time because the `gc` cargo \ - feature was not enabled" - )) -} - struct DisabledGcCompiler; impl GcCompiler for DisabledGcCompiler { + fn layouts(&self) -> &dyn GcTypeLayouts { + panic!( + "support for GC types disabled at compile time because the `gc` cargo \ + feature was not enabled" + ) + } + fn translate_read_gc_reference( &mut self, _func_env: &mut FuncEnvironment<'_>, diff --git a/crates/cranelift/src/gc/enabled.rs b/crates/cranelift/src/gc/enabled.rs index 3c8245bcea3b..103685b0fc4b 100644 --- a/crates/cranelift/src/gc/enabled.rs +++ b/crates/cranelift/src/gc/enabled.rs @@ -2,14 +2,14 @@ use super::GcCompiler; use crate::func_environ::FuncEnvironment; use cranelift_codegen::ir::{self, condcodes::IntCC, InstBuilder}; use cranelift_frontend::FunctionBuilder; -use cranelift_wasm::{ - TargetEnvironment, WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult, WasmValType, +use cranelift_wasm::{TargetEnvironment, WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult}; +use wasmtime_environ::{ + drc::DrcTypeLayouts, GcTypeLayouts, PtrSize, I31_DISCRIMINANT, NON_NULL_NON_I31_MASK, }; -use wasmtime_environ::{PtrSize, I31_DISCRIMINANT, NON_NULL_NON_I31_MASK}; /// Get the default GC compiler. pub fn gc_compiler(_func_env: &FuncEnvironment<'_>) -> Box { - Box::new(DrcCompiler) + Box::new(DrcCompiler::default()) } pub fn unbarriered_load_gc_ref( @@ -62,24 +62,6 @@ pub fn gc_ref_table_fill_builtin( Ok(func_env.builtin_functions.table_fill_gc_ref(func)) } -pub fn gc_ref_global_get_builtin( - ty: WasmValType, - func_env: &mut FuncEnvironment<'_>, - func: &mut ir::Function, -) -> WasmResult { - debug_assert!(ty.is_vmgcref_type()); - Ok(func_env.builtin_functions.gc_ref_global_get(func)) -} - -pub fn gc_ref_global_set_builtin( - ty: WasmValType, - func_env: &mut FuncEnvironment<'_>, - func: &mut ir::Function, -) -> WasmResult { - debug_assert!(ty.is_vmgcref_type()); - Ok(func_env.builtin_functions.gc_ref_global_set(func)) -} - impl FuncEnvironment<'_> { /// Get the GC heap's base pointer and bound. fn get_gc_heap_base_bound(&mut self, builder: &mut FunctionBuilder) -> (ir::Value, ir::Value) { @@ -204,7 +186,10 @@ impl FuncEnvironment<'_> { } } -struct DrcCompiler; +#[derive(Default)] +struct DrcCompiler { + layouts: DrcTypeLayouts, +} impl DrcCompiler { /// Generate code to load the given GC reference's ref count. @@ -296,6 +281,10 @@ impl DrcCompiler { } impl GcCompiler for DrcCompiler { + fn layouts(&self) -> &dyn GcTypeLayouts { + &self.layouts + } + fn translate_read_gc_reference( &mut self, func_env: &mut FuncEnvironment<'_>, diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs index 36079d157bbf..d87b5c070f16 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs @@ -230,33 +230,37 @@ pub fn mach_trap_to_trap(trap: &MachTrap) -> Option { let &MachTrap { offset, code } = trap; Some(TrapInformation { code_offset: offset, - trap_code: match code { - ir::TrapCode::StackOverflow => Trap::StackOverflow, - ir::TrapCode::HeapOutOfBounds => Trap::MemoryOutOfBounds, - ir::TrapCode::HeapMisaligned => Trap::HeapMisaligned, - ir::TrapCode::TableOutOfBounds => Trap::TableOutOfBounds, - ir::TrapCode::IndirectCallToNull => Trap::IndirectCallToNull, - ir::TrapCode::BadSignature => Trap::BadSignature, - ir::TrapCode::IntegerOverflow => Trap::IntegerOverflow, - ir::TrapCode::IntegerDivisionByZero => Trap::IntegerDivisionByZero, - ir::TrapCode::BadConversionToInteger => Trap::BadConversionToInteger, - ir::TrapCode::UnreachableCodeReached => Trap::UnreachableCodeReached, - ir::TrapCode::Interrupt => Trap::Interrupt, - ir::TrapCode::User(ALWAYS_TRAP_CODE) => Trap::AlwaysTrapAdapter, - ir::TrapCode::User(CANNOT_ENTER_CODE) => Trap::CannotEnterComponent, - ir::TrapCode::NullReference => Trap::NullReference, - ir::TrapCode::UnhandledTag => Trap::UnhandledTag, - ir::TrapCode::NullI31Ref => Trap::NullI31Ref, - ir::TrapCode::ContinuationAlreadyConsumed => Trap::ContinuationAlreadyConsumed, - - // These do not get converted to wasmtime traps, since they - // shouldn't ever be hit in theory. Instead of catching and handling - // these, we let the signal crash the process. - ir::TrapCode::User(DEBUG_ASSERT_TRAP_CODE) => return None, - - // these should never be emitted by wasmtime-cranelift - ir::TrapCode::User(_) => unreachable!(), - }, + trap_code: clif_trap_to_env_trap(code)?, + }) +} + +fn clif_trap_to_env_trap(trap: ir::TrapCode) -> Option { + Some(match trap { + ir::TrapCode::StackOverflow => Trap::StackOverflow, + ir::TrapCode::HeapOutOfBounds => Trap::MemoryOutOfBounds, + ir::TrapCode::HeapMisaligned => Trap::HeapMisaligned, + ir::TrapCode::TableOutOfBounds => Trap::TableOutOfBounds, + ir::TrapCode::IndirectCallToNull => Trap::IndirectCallToNull, + ir::TrapCode::BadSignature => Trap::BadSignature, + ir::TrapCode::IntegerOverflow => Trap::IntegerOverflow, + ir::TrapCode::IntegerDivisionByZero => Trap::IntegerDivisionByZero, + ir::TrapCode::BadConversionToInteger => Trap::BadConversionToInteger, + ir::TrapCode::UnreachableCodeReached => Trap::UnreachableCodeReached, + ir::TrapCode::Interrupt => Trap::Interrupt, + ir::TrapCode::User(ALWAYS_TRAP_CODE) => Trap::AlwaysTrapAdapter, + ir::TrapCode::User(CANNOT_ENTER_CODE) => Trap::CannotEnterComponent, + ir::TrapCode::NullReference => Trap::NullReference, + ir::TrapCode::NullI31Ref => Trap::NullI31Ref, + ir::TrapCode::UnhandledTag => Trap::UnhandledTag, + ir::TrapCode::ContinuationAlreadyConsumed => Trap::ContinuationAlreadyConsumed, + + // These do not get converted to wasmtime traps, since they + // shouldn't ever be hit in theory. Instead of catching and handling + // these, we let the signal crash the process. + ir::TrapCode::User(DEBUG_ASSERT_TRAP_CODE) => return None, + + // these should never be emitted by wasmtime-cranelift + ir::TrapCode::User(_) => unreachable!(), }) } @@ -366,6 +370,14 @@ impl BuiltinFunctionSignatures { AbiParam::new(ir::types::I64) } + fn f64(&self) -> AbiParam { + AbiParam::new(ir::types::F64) + } + + fn u8(&self) -> AbiParam { + AbiParam::new(ir::types::I8) + } + fn signature(&self, builtin: BuiltinFunctionIndex) -> Signature { let mut _cur = 0; macro_rules! iter { diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml index 39d7e15d12a2..2faa76868fec 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml @@ -25,7 +25,7 @@ cranelift-entity = { workspace = true } cranelift-bitset = { workspace = true, features = ['enable-serde'] } wasmtime-types = { workspace = true } wasmtime-continuations = { workspace = true } -wasmparser = { workspace = true, features = ['validate', 'serde'] } +wasmparser = { workspace = true, features = ['validate', 'serde', 'features'] } indexmap = { workspace = true, features = ["serde"] } serde = { workspace = true } serde_derive = { workspace = true } diff --git a/crates/environ/src/builtin.rs b/crates/environ/src/builtin.rs index 54d7cc66d60d..813fe813a1be 100644 --- a/crates/environ/src/builtin.rs +++ b/crates/environ/src/builtin.rs @@ -7,9 +7,9 @@ macro_rules! foreach_builtin_function { memory32_grow(vmctx: vmctx, delta: i64, index: i32) -> pointer; // Returns an index for wasm's `table.copy` when both tables are locally // defined. - table_copy(vmctx: vmctx, dst_index: i32, src_index: i32, dst: i32, src: i32, len: i32); + table_copy(vmctx: vmctx, dst_index: i32, src_index: i32, dst: i64, src: i64, len: i64); // Returns an index for wasm's `table.init`. - table_init(vmctx: vmctx, table: i32, elem: i32, dst: i32, src: i32, len: i32); + table_init(vmctx: vmctx, table: i32, elem: i32, dst: i64, src: i64, len: i64); // Returns an index for wasm's `elem.drop`. elem_drop(vmctx: vmctx, elem: i32); // Returns an index for wasm's `memory.copy` @@ -23,11 +23,11 @@ macro_rules! foreach_builtin_function { // Returns an index for wasm's `data.drop` instruction. data_drop(vmctx: vmctx, data: i32); // Returns a table entry after lazily initializing it. - table_get_lazy_init_func_ref(vmctx: vmctx, table: i32, index: i32) -> pointer; + table_get_lazy_init_func_ref(vmctx: vmctx, table: i32, index: i64) -> pointer; // Returns an index for Wasm's `table.grow` instruction for `funcref`s. - table_grow_func_ref(vmctx: vmctx, table: i32, delta: i32, init: pointer) -> i32; + table_grow_func_ref(vmctx: vmctx, table: i32, delta: i64, init: pointer) -> pointer; // Returns an index for Wasm's `table.fill` instruction for `funcref`s. - table_fill_func_ref(vmctx: vmctx, table: i32, dst: i32, val: pointer, len: i32); + table_fill_func_ref(vmctx: vmctx, table: i32, dst: i64, val: pointer, len: i64); // Returns an index for wasm's `memory.atomic.notify` instruction. #[cfg(feature = "threads")] memory_atomic_notify(vmctx: vmctx, memory: i32, addr: i64, count: i32) -> i32; @@ -79,24 +79,26 @@ macro_rules! foreach_builtin_function { #[cfg(feature = "gc")] gc(vmctx: vmctx, root: reference) -> reference; - // Implementation of Wasm's `global.get` instruction for globals - // containing GC references. - #[cfg(feature = "gc")] - gc_ref_global_get(vmctx: vmctx, global: i32) -> reference; - - // Implementation of Wasm's `global.set` instruction for globals - // containing GC references. - #[cfg(feature = "gc")] - gc_ref_global_set(vmctx: vmctx, global: i32, val: reference); - // Returns an index for Wasm's `table.grow` instruction for GC references. #[cfg(feature = "gc")] - table_grow_gc_ref(vmctx: vmctx, table: i32, delta: i32, init: reference) -> i32; + table_grow_gc_ref(vmctx: vmctx, table: i32, delta: i64, init: reference) -> pointer; // Returns an index for Wasm's `table.fill` instruction for GC references. #[cfg(feature = "gc")] - table_fill_gc_ref(vmctx: vmctx, table: i32, dst: i32, val: reference, len: i32); + table_fill_gc_ref(vmctx: vmctx, table: i32, dst: i64, val: reference, len: i64); + + // Raises an unconditional trap. + trap(vmctx: vmctx, code: u8); + // Implementation of `i{32,64}.trunc_f{32,64}_{u,s}` when host trap + // handlers are disabled. These will raise a trap if necessary. Note + // that f32 inputs are always converted to f64 as the argument. Also + // note that the signed-ness of the result is not reflected in the + // type here. + f64_to_i64(vmctx: vmctx, float: f64) -> i64; + f64_to_u64(vmctx: vmctx, float: f64) -> i64; + f64_to_i32(vmctx: vmctx, float: f64) -> i32; + f64_to_u32(vmctx: vmctx, float: f64) -> i32; // Creates a new continuation from a funcref. tc_cont_new(vmctx: vmctx, r: pointer, param_count: i32, result_count: i32) -> pointer; @@ -168,9 +170,9 @@ macro_rules! foreach_builtin_function { // continuation reference and the revision count. // If `unsafe_disable_continuation_linearity_check` is enabled, the revision value is arbitrary. // To denote the continuation being `None`, `init_contref` may be 0. - table_grow_cont_obj(vmctx: vmctx, table: i32, delta: i32, init_contref: pointer, init_revision : i64) -> i32; + table_grow_cont_obj(vmctx: vmctx, table: i32, delta: i64, init_contref: pointer, init_revision : i64) -> pointer; // `value_contref` and `value_revision` together encode the Option, as in previous libcall. - table_fill_cont_obj(vmctx: vmctx, table: i32, dst: i32, value_contref: pointer, value_revision : i64, len: i32); + table_fill_cont_obj(vmctx: vmctx, table: i32, dst: i64, value_contref: pointer, value_revision : i64, len: i64); } }; } diff --git a/crates/environ/src/compile/mod.rs b/crates/environ/src/compile/mod.rs index 0af013a9f11b..59ef62e0bdba 100644 --- a/crates/environ/src/compile/mod.rs +++ b/crates/environ/src/compile/mod.rs @@ -293,6 +293,10 @@ pub trait Compiler: Send + Sync { Aarch64(_) => Architecture::Aarch64, S390x => Architecture::S390x, Riscv64(_) => Architecture::Riscv64, + // XXX: the `object` crate won't successfully build an object + // with relocations and such if it doesn't know the + // architecture, so just pretend we are riscv64. Yolo! + Pulley32 | Pulley64 => Architecture::Riscv64, architecture => { anyhow::bail!("target architecture {:?} is unsupported", architecture,); } diff --git a/crates/environ/src/compile/module_artifacts.rs b/crates/environ/src/compile/module_artifacts.rs index 8449c456d5d1..6d071dc1b317 100644 --- a/crates/environ/src/compile/module_artifacts.rs +++ b/crates/environ/src/compile/module_artifacts.rs @@ -28,6 +28,9 @@ pub struct ObjectBuilder<'a> { /// will go. data: SectionId, + /// The target triple for this compilation. + triple: target_lexicon::Triple, + /// The section identifier for function name information, or otherwise where /// the `name` custom section of wasm is copied into. /// @@ -43,7 +46,11 @@ pub struct ObjectBuilder<'a> { impl<'a> ObjectBuilder<'a> { /// Creates a new builder for the `obj` specified. - pub fn new(mut obj: Object<'a>, tunables: &'a Tunables) -> ObjectBuilder<'a> { + pub fn new( + mut obj: Object<'a>, + tunables: &'a Tunables, + triple: target_lexicon::Triple, + ) -> ObjectBuilder<'a> { let data = obj.add_section( obj.segment_name(StandardSegment::Data).to_vec(), obj::ELF_WASM_DATA.as_bytes().to_vec(), @@ -53,6 +60,7 @@ impl<'a> ObjectBuilder<'a> { obj, tunables, data, + triple, names: None, dwarf: None, } @@ -217,6 +225,12 @@ impl<'a> ObjectBuilder<'a> { self.push_debuginfo(&mut dwarf, &debuginfo); } + let is_pulley = matches!( + self.triple.architecture, + target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 + ); + assert!(!is_pulley || wasm_to_array_trampolines.is_empty()); + Ok(CompiledModuleInfo { module, funcs, @@ -227,6 +241,7 @@ impl<'a> ObjectBuilder<'a> { has_unparsed_debuginfo, code_section_offset: debuginfo.wasm_file.code_section_offset, has_wasm_debuginfo: self.tunables.parse_wasm_debuginfo, + is_pulley, dwarf, }, }) diff --git a/crates/environ/src/compile/module_environ.rs b/crates/environ/src/compile/module_environ.rs index 894b6c6ed068..2fbd94975847 100644 --- a/crates/environ/src/compile/module_environ.rs +++ b/crates/environ/src/compile/module_environ.rs @@ -21,7 +21,9 @@ use wasmparser::{ FuncToValidate, FunctionBody, KnownCustom, NameSectionReader, Naming, Parser, Payload, TypeRef, Validator, ValidatorResources, }; -use wasmtime_types::{ConstExpr, ConstOp, ModuleInternedTypeIndex, SizeOverflow, WasmHeapTopType}; +use wasmtime_types::{ + ConstExpr, ConstOp, IndexType, ModuleInternedTypeIndex, SizeOverflow, WasmHeapTopType, +}; /// Object containing the standalone environment information. pub struct ModuleEnvironment<'a, 'data> { @@ -973,10 +975,14 @@ impl ModuleTranslation<'_> { } fn eval_offset(&mut self, memory_index: MemoryIndex, expr: &ConstExpr) -> Option { - let mem64 = self.module.memory_plans[memory_index].memory.memory64; - match expr.ops() { - &[ConstOp::I32Const(offset)] if !mem64 => Some(offset.unsigned().into()), - &[ConstOp::I64Const(offset)] if mem64 => Some(offset.unsigned()), + match ( + expr.ops(), + self.module.memory_plans[memory_index].memory.idx_type, + ) { + (&[ConstOp::I32Const(offset)], IndexType::I32) => { + Some(offset.unsigned().into()) + } + (&[ConstOp::I64Const(offset)], IndexType::I64) => Some(offset.unsigned()), _ => None, } } @@ -1156,7 +1162,7 @@ impl ModuleTranslation<'_> { // This should be large enough to support very large Wasm // modules with huge funcref tables, but small enough to avoid // OOMs or DoS on truly sparse tables. - const MAX_FUNC_TABLE_SIZE: u32 = 1024 * 1024; + const MAX_FUNC_TABLE_SIZE: u64 = 1024 * 1024; // First convert any element-initialized tables to images of just that // single function if the minimum size of the table allows doing so. @@ -1172,7 +1178,7 @@ impl ModuleTranslation<'_> { .skip(self.module.num_imported_tables), ) { - let table_size = plan.table.minimum; + let table_size = plan.table.limits.min; if table_size > MAX_FUNC_TABLE_SIZE { continue; } @@ -1213,7 +1219,8 @@ impl ModuleTranslation<'_> { // include it in the statically-built array of initial // contents. let offset = match segment.offset.ops() { - &[ConstOp::I32Const(offset)] => offset.unsigned(), + &[ConstOp::I32Const(offset)] => u64::from(offset.unsigned()), + &[ConstOp::I64Const(offset)] => offset.unsigned(), _ => break, }; @@ -1224,14 +1231,17 @@ impl ModuleTranslation<'_> { Some(top) => top, None => break, }; - let table_size = self.module.table_plans[segment.table_index].table.minimum; + let table_size = self.module.table_plans[segment.table_index] + .table + .limits + .min; if top > table_size || top > MAX_FUNC_TABLE_SIZE { break; } match self.module.table_plans[segment.table_index] .table - .wasm_ty + .ref_type .heap_type .top() { diff --git a/crates/environ/src/component.rs b/crates/environ/src/component.rs index 10741a59c5e9..4b72baa71322 100644 --- a/crates/environ/src/component.rs +++ b/crates/environ/src/component.rs @@ -104,6 +104,8 @@ macro_rules! foreach_builtin_component_function { resource_transfer_borrow(vmctx: vmctx, src_idx: u32, src_table: u32, dst_table: u32) -> u32; resource_enter_call(vmctx: vmctx); resource_exit_call(vmctx: vmctx); + + trap(vmctx: vmctx, code: u8); } }; } diff --git a/crates/environ/src/component/compiler.rs b/crates/environ/src/component/compiler.rs index aec715c9d19b..b4320ec407fc 100644 --- a/crates/environ/src/component/compiler.rs +++ b/crates/environ/src/component/compiler.rs @@ -1,5 +1,6 @@ use crate::component::{AllCallFunc, ComponentTranslation, ComponentTypesBuilder, TrampolineIndex}; use crate::prelude::*; +use crate::Tunables; use anyhow::Result; use std::any::Any; @@ -16,5 +17,6 @@ pub trait ComponentCompiler: Send + Sync { component: &ComponentTranslation, types: &ComponentTypesBuilder, trampoline: TrampolineIndex, + tunables: &Tunables, ) -> Result>>; } diff --git a/crates/environ/src/component/translate/inline.rs b/crates/environ/src/component/translate/inline.rs index 0f4dfd9bdcc5..5f50d35691ec 100644 --- a/crates/environ/src/component/translate/inline.rs +++ b/crates/environ/src/component/translate/inline.rs @@ -48,6 +48,7 @@ use crate::component::translate::*; use std::borrow::Cow; use wasmparser::types::{ComponentAnyTypeId, ComponentCoreModuleTypeId}; +use wasmtime_types::IndexType; pub(super) fn run( types: &mut ComponentTypesBuilder, @@ -967,13 +968,19 @@ impl<'a> Inliner<'a> { InstanceModule::Static(idx) => match &memory.item { ExportItem::Index(i) => { let plan = &self.nested_modules[*idx].module.memory_plans[*i]; - plan.memory.memory64 + match plan.memory.idx_type { + IndexType::I32 => false, + IndexType::I64 => true, + } } ExportItem::Name(_) => unreachable!(), }, InstanceModule::Import(ty) => match &memory.item { ExportItem::Name(name) => match types[*ty].exports[name] { - wasmtime_types::EntityType::Memory(m) => m.memory64, + wasmtime_types::EntityType::Memory(m) => match m.idx_type { + IndexType::I32 => false, + IndexType::I64 => true, + }, _ => unreachable!(), }, ExportItem::Index(_) => unreachable!(), diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index 0097f801def8..8af700de421b 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -3073,7 +3073,7 @@ impl<'a> Destination<'a> { &'b self, types: &'b ComponentTypesBuilder, fields: impl IntoIterator + 'b, - ) -> impl Iterator + 'b + ) -> impl Iterator> + 'b where 'a: 'b, { diff --git a/crates/environ/src/gc.rs b/crates/environ/src/gc.rs index c28bfcff8e6f..5119d7eb3159 100644 --- a/crates/environ/src/gc.rs +++ b/crates/environ/src/gc.rs @@ -9,6 +9,12 @@ //! on our various `gc` cargo features is the actual garbage collection //! functions and their associated impact on binary size anyways. +#[cfg(feature = "gc")] +pub mod drc; + +use crate::prelude::*; +use wasmtime_types::{WasmArrayType, WasmStructType}; + /// Discriminant to check whether GC reference is an `i31ref` or not. pub const I31_DISCRIMINANT: u64 = 1; @@ -16,6 +22,126 @@ pub const I31_DISCRIMINANT: u64 = 1; /// with a single bitwise-and operation. pub const NON_NULL_NON_I31_MASK: u64 = !I31_DISCRIMINANT; +/// A trait for getting the layout of a Wasm GC struct or array inside a +/// particular collector. +pub trait GcTypeLayouts { + /// Get this collector's layout for the given array type. + fn array_layout(&self, ty: &WasmArrayType) -> GcArrayLayout; + + /// Get this collector's layout for the given struct type. + fn struct_layout(&self, ty: &WasmStructType) -> GcStructLayout; +} + +/// The layout of a GC-managed object. +#[derive(Clone, Debug)] +pub enum GcLayout { + /// The layout of a GC-managed array object. + Array(GcArrayLayout), + + /// The layout of a GC-managed struct object. + Struct(GcStructLayout), +} + +impl From for GcLayout { + fn from(layout: GcArrayLayout) -> Self { + Self::Array(layout) + } +} + +impl From for GcLayout { + fn from(layout: GcStructLayout) -> Self { + Self::Struct(layout) + } +} + +impl GcLayout { + /// Get the underlying `GcStructLayout`, or panic. + #[track_caller] + pub fn unwrap_struct(&self) -> &GcStructLayout { + match self { + Self::Struct(s) => s, + _ => panic!("GcLayout::unwrap_struct on non-struct GC layout"), + } + } + + /// Get the underlying `GcArrayLayout`, or panic. + #[track_caller] + pub fn unwrap_array(&self) -> &GcArrayLayout { + match self { + Self::Array(a) => a, + _ => panic!("GcLayout::unwrap_array on non-array GC layout"), + } + } +} + +/// The layout of a GC-managed array. +/// +/// This layout is only valid for use with the GC runtime that created it. It is +/// not valid to use one GC runtime's layout with another GC runtime, doing so +/// is memory safe but will lead to general incorrectness like panics and wrong +/// results. +/// +/// All offsets are from the start of the object; that is, the size of the GC +/// header (for example) is included in the offset. +/// +/// All arrays are composed of the generic `VMGcHeader`, followed by +/// collector-specific fields, followed by the contiguous array elements +/// themselves. The array elements must be aligned to the element type's natural +/// alignment. +#[derive(Clone, Debug)] +#[allow(dead_code)] // Not used yet, but added for completeness. +pub struct GcArrayLayout { + /// The size of this array object, ignoring its elements. + pub size: u32, + + /// The alignment of this array. + pub align: u32, + + /// The offset of the array's length. + pub length_field_offset: u32, + + /// The offset from where this array's contiguous elements begin. + pub elems_offset: u32, + + /// The size and natural alignment of each element in this array. + pub elem_size: u32, +} + +impl GcArrayLayout { + /// Get the total size of this array for a given length of elements. + pub fn size_for_len(&self, len: u32) -> u32 { + self.size + len * self.elem_size + } + + /// Get the offset of the `i`th element in an array with this layout. + #[inline] + pub fn elem_offset(&self, i: u32, elem_size: u32) -> u32 { + self.elems_offset + i * elem_size + } +} + +/// The layout for a GC-managed struct type. +/// +/// This layout is only valid for use with the GC runtime that created it. It is +/// not valid to use one GC runtime's layout with another GC runtime, doing so +/// is memory safe but will lead to general incorrectness like panics and wrong +/// results. +/// +/// All offsets are from the start of the object; that is, the size of the GC +/// header (for example) is included in the offset. +#[derive(Clone, Debug)] +pub struct GcStructLayout { + /// The size of this struct. + pub size: u32, + + /// The alignment of this struct. + pub align: u32, + + /// The fields of this struct. The `i`th entry is the `i`th struct field's + /// offset in the struct. + pub fields: Vec, +} + /// The kind of an object in a GC heap. /// /// Note that this type is accessed from Wasm JIT code. diff --git a/crates/environ/src/gc/drc.rs b/crates/environ/src/gc/drc.rs new file mode 100644 index 000000000000..80c683d1b11a --- /dev/null +++ b/crates/environ/src/gc/drc.rs @@ -0,0 +1,100 @@ +//! Layout of Wasm GC objects in the deferred reference-counting collector. + +use super::*; +use wasmtime_types::{WasmStorageType, WasmValType}; + +/// The size of the `VMDrcHeader` header for GC objects. +pub const HEADER_SIZE: u32 = 16; + +/// The align of the `VMDrcHeader` header for GC objects. +pub const HEADER_ALIGN: u32 = 8; + +/// The offset of the length field in a `VMDrcArrayHeader`. +pub const ARRAY_LENGTH_OFFSET: u32 = HEADER_SIZE; + +/// Align `offset` up to `bytes`, updating `max_align` if `align` is the +/// new maximum alignment, and returning the aligned offset. +fn align_up(offset: &mut u32, max_align: &mut u32, align: u32) -> u32 { + debug_assert!(max_align.is_power_of_two()); + debug_assert!(align.is_power_of_two()); + *offset = offset.checked_add(align - 1).unwrap() & !(align - 1); + *max_align = core::cmp::max(*max_align, align); + *offset +} + +/// Define a new field of size and alignment `bytes`, updating the object's +/// total `size` and `align` as necessary. The offset of the new field is +/// returned. +fn field(size: &mut u32, align: &mut u32, bytes: u32) -> u32 { + let offset = align_up(size, align, bytes); + *size += bytes; + offset +} + +fn size_of_wasm_ty(ty: &WasmStorageType) -> u32 { + match ty { + WasmStorageType::I8 => 1, + WasmStorageType::I16 => 2, + WasmStorageType::Val(ty) => match ty { + WasmValType::I32 | WasmValType::F32 | WasmValType::Ref(_) => 4, + WasmValType::I64 | WasmValType::F64 => 8, + WasmValType::V128 => 16, + }, + } +} + +/// The layout of Wasm GC objects in the deferred reference-counting collector. +#[derive(Default)] +pub struct DrcTypeLayouts; + +impl GcTypeLayouts for DrcTypeLayouts { + fn array_layout(&self, ty: &WasmArrayType) -> GcArrayLayout { + let mut size = HEADER_SIZE; + let mut align = HEADER_ALIGN; + + let length_field_offset = field(&mut size, &mut align, 4); + debug_assert_eq!(length_field_offset, ARRAY_LENGTH_OFFSET); + + let elem_size = size_of_wasm_ty(&ty.0.element_type); + let elems_offset = align_up(&mut size, &mut align, elem_size); + + GcArrayLayout { + size, + align, + length_field_offset, + elems_offset, + elem_size, + } + } + + fn struct_layout(&self, ty: &WasmStructType) -> GcStructLayout { + // Process each field, aligning it to its natural alignment. + // + // We don't try and do any fancy field reordering to minimize padding + // (yet?) because (a) the toolchain probably already did that and (b) + // we're just doing the simple thing first. We can come back and improve + // things here if we find that (a) isn't actually holding true in + // practice. + let mut size = HEADER_SIZE; + let mut align = HEADER_ALIGN; + + let fields = ty + .fields + .iter() + .map(|f| { + let field_size = size_of_wasm_ty(&f.element_type); + field(&mut size, &mut align, field_size) + }) + .collect(); + + // Ensure that the final size is a multiple of the alignment, for + // simplicity. + align_up(&mut size, &mut 16, align); + + GcStructLayout { + size, + align, + fields, + } + } +} diff --git a/crates/environ/src/module.rs b/crates/environ/src/module.rs index 4d162267c86b..e1ce82c6594d 100644 --- a/crates/environ/src/module.rs +++ b/crates/environ/src/module.rs @@ -33,6 +33,7 @@ impl MemoryStyle { // page size, but unfortunately that is a little hard to plumb // through here. memory.page_size_log2 >= Memory::DEFAULT_PAGE_SIZE_LOG2 + && tunables.signals_based_traps && match memory.maximum_byte_size() { Ok(mut maximum) => { if tunables.static_memory_bound_is_maximum { @@ -413,10 +414,10 @@ pub enum TableSegmentElements { impl TableSegmentElements { /// Returns the number of elements in this segment. - pub fn len(&self) -> u32 { + pub fn len(&self) -> u64 { match self { - Self::Functions(s) => s.len() as u32, - Self::Expressions(s) => s.len() as u32, + Self::Functions(s) => u64::try_from(s.len()).unwrap(), + Self::Expressions(s) => u64::try_from(s.len()).unwrap(), } } } diff --git a/crates/environ/src/module_artifacts.rs b/crates/environ/src/module_artifacts.rs index 8610029e6654..b479521cc989 100644 --- a/crates/environ/src/module_artifacts.rs +++ b/crates/environ/src/module_artifacts.rs @@ -109,6 +109,10 @@ pub struct Metadata { /// weren't found in the original wasm module itself. pub has_wasm_debuginfo: bool, + /// Whether this artifact contains Pulley bytecode (instead of machine code) + /// or not. + pub is_pulley: bool, + /// Dwarf sections and the offsets at which they're stored in the /// ELF_WASMTIME_DWARF pub dwarf: Vec<(u8, Range)>, diff --git a/crates/environ/src/tunables.rs b/crates/environ/src/tunables.rs index 22b96c4abff8..ddf317124a15 100644 --- a/crates/environ/src/tunables.rs +++ b/crates/environ/src/tunables.rs @@ -62,6 +62,10 @@ pub struct Tunables { /// Whether or not Wasm functions target the winch abi. pub winch_callable: bool, + + /// Whether or not the host will be using native signals (e.g. SIGILL, + /// SIGSEGV, etc) to implement traps. + pub signals_based_traps: bool, } impl Tunables { @@ -113,6 +117,7 @@ impl Tunables { debug_adapter_modules: false, relaxed_simd_deterministic: false, winch_callable: false, + signals_based_traps: true, } } diff --git a/crates/environ/src/vmoffsets.rs b/crates/environ/src/vmoffsets.rs index b529ade7f864..00c17543de67 100644 --- a/crates/environ/src/vmoffsets.rs +++ b/crates/environ/src/vmoffsets.rs @@ -643,7 +643,7 @@ impl VMOffsets

{ /// The size of the `current_elements` field. #[inline] pub fn size_of_vmtable_definition_current_elements(&self) -> u8 { - 4 + self.pointer_size() } /// Return the size of `VMTableDefinition`. diff --git a/crates/fuzzing/src/generators/config.rs b/crates/fuzzing/src/generators/config.rs index d6fd64824af2..aaf12ac49714 100644 --- a/crates/fuzzing/src/generators/config.rs +++ b/crates/fuzzing/src/generators/config.rs @@ -180,7 +180,8 @@ impl Config { self.wasmtime.memory_guaranteed_dense_image_size, )) .allocation_strategy(self.wasmtime.strategy.to_wasmtime()) - .generate_address_map(self.wasmtime.generate_address_map); + .generate_address_map(self.wasmtime.generate_address_map) + .signals_based_traps(self.wasmtime.signals_based_traps); if !self.module_config.config.simd_enabled { cfg.wasm_relaxed_simd(false); @@ -361,20 +362,6 @@ impl Config { unsafe { Ok(Module::deserialize_file(engine, &file).unwrap()) } } - /// Winch doesn't support the same set of wasm proposal as Cranelift at - /// this time, so if winch is selected be sure to disable wasm proposals - /// in `Config` to ensure that Winch can compile the module that - /// wasm-smith generates. - pub fn disable_unimplemented_winch_proposals(&mut self) { - self.module_config.config.simd_enabled = false; - self.module_config.config.relaxed_simd_enabled = false; - self.module_config.config.gc_enabled = false; - self.module_config.config.threads_enabled = false; - self.module_config.config.tail_call_enabled = false; - self.module_config.config.exceptions_enabled = false; - self.module_config.config.reference_types_enabled = false; - } - /// Updates this configuration to forcibly enable async support. Only useful /// in fuzzers which do async calls. pub fn enable_async(&mut self, u: &mut Unstructured<'_>) -> arbitrary::Result<()> { @@ -400,76 +387,9 @@ impl<'a> Arbitrary<'a> for Config { module_config: u.arbitrary()?, }; - if let CompilerStrategy::Winch = config.wasmtime.compiler_strategy { - config.disable_unimplemented_winch_proposals(); - } - - // Wasm-smith implements the most up-to-date version of memory64 where - // it supports 64-bit tables as well, but Wasmtime doesn't support that - // yet, so disable the memory64 proposal in fuzzing for now. - config.module_config.config.memory64_enabled = false; - - // If using the pooling allocator, constrain the memory and module configurations - // to the module limits. - if let InstanceAllocationStrategy::Pooling(pooling) = &mut config.wasmtime.strategy { - // Forcibly don't use the `CustomUnaligned` memory configuration - // with the pooling allocator active. - if let MemoryConfig::CustomUnaligned = config.wasmtime.memory_config { - config.wasmtime.memory_config = MemoryConfig::Normal(u.arbitrary()?); - } - - let cfg = &mut config.module_config.config; - // If the pooling allocator is used, do not allow shared memory to - // be created. FIXME: see - // https://github.com/bytecodealliance/wasmtime/issues/4244. - cfg.threads_enabled = false; - - // Ensure the pooling allocator can support the maximal size of - // memory, picking the smaller of the two to win. - let min_bytes = cfg - .max_memory32_bytes - // memory64_bytes is a u128, but since we are taking the min - // we can truncate it down to a u64. - .min(cfg.max_memory64_bytes.try_into().unwrap_or(u64::MAX)); - let mut min = min_bytes.min(pooling.max_memory_size as u64); - if let MemoryConfig::Normal(cfg) = &config.wasmtime.memory_config { - min = min.min(cfg.static_memory_maximum_size.unwrap_or(0)); - } - pooling.max_memory_size = min as usize; - cfg.max_memory32_bytes = min; - cfg.max_memory64_bytes = min as u128; - - // If traps are disallowed then memories must have at least one page - // of memory so if we still are only allowing 0 pages of memory then - // increase that to one here. - if cfg.disallow_traps { - if pooling.max_memory_size < (1 << 16) { - pooling.max_memory_size = 1 << 16; - cfg.max_memory32_bytes = 1 << 16; - cfg.max_memory64_bytes = 1 << 16; - if let MemoryConfig::Normal(cfg) = &mut config.wasmtime.memory_config { - match &mut cfg.static_memory_maximum_size { - Some(size) => *size = (*size).max(pooling.max_memory_size as u64), - size @ None => *size = Some(pooling.max_memory_size as u64), - } - } - } - // .. additionally update tables - if pooling.table_elements == 0 { - pooling.table_elements = 1; - } - } - - // Don't allow too many linear memories per instance since massive - // virtual mappings can fail to get allocated. - cfg.min_memories = cfg.min_memories.min(10); - cfg.max_memories = cfg.max_memories.min(10); - - // Force this pooling allocator to always be able to accommodate the - // module that may be generated. - pooling.total_memories = cfg.max_memories as u32; - pooling.total_tables = cfg.max_tables as u32; - } + config + .wasmtime + .update_module_config(&mut config.module_config.config, u)?; Ok(config) } @@ -507,6 +427,10 @@ pub struct WasmtimeConfig { /// Configuration for whether wasm is invoked in an async fashion and how /// it's cooperatively time-sliced. pub async_config: AsyncConfig, + + /// Whether or not host signal handlers are enabled for this configuration, + /// aka whether signal handlers are supported. + signals_based_traps: bool, } impl WasmtimeConfig { @@ -532,6 +456,109 @@ impl WasmtimeConfig { self.memory_config = other.memory_config.clone(); } } + + /// Updates `config` to be compatible with `self` and the other way around + /// too. + pub fn update_module_config( + &mut self, + config: &mut wasm_smith::Config, + u: &mut Unstructured<'_>, + ) -> arbitrary::Result<()> { + // Winch doesn't support the same set of wasm proposal as Cranelift at + // this time, so if winch is selected be sure to disable wasm proposals + // in `Config` to ensure that Winch can compile the module that + // wasm-smith generates. + if let CompilerStrategy::Winch = self.compiler_strategy { + config.simd_enabled = false; + config.relaxed_simd_enabled = false; + config.gc_enabled = false; + config.threads_enabled = false; + config.tail_call_enabled = false; + config.exceptions_enabled = false; + config.reference_types_enabled = false; + + // Winch requires host trap handlers to be enabled at this time. + self.signals_based_traps = true; + } + + // If using the pooling allocator, constrain the memory and module configurations + // to the module limits. + if let InstanceAllocationStrategy::Pooling(pooling) = &mut self.strategy { + // Forcibly don't use the `CustomUnaligned` memory configuration + // with the pooling allocator active. + if let MemoryConfig::CustomUnaligned = self.memory_config { + self.memory_config = MemoryConfig::Normal(u.arbitrary()?); + } + + // If the pooling allocator is used, do not allow shared memory to + // be created. FIXME: see + // https://github.com/bytecodealliance/wasmtime/issues/4244. + config.threads_enabled = false; + + // Ensure the pooling allocator can support the maximal size of + // memory, picking the smaller of the two to win. + let min_bytes = config + .max_memory32_bytes + // memory64_bytes is a u128, but since we are taking the min + // we can truncate it down to a u64. + .min(config.max_memory64_bytes.try_into().unwrap_or(u64::MAX)); + let mut min = min_bytes.min(pooling.max_memory_size as u64); + if let MemoryConfig::Normal(cfg) = &self.memory_config { + min = min.min(cfg.static_memory_maximum_size.unwrap_or(0)); + } + pooling.max_memory_size = min as usize; + config.max_memory32_bytes = min; + config.max_memory64_bytes = min as u128; + + // If traps are disallowed then memories must have at least one page + // of memory so if we still are only allowing 0 pages of memory then + // increase that to one here. + if config.disallow_traps { + if pooling.max_memory_size < (1 << 16) { + pooling.max_memory_size = 1 << 16; + config.max_memory32_bytes = 1 << 16; + config.max_memory64_bytes = 1 << 16; + if let MemoryConfig::Normal(cfg) = &mut self.memory_config { + match &mut cfg.static_memory_maximum_size { + Some(size) => *size = (*size).max(pooling.max_memory_size as u64), + size @ None => *size = Some(pooling.max_memory_size as u64), + } + } + } + // .. additionally update tables + if pooling.table_elements == 0 { + pooling.table_elements = 1; + } + } + + // Don't allow too many linear memories per instance since massive + // virtual mappings can fail to get allocated. + config.min_memories = config.min_memories.min(10); + config.max_memories = config.max_memories.min(10); + + // Force this pooling allocator to always be able to accommodate the + // module that may be generated. + pooling.total_memories = config.max_memories as u32; + pooling.total_tables = config.max_tables as u32; + } + + if !self.signals_based_traps { + // At this time shared memories require a "static" memory + // configuration but when signals-based traps are disabled all + // memories are forced to the "dynamic" configuration. This is + // fixable with some more work on the bounds-checks side of things + // to do a full bounds check even on static memories, but that's + // left for a future PR. + config.threads_enabled = false; + + // Spectre-based heap mitigations require signal handlers so this + // must always be disabled if signals-based traps are disabled. + if let MemoryConfig::Normal(cfg) = &mut self.memory_config { + cfg.cranelift_enable_heap_access_spectre_mitigations = None; + } + } + Ok(()) + } } #[derive(Arbitrary, Clone, Debug, PartialEq, Eq, Hash)] diff --git a/crates/fuzzing/src/generators/pooling_config.rs b/crates/fuzzing/src/generators/pooling_config.rs index 0e327bce3724..46e588ca05b4 100644 --- a/crates/fuzzing/src/generators/pooling_config.rs +++ b/crates/fuzzing/src/generators/pooling_config.rs @@ -14,7 +14,7 @@ pub struct PoolingAllocationConfig { pub total_stacks: u32, pub max_memory_size: usize, - pub table_elements: u32, + pub table_elements: usize, pub component_instance_size: usize, pub max_memories_per_component: u32, @@ -79,7 +79,7 @@ impl<'a> Arbitrary<'a> for PoolingAllocationConfig { const MAX_COUNT: u32 = 100; const MAX_TABLES: u32 = 100; const MAX_MEMORIES: u32 = 100; - const MAX_ELEMENTS: u32 = 1000; + const MAX_ELEMENTS: usize = 1000; const MAX_MEMORY_SIZE: usize = 10 * (1 << 20); // 10 MiB const MAX_SIZE: usize = 1 << 20; // 1 MiB const MAX_INSTANCE_MEMORIES: u32 = 10; diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index d28ebfd3c9f2..6cc1e586c9aa 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -116,8 +116,13 @@ impl ResourceLimiter for StoreLimits { Ok(self.alloc(desired - current)) } - fn table_growing(&mut self, current: u32, desired: u32, _maximum: Option) -> Result { - let delta = (desired - current) as usize * std::mem::size_of::(); + fn table_growing( + &mut self, + current: usize, + desired: usize, + _maximum: Option, + ) -> Result { + let delta = (desired - current) * std::mem::size_of::(); Ok(self.alloc(delta)) } } @@ -484,7 +489,13 @@ impl DiffEqResult { // of the two instances, so `None` is returned and nothing else is // compared. (Err(lhs), Err(rhs)) => { - let err = rhs.downcast::().expect("not a trap"); + let err = match rhs.downcast::() { + Ok(trap) => trap, + Err(err) => { + log::debug!("rhs failed: {err:?}"); + return DiffEqResult::Failed; + } + }; let poisoned = err == Trap::StackOverflow || lhs_engine.is_stack_overflow(&lhs); if poisoned { @@ -494,8 +505,8 @@ impl DiffEqResult { DiffEqResult::Failed } // A real bug is found if only one side fails. - (Ok(_), Err(_)) => panic!("only the `rhs` failed for this input"), - (Err(_), Ok(_)) => panic!("only the `lhs` failed for this input"), + (Ok(_), Err(err)) => panic!("only the `rhs` failed for this input: {err:?}"), + (Err(err), Ok(_)) => panic!("only the `lhs` failed for this input: {err:?}"), } } } diff --git a/crates/fuzzing/src/oracles/diff_wasmtime.rs b/crates/fuzzing/src/oracles/diff_wasmtime.rs index b232b0e8d1bd..538cb1fdd648 100644 --- a/crates/fuzzing/src/oracles/diff_wasmtime.rs +++ b/crates/fuzzing/src/oracles/diff_wasmtime.rs @@ -24,11 +24,9 @@ impl WasmtimeEngine { config: &mut generators::Config, compiler_strategy: CompilerStrategy, ) -> arbitrary::Result { - if let CompilerStrategy::Winch = compiler_strategy { - config.disable_unimplemented_winch_proposals(); - } let mut new_config = u.arbitrary::()?; new_config.compiler_strategy = compiler_strategy; + new_config.update_module_config(&mut config.module_config.config, u)?; new_config.make_compatible_with(&config.wasmtime); let config = generators::Config { diff --git a/crates/test-programs/src/bin/api_proxy_streaming.rs b/crates/test-programs/src/bin/api_proxy_streaming.rs index 328e8a12d525..39b17827264a 100644 --- a/crates/test-programs/src/bin/api_proxy_streaming.rs +++ b/crates/test-programs/src/bin/api_proxy_streaming.rs @@ -318,8 +318,8 @@ mod executor { http::{ outgoing_handler, types::{ - self, IncomingBody, IncomingResponse, InputStream, OutgoingBody, OutgoingRequest, - OutputStream, + self, FutureTrailers, IncomingBody, IncomingResponse, InputStream, OutgoingBody, + OutgoingRequest, OutputStream, }, }, io::{self, streams::StreamError}, @@ -465,42 +465,102 @@ mod executor { } pub fn incoming_body(body: IncomingBody) -> impl Stream>> { - struct Incoming(Option<(InputStream, IncomingBody)>); + enum Inner { + Stream { + stream: InputStream, + body: IncomingBody, + }, + Trailers(FutureTrailers), + Closed, + } + + struct Incoming(Inner); impl Drop for Incoming { fn drop(&mut self) { - if let Some((stream, body)) = self.0.take() { - drop(stream); - IncomingBody::finish(body); + match mem::replace(&mut self.0, Inner::Closed) { + Inner::Stream { stream, body } => { + drop(stream); + IncomingBody::finish(body); + } + Inner::Trailers(_) | Inner::Closed => {} } } } stream::poll_fn({ let stream = body.stream().expect("response body should be readable"); - let pair = Incoming(Some((stream, body))); + let mut incoming = Incoming(Inner::Stream { stream, body }); move |context| { - if let Some((stream, _)) = &pair.0 { - match stream.read(READ_SIZE) { - Ok(buffer) => { - if buffer.is_empty() { - WAKERS - .lock() - .unwrap() - .push((stream.subscribe(), context.waker().clone())); - Poll::Pending - } else { - Poll::Ready(Some(Ok(buffer))) + loop { + match &incoming.0 { + Inner::Stream { stream, .. } => match stream.read(READ_SIZE) { + Ok(buffer) => { + return if buffer.is_empty() { + WAKERS + .lock() + .unwrap() + .push((stream.subscribe(), context.waker().clone())); + Poll::Pending + } else { + Poll::Ready(Some(Ok(buffer))) + }; + } + Err(StreamError::Closed) => { + let Inner::Stream { stream, body } = + mem::replace(&mut incoming.0, Inner::Closed) + else { + unreachable!(); + }; + drop(stream); + incoming.0 = Inner::Trailers(IncomingBody::finish(body)); + } + Err(StreamError::LastOperationFailed(error)) => { + return Poll::Ready(Some(Err(anyhow!( + "{}", + error.to_debug_string() + )))); + } + }, + + Inner::Trailers(trailers) => { + match trailers.get() { + Some(Ok(trailers)) => { + incoming.0 = Inner::Closed; + match trailers { + Ok(Some(_)) => { + // Currently, we just ignore any trailers. TODO: Add a test that + // expects trailers and verify they match the expected contents. + } + Ok(None) => { + // No trailers; nothing else to do. + } + Err(error) => { + // Error reading the trailers: pass it on to the application. + return Poll::Ready(Some(Err(anyhow!("{error:?}")))); + } + } + } + Some(Err(_)) => { + // Should only happen if we try to retrieve the trailers twice, i.e. a bug in + // this code. + unreachable!(); + } + None => { + WAKERS + .lock() + .unwrap() + .push((trailers.subscribe(), context.waker().clone())); + return Poll::Pending; + } } } - Err(StreamError::Closed) => Poll::Ready(None), - Err(StreamError::LastOperationFailed(error)) => { - Poll::Ready(Some(Err(anyhow!("{}", error.to_debug_string())))) + + Inner::Closed => { + return Poll::Ready(None); } } - } else { - Poll::Ready(None) } } }) diff --git a/crates/test-programs/src/bin/preview2_tcp_streams.rs b/crates/test-programs/src/bin/preview2_tcp_streams.rs index 688827be661e..c756958968d4 100644 --- a/crates/test-programs/src/bin/preview2_tcp_streams.rs +++ b/crates/test-programs/src/bin/preview2_tcp_streams.rs @@ -25,6 +25,31 @@ fn test_tcp_input_stream_should_be_closed_by_remote_shutdown( }); } +/// InputStream::read should return `StreamError::Closed` after the connection has been shut down locally. +fn test_tcp_input_stream_should_be_closed_by_local_shutdown( + net: &Network, + family: IpAddressFamily, +) { + setup(net, family, |server, client| { + // On Linux, `recv` continues to work even after `shutdown(sock, SHUT_RD)` + // has been called. To properly test that this behavior doesn't happen in + // WASI, we make sure there's some data to read by the client: + server.output.blocking_write_util(b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.").unwrap(); + + // Wait for the data to reach the client: + client.input.subscribe().block(); + + // Shut down socket locally: + client.socket.shutdown(ShutdownType::Receive).unwrap(); + + // The input stream should immediately signal StreamError::Closed. + assert!(matches!(client.input.read(10), Err(StreamError::Closed))); + + // Stream should still be closed, even when requesting 0 bytes: + assert!(matches!(client.input.read(0), Err(StreamError::Closed))); + }); +} + /// OutputStream should return `StreamError::Closed` after the connection has been locally shut down for sending. fn test_tcp_output_stream_should_be_closed_by_local_shutdown( net: &Network, @@ -54,14 +79,50 @@ fn test_tcp_output_stream_should_be_closed_by_local_shutdown( }); } +/// Calling `shutdown` while the OutputStream is in the middle of a background write should not cause that write to be lost. +fn test_tcp_shutdown_should_not_lose_data(net: &Network, family: IpAddressFamily) { + setup(net, family, |server, client| { + // Minimize the local send buffer: + client.socket.set_send_buffer_size(1024).unwrap(); + let small_buffer_size = client.socket.send_buffer_size().unwrap(); + + // Create a significantly bigger buffer, so that we can be pretty sure the `write` won't finish immediately: + let big_buffer_size = client + .output + .check_write() + .unwrap() + .min(100 * small_buffer_size); + assert!(big_buffer_size > small_buffer_size); + let outgoing_data = vec![0; big_buffer_size as usize]; + + // Submit the oversized buffer and immediately initiate the shutdown: + client.output.write(&outgoing_data).unwrap(); + client.socket.shutdown(ShutdownType::Send).unwrap(); + + // The peer should receive _all_ data: + let incoming_data = server.input.blocking_read_to_end().unwrap(); + assert_eq!( + outgoing_data.len(), + incoming_data.len(), + "Received data should match the sent data" + ); + }); +} + fn main() { let net = Network::default(); test_tcp_input_stream_should_be_closed_by_remote_shutdown(&net, IpAddressFamily::Ipv4); test_tcp_input_stream_should_be_closed_by_remote_shutdown(&net, IpAddressFamily::Ipv6); + test_tcp_input_stream_should_be_closed_by_local_shutdown(&net, IpAddressFamily::Ipv4); + test_tcp_input_stream_should_be_closed_by_local_shutdown(&net, IpAddressFamily::Ipv6); + test_tcp_output_stream_should_be_closed_by_local_shutdown(&net, IpAddressFamily::Ipv4); test_tcp_output_stream_should_be_closed_by_local_shutdown(&net, IpAddressFamily::Ipv6); + + test_tcp_shutdown_should_not_lose_data(&net, IpAddressFamily::Ipv4); + test_tcp_shutdown_should_not_lose_data(&net, IpAddressFamily::Ipv6); } struct Connection { diff --git a/crates/test-programs/src/sockets.rs b/crates/test-programs/src/sockets.rs index c77ad8d7f819..0fcccaaab4af 100644 --- a/crates/test-programs/src/sockets.rs +++ b/crates/test-programs/src/sockets.rs @@ -29,6 +29,19 @@ impl Pollable { } } +impl InputStream { + pub fn blocking_read_to_end(&self) -> Result, crate::wasi::io::error::Error> { + let mut data = vec![]; + loop { + match self.blocking_read(1024 * 1024) { + Ok(chunk) => data.extend(chunk), + Err(StreamError::Closed) => return Ok(data), + Err(StreamError::LastOperationFailed(e)) => return Err(e), + } + } + } +} + impl OutputStream { pub fn blocking_write_util(&self, mut bytes: &[u8]) -> Result<(), StreamError> { let timeout = monotonic_clock::subscribe_duration(TIMEOUT_NS); diff --git a/crates/types/src/error.rs b/crates/types/src/error.rs index 37e5043e0e1b..27c25bbcc036 100644 --- a/crates/types/src/error.rs +++ b/crates/types/src/error.rs @@ -1,5 +1,6 @@ -use alloc::string::String; +use alloc::string::{String, ToString}; use core::fmt; +use core::num::TryFromIntError; /// A WebAssembly translation error. /// @@ -52,6 +53,16 @@ impl From for WasmError { } } +impl From for WasmError { + /// Convert from a `TryFromIntError` to a `WasmError`. + fn from(e: TryFromIntError) -> Self { + Self::InvalidWebAssembly { + message: e.to_string(), + offset: 0, + } + } +} + /// A convenient alias for a `Result` that uses `WasmError` as the error type. pub type WasmResult = Result; diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 98c73e9d0081..e4eb6626201c 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -1631,15 +1631,30 @@ impl ConstOp { } } +/// The type that can be used to index into [Memory] and [Table]. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub enum IndexType { + I32, + I64, +} + +/// The size range of resizeable storage associated with [Memory] types and [Table] types. +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] +pub struct Limits { + pub min: u64, + pub max: Option, +} + /// WebAssembly table. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] pub struct Table { + /// The type of the index used to access the table. + pub idx_type: IndexType, + /// Tables are constrained by limits for their minimum and optionally maximum size. + /// The limits are given in numbers of entries. + pub limits: Limits, /// The table elements' Wasm type. - pub wasm_ty: WasmRefType, - /// The minimum number of elements in the table. - pub minimum: u32, - /// The maximum number of elements in the table. - pub maximum: Option, + pub ref_type: WasmRefType, } impl TypeTrace for Table { @@ -1648,9 +1663,9 @@ impl TypeTrace for Table { F: FnMut(EngineOrModuleTypeIndex) -> Result<(), E>, { let Table { - wasm_ty, - minimum: _, - maximum: _, + ref_type: wasm_ty, + idx_type: _, + limits: _, } = self; wasm_ty.trace(func) } @@ -1660,9 +1675,9 @@ impl TypeTrace for Table { F: FnMut(&mut EngineOrModuleTypeIndex) -> Result<(), E>, { let Table { - wasm_ty, - minimum: _, - maximum: _, + ref_type: wasm_ty, + idx_type: _, + limits: _, } = self; wasm_ty.trace_mut(func) } @@ -1671,14 +1686,13 @@ impl TypeTrace for Table { /// WebAssembly linear memory. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)] pub struct Memory { - /// The minimum number of pages in the memory. - pub minimum: u64, - /// The maximum number of pages in the memory. - pub maximum: Option, + /// The type of the index used to access the memory. + pub idx_type: IndexType, + /// The limits constrain the minimum and optionally the maximum size of a memory. + /// The limits are given in units of page size. + pub limits: Limits, /// Whether the memory may be shared between multiple threads. pub shared: bool, - /// Whether or not this is a 64-bit memory - pub memory64: bool, /// The log2 of this memory's page size, in bytes. /// /// By default the page size is 64KiB (0x10000; 2**16; 1<<16; 65536) but the @@ -1708,7 +1722,8 @@ impl Memory { /// `u64` return type. This means that the memory can't be allocated but /// it's deferred to the caller to how to deal with that. pub fn minimum_byte_size(&self) -> Result { - self.minimum + self.limits + .min .checked_mul(self.page_size()) .ok_or(SizeOverflow) } @@ -1728,7 +1743,7 @@ impl Memory { /// `u64` return type. This means that the memory can't be allocated but /// it's deferred to the caller to how to deal with that. pub fn maximum_byte_size(&self) -> Result { - match self.maximum { + match self.limits.max { Some(max) => max.checked_mul(self.page_size()).ok_or(SizeOverflow), None => { let min = self.minimum_byte_size()?; @@ -1752,7 +1767,8 @@ impl Memory { /// /// For example 32-bit linear memories return `1<<32` from this method. pub fn max_size_based_on_index_type(&self) -> u64 { - if self.memory64 { + match self.idx_type { + IndexType::I64 => // Note that the true maximum size of a 64-bit linear memory, in // bytes, cannot be represented in a `u64`. That would require a u65 // to store `1<<64`. Despite that no system can actually allocate a @@ -1760,9 +1776,10 @@ impl Memory { // the kernel fit in a single Wasm page of linear memory". Shouldn't // ever actually be possible but it provides a number to serve as an // effective maximum. - 0_u64.wrapping_sub(self.page_size()) - } else { - WASM32_MAX_SIZE + { + 0_u64.wrapping_sub(self.page_size()) + } + IndexType::I32 => WASM32_MAX_SIZE, } } } @@ -1781,16 +1798,23 @@ impl std::error::Error for SizeOverflow {} impl From for Memory { fn from(ty: wasmparser::MemoryType) -> Memory { + let idx_type = match ty.memory64 { + false => IndexType::I32, + true => IndexType::I64, + }; + let limits = Limits { + min: ty.initial, + max: ty.maximum, + }; let page_size_log2 = u8::try_from(ty.page_size_log2.unwrap_or(16)).unwrap(); debug_assert!( page_size_log2 == 16 || page_size_log2 == 0, "invalid page_size_log2: {page_size_log2}; must be 16 or 0" ); Memory { - minimum: ty.initial, - maximum: ty.maximum, + idx_type, + limits, shared: ty.shared, - memory64: ty.memory64, page_size_log2, } } @@ -1854,13 +1878,18 @@ pub trait TypeConvert { /// Converts a wasmparser table type into a wasmtime type fn convert_table_type(&self, ty: &wasmparser::TableType) -> WasmResult { - if ty.table64 { - return Err(wasm_unsupported!("wasm memory64: 64-bit table type")); - } + let idx_type = match ty.table64 { + false => IndexType::I32, + true => IndexType::I64, + }; + let limits = Limits { + min: ty.initial.try_into().unwrap(), + max: ty.maximum.map(|i| i.try_into().unwrap()), + }; Ok(Table { - wasm_ty: self.convert_ref_type(ty.element_type), - minimum: ty.initial.try_into().unwrap(), - maximum: ty.maximum.map(|i| i.try_into().unwrap()), + idx_type, + limits, + ref_type: self.convert_ref_type(ty.element_type), }) } diff --git a/crates/wasi-http/src/body.rs b/crates/wasi-http/src/body.rs index 5f16f42393f0..5913a4922df9 100644 --- a/crates/wasi-http/src/body.rs +++ b/crates/wasi-http/src/body.rs @@ -347,12 +347,9 @@ impl Subscribe for HostFutureTrailers { // were reached. It's up to us now to complete the body. Ok(StreamEnd::Remaining(b)) => body.body = IncomingBodyState::Start(b), - // Technically this shouldn't be possible as the sender - // shouldn't get destroyed without receiving a message. Handle - // this just in case though. + // This means there were no trailers present. Err(_) => { - debug_assert!(false, "should be unreachable"); - *self = HostFutureTrailers::Done(Err(types::ErrorCode::ConnectionTerminated)); + *self = HostFutureTrailers::Done(Ok(None)); } } } diff --git a/crates/wasi/src/filesystem.rs b/crates/wasi/src/filesystem.rs index a924fa96a70c..2c656b6997e5 100644 --- a/crates/wasi/src/filesystem.rs +++ b/crates/wasi/src/filesystem.rs @@ -361,7 +361,7 @@ impl HostInputStream for FileInputStream { // background tasks. Also, the guest is only blocked if // the stream was dropped mid-read, which we don't expect to // occur frequently. - task.abort_wait().await; + task.cancel().await; } _ => {} } @@ -558,7 +558,7 @@ impl HostOutputStream for FileOutputStream { // background tasks. Also, the guest is only blocked if // the stream was dropped mid-write, which we don't expect to // occur frequently. - task.abort_wait().await; + task.cancel().await; } _ => {} } diff --git a/crates/wasi/src/host/tcp.rs b/crates/wasi/src/host/tcp.rs index 2f20cdc2590e..143ea607eb1c 100644 --- a/crates/wasi/src/host/tcp.rs +++ b/crates/wasi/src/host/tcp.rs @@ -298,7 +298,7 @@ where ShutdownType::Send => std::net::Shutdown::Write, ShutdownType::Both => std::net::Shutdown::Both, }; - Ok(socket.shutdown(how)?) + socket.shutdown(how) } fn drop(&mut self, this: Resource) -> Result<(), anyhow::Error> { diff --git a/crates/wasi/src/pipe.rs b/crates/wasi/src/pipe.rs index 4b723cc0c13a..83a389d90232 100644 --- a/crates/wasi/src/pipe.rs +++ b/crates/wasi/src/pipe.rs @@ -193,7 +193,7 @@ impl HostInputStream for AsyncReadStream { async fn cancel(&mut self) { match self.join_handle.take() { - Some(task) => _ = task.abort_wait().await, + Some(task) => _ = task.cancel().await, None => {} } } diff --git a/crates/wasi/src/runtime.rs b/crates/wasi/src/runtime.rs index dc29fef97239..b1fb7839618f 100644 --- a/crates/wasi/src/runtime.rs +++ b/crates/wasi/src/runtime.rs @@ -42,8 +42,9 @@ pub struct AbortOnDropJoinHandle(tokio::task::JoinHandle); impl AbortOnDropJoinHandle { /// Abort the task and wait for it to finish. Optionally returns the result /// of the task if it ran to completion prior to being aborted. - pub(crate) async fn abort_wait(mut self) -> Option { + pub(crate) async fn cancel(mut self) -> Option { self.0.abort(); + match (&mut self.0).await { Ok(value) => Some(value), Err(err) if err.is_cancelled() => None, diff --git a/crates/wasi/src/tcp.rs b/crates/wasi/src/tcp.rs index 32feef95a683..44ba68416c07 100644 --- a/crates/wasi/src/tcp.rs +++ b/crates/wasi/src/tcp.rs @@ -3,10 +3,10 @@ use crate::host::network; use crate::network::SocketAddressFamily; use crate::runtime::{with_ambient_tokio_runtime, AbortOnDropJoinHandle}; use crate::{ - HostInputStream, HostOutputStream, InputStream, OutputStream, SocketResult, StreamError, - Subscribe, + HostInputStream, HostOutputStream, InputStream, OutputStream, SocketError, SocketResult, + StreamError, Subscribe, }; -use anyhow::{Error, Result}; +use anyhow::Result; use cap_net_ext::AddressFamily; use futures::Future; use io_lifetimes::views::SocketlikeView; @@ -15,10 +15,11 @@ use rustix::io::Errno; use rustix::net::sockopt; use std::io; use std::mem; -use std::net::SocketAddr; +use std::net::{Shutdown, SocketAddr}; use std::pin::Pin; use std::sync::Arc; use std::task::Poll; +use tokio::sync::Mutex; /// Value taken from rust std library. const DEFAULT_BACKLOG: u32 = 128; @@ -54,7 +55,13 @@ enum TcpState { ConnectReady(io::Result), /// An outgoing connection has been established. - Connected(Arc), + Connected { + stream: Arc, + + // WASI is single threaded, so in practice these Mutexes should never be contended: + reader: Arc>, + writer: Arc>, + }, Closed, } @@ -72,7 +79,7 @@ impl std::fmt::Debug for TcpState { .finish(), Self::Connecting(_) => f.debug_tuple("Connecting").finish(), Self::ConnectReady(_) => f.debug_tuple("ConnectReady").finish(), - Self::Connected(_) => f.debug_tuple("Connected").finish(), + Self::Connected { .. } => f.debug_tuple("Connected").finish(), Self::Closed => write!(f, "Closed"), } } @@ -145,7 +152,9 @@ impl TcpSocket { TcpState::Default(socket) | TcpState::Bound(socket) => { Ok(socket.as_socketlike_view::()) } - TcpState::Connected(stream) => Ok(stream.as_socketlike_view::()), + TcpState::Connected { stream, .. } => { + Ok(stream.as_socketlike_view::()) + } TcpState::Listening { listener, .. } => { Ok(listener.as_socketlike_view::()) } @@ -277,9 +286,15 @@ impl TcpSocket { match result { Ok(stream) => { let stream = Arc::new(stream); - self.tcp_state = TcpState::Connected(stream.clone()); - let input: InputStream = Box::new(TcpReadStream::new(stream.clone())); - let output: OutputStream = Box::new(TcpWriteStream::new(stream)); + let reader = Arc::new(Mutex::new(TcpReader::new(stream.clone()))); + let writer = Arc::new(Mutex::new(TcpWriter::new(stream.clone()))); + self.tcp_state = TcpState::Connected { + stream, + reader: reader.clone(), + writer: writer.clone(), + }; + let input: InputStream = Box::new(TcpReadStream(reader)); + let output: OutputStream = Box::new(TcpWriteStream(writer)); Ok((input, output)) } Err(err) => { @@ -427,9 +442,19 @@ impl TcpSocket { let client = Arc::new(client); - let input: InputStream = Box::new(TcpReadStream::new(client.clone())); - let output: OutputStream = Box::new(TcpWriteStream::new(client.clone())); - let tcp_socket = TcpSocket::from_state(TcpState::Connected(client), self.family)?; + let reader = Arc::new(Mutex::new(TcpReader::new(client.clone()))); + let writer = Arc::new(Mutex::new(TcpWriter::new(client.clone()))); + + let input: InputStream = Box::new(TcpReadStream(reader.clone())); + let output: OutputStream = Box::new(TcpWriteStream(writer.clone())); + let tcp_socket = TcpSocket::from_state( + TcpState::Connected { + stream: client, + reader, + writer, + }, + self.family, + )?; Ok((tcp_socket, input, output)) } @@ -446,7 +471,7 @@ impl TcpSocket { pub fn remote_address(&self) -> SocketResult { let view = match self.tcp_state { - TcpState::Connected(..) => self.as_std_view()?, + TcpState::Connected { .. } => self.as_std_view()?, TcpState::Connecting(..) | TcpState::ConnectReady(..) => { return Err(ErrorCode::ConcurrencyConflict.into()) } @@ -613,20 +638,19 @@ impl TcpSocket { Ok(()) } - pub fn shutdown(&self, how: std::net::Shutdown) -> io::Result<()> { - let stream = match &self.tcp_state { - TcpState::Connected(stream) => stream, - _ => { - return Err(io::Error::new( - io::ErrorKind::NotConnected, - "socket not connected", - )) - } + pub fn shutdown(&self, how: Shutdown) -> SocketResult<()> { + let TcpState::Connected { reader, writer, .. } = &self.tcp_state else { + return Err(ErrorCode::InvalidState.into()); }; - stream - .as_socketlike_view::() - .shutdown(how)?; + if let Shutdown::Both | Shutdown::Read = how { + try_lock_for_socket(reader)?.shutdown(); + } + + if let Shutdown::Both | Shutdown::Write = how { + try_lock_for_socket(writer)?.shutdown(); + } + Ok(()) } } @@ -641,7 +665,7 @@ impl Subscribe for TcpSocket { | TcpState::ListenStarted(..) | TcpState::ConnectReady(..) | TcpState::Closed - | TcpState::Connected(..) => { + | TcpState::Connected { .. } => { // No async operation in progress. } TcpState::Connecting(future) => { @@ -664,22 +688,18 @@ impl Subscribe for TcpSocket { } } -struct TcpReadStream { +struct TcpReader { stream: Arc, closed: bool, } -impl TcpReadStream { +impl TcpReader { fn new(stream: Arc) -> Self { Self { stream, closed: false, } } -} - -#[async_trait::async_trait] -impl HostInputStream for TcpReadStream { fn read(&mut self, size: usize) -> Result { if self.closed { return Err(StreamError::Closed); @@ -710,37 +730,57 @@ impl HostInputStream for TcpReadStream { buf.truncate(n); Ok(buf.freeze()) } -} -#[async_trait::async_trait] -impl Subscribe for TcpReadStream { + fn shutdown(&mut self) { + native_shutdown(&self.stream, Shutdown::Read); + self.closed = true; + } + async fn ready(&mut self) { if self.closed { return; } + self.stream.readable().await.unwrap(); } } +struct TcpReadStream(Arc>); + +#[async_trait::async_trait] +impl HostInputStream for TcpReadStream { + fn read(&mut self, size: usize) -> Result { + try_lock_for_stream(&self.0)?.read(size) + } +} + +#[async_trait::async_trait] +impl Subscribe for TcpReadStream { + async fn ready(&mut self) { + self.0.lock().await.ready().await + } +} + const SOCKET_READY_SIZE: usize = 1024 * 1024 * 1024; -struct TcpWriteStream { +struct TcpWriter { stream: Arc, - last_write: LastWrite, + state: WriteState, } -enum LastWrite { - Waiting(AbortOnDropJoinHandle>), - Error(Error), - Done, +enum WriteState { + Ready, + Writing(AbortOnDropJoinHandle>), + Closing(AbortOnDropJoinHandle>), Closed, + Error(io::Error), } -impl TcpWriteStream { +impl TcpWriter { fn new(stream: Arc) -> Self { Self { stream, - last_write: LastWrite::Done, + state: WriteState::Ready, } } @@ -761,10 +801,10 @@ impl TcpWriteStream { /// Write `bytes` in a background task, remembering the task handle for use in a future call to /// `write_ready` fn background_write(&mut self, mut bytes: bytes::Bytes) { - assert!(matches!(self.last_write, LastWrite::Done)); + assert!(matches!(self.state, WriteState::Ready)); let stream = self.stream.clone(); - self.last_write = LastWrite::Waiting(crate::runtime::spawn(async move { + self.state = WriteState::Writing(crate::runtime::spawn(async move { // Note: we are not using the AsyncWrite impl here, and instead using the TcpStream // primitive try_write, which goes directly to attempt a write with mio. This has // two advantages: 1. this operation takes a &TcpStream instead of a &mut TcpStream @@ -784,14 +824,12 @@ impl TcpWriteStream { Ok(()) })); } -} -#[async_trait::async_trait] -impl HostOutputStream for TcpWriteStream { fn write(&mut self, mut bytes: bytes::Bytes) -> Result<(), StreamError> { - match self.last_write { - LastWrite::Done => {} - LastWrite::Waiting(_) | LastWrite::Error(_) | LastWrite::Closed => { + match self.state { + WriteState::Ready => {} + WriteState::Closed => return Err(StreamError::Closed), + WriteState::Writing(_) | WriteState::Closing(_) | WriteState::Error(_) => { return Err(StreamError::Trap(anyhow::anyhow!( "unpermitted: must call check_write first" ))); @@ -812,7 +850,7 @@ impl HostOutputStream for TcpWriteStream { } Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => { - self.last_write = LastWrite::Closed; + self.state = WriteState::Closed; return Err(StreamError::Closed); } @@ -827,23 +865,30 @@ impl HostOutputStream for TcpWriteStream { // `flush` is a no-op here, as we're not managing any internal buffer. Additionally, // `write_ready` will join the background write task if it's active, so following `flush` // with `write_ready` will have the desired effect. - match self.last_write { - LastWrite::Done | LastWrite::Waiting(_) | LastWrite::Error(_) => Ok(()), - LastWrite::Closed => Err(StreamError::Closed), + match self.state { + WriteState::Ready + | WriteState::Writing(_) + | WriteState::Closing(_) + | WriteState::Error(_) => Ok(()), + WriteState::Closed => Err(StreamError::Closed), } } fn check_write(&mut self) -> Result { - match mem::replace(&mut self.last_write, LastWrite::Closed) { - LastWrite::Waiting(task) => { - self.last_write = LastWrite::Waiting(task); + match mem::replace(&mut self.state, WriteState::Closed) { + WriteState::Writing(task) => { + self.state = WriteState::Writing(task); return Ok(0); } - LastWrite::Done => { - self.last_write = LastWrite::Done; + WriteState::Closing(task) => { + self.state = WriteState::Closing(task); + return Ok(0); + } + WriteState::Ready => { + self.state = WriteState::Ready; } - LastWrite::Closed => return Err(StreamError::Closed), - LastWrite::Error(e) => return Err(StreamError::LastOperationFailed(e.into())), + WriteState::Closed => return Err(StreamError::Closed), + WriteState::Error(e) => return Err(StreamError::LastOperationFailed(e.into())), } let writable = self.stream.writable(); @@ -853,25 +898,103 @@ impl HostOutputStream for TcpWriteStream { } Ok(SOCKET_READY_SIZE) } + + fn shutdown(&mut self) { + self.state = match mem::replace(&mut self.state, WriteState::Closed) { + // No write in progress, immediately shut down: + WriteState::Ready => { + native_shutdown(&self.stream, Shutdown::Write); + WriteState::Closed + } + + // Schedule the shutdown after the current write has finished: + WriteState::Writing(write) => { + let stream = self.stream.clone(); + WriteState::Closing(crate::runtime::spawn(async move { + let result = write.await; + native_shutdown(&stream, Shutdown::Write); + result + })) + } + + s => s, + }; + } + async fn cancel(&mut self) { - match mem::replace(&mut self.last_write, LastWrite::Closed) { - LastWrite::Waiting(task) => _ = task.abort_wait().await, + match mem::replace(&mut self.state, WriteState::Closed) { + WriteState::Writing(task) | WriteState::Closing(task) => _ = task.cancel().await, _ => {} } } -} -#[async_trait::async_trait] -impl Subscribe for TcpWriteStream { async fn ready(&mut self) { - if let LastWrite::Waiting(task) = &mut self.last_write { - self.last_write = match task.await { - Ok(()) => LastWrite::Done, - Err(e) => LastWrite::Error(e), - }; + match &mut self.state { + WriteState::Writing(task) => { + self.state = match task.await { + Ok(()) => WriteState::Ready, + Err(e) => WriteState::Error(e), + } + } + WriteState::Closing(task) => { + self.state = match task.await { + Ok(()) => WriteState::Closed, + Err(e) => WriteState::Error(e), + } + } + _ => {} } - if let LastWrite::Done = self.last_write { + + if let WriteState::Ready = self.state { self.stream.writable().await.unwrap(); } } } + +struct TcpWriteStream(Arc>); + +#[async_trait::async_trait] +impl HostOutputStream for TcpWriteStream { + fn write(&mut self, bytes: bytes::Bytes) -> Result<(), StreamError> { + try_lock_for_stream(&self.0)?.write(bytes) + } + + fn flush(&mut self) -> Result<(), StreamError> { + try_lock_for_stream(&self.0)?.flush() + } + + fn check_write(&mut self) -> Result { + try_lock_for_stream(&self.0)?.check_write() + } + + async fn cancel(&mut self) { + self.0.lock().await.cancel().await + } +} + +#[async_trait::async_trait] +impl Subscribe for TcpWriteStream { + async fn ready(&mut self) { + self.0.lock().await.ready().await + } +} + +fn native_shutdown(stream: &tokio::net::TcpStream, how: Shutdown) { + _ = stream + .as_socketlike_view::() + .shutdown(how); +} + +fn try_lock_for_stream(mutex: &Mutex) -> Result, StreamError> { + mutex + .try_lock() + .map_err(|_| StreamError::trap("concurrent access to resource not supported")) +} + +fn try_lock_for_socket(mutex: &Mutex) -> Result, SocketError> { + mutex.try_lock().map_err(|_| { + SocketError::trap(anyhow::anyhow!( + "concurrent access to resource not supported" + )) + }) +} diff --git a/crates/wasi/src/write_stream.rs b/crates/wasi/src/write_stream.rs index 33ae910481b7..fe3658662ff2 100644 --- a/crates/wasi/src/write_stream.rs +++ b/crates/wasi/src/write_stream.rs @@ -198,7 +198,7 @@ impl HostOutputStream for AsyncWriteStream { async fn cancel(&mut self) { match self.join_handle.take() { - Some(task) => _ = task.abort_wait().await, + Some(task) => _ = task.cancel().await, None => {} } } diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index 1ecbcf181bf5..9bd10c1a6d66 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -31,6 +31,7 @@ wasmtime-component-util = { workspace = true, optional = true } wasmtime-slab = { workspace = true, optional = true } wasmtime-versioned-export-macros = { workspace = true } wasmtime-wmemcheck = { workspace = true, optional = true } +pulley-interpreter = { workspace = true, optional = true } target-lexicon = { workspace = true } wasmparser = { workspace = true } wasm-encoder = { workspace = true, optional = true } @@ -135,11 +136,18 @@ default = [ # precompiled WebAssembly modules. cranelift = ["dep:wasmtime-cranelift", "std"] -# Enables support for winch, the WebAssembly baseline compiler. The Winch compiler +# Enables support for Winch, the WebAssembly baseline compiler. The Winch compiler # strategy in `Config` will be available. It is currently in active development # and shouldn't be used in production applications. winch = ["dep:wasmtime-winch", "std"] +# Enables support for Pulley, the WebAssembly interpreter. When paired with the +# `cranelift` feature, the compiler backends for the `pulley32` and `pulley64` +# targets will be available. When paired with the `runtime` feature, the Pulley +# interpreter will be built into the runtime and you can interpret WebAssembly +# modules that have been compiled to Pulley bytecode. +pulley = ["dep:pulley-interpreter", "wasmtime-cranelift?/pulley"] + # Enables support for incremental compilation cache to be enabled in `Config`. incremental-cache = ["wasmtime-cranelift?/incremental-cache", "std"] @@ -176,7 +184,7 @@ pooling-allocator = ["runtime", "std"] # Enables support for all architectures in Cranelift, allowing # cross-compilation using the `wasmtime` crate's API, notably the # `Engine::precompile_module` function. -all-arch = ["wasmtime-cranelift?/all-arch", "wasmtime-winch?/all-arch"] +all-arch = ["wasmtime-cranelift?/all-arch", "wasmtime-winch?/all-arch", "pulley"] # Enables in-progress support for the component model. Note that this feature is # in-progress, buggy, and incomplete. This is primarily here for internal @@ -222,7 +230,8 @@ runtime = [ "dep:windows-sys", "dep:psm", "dep:rustix", - "rustix/mm" + "rustix/mm", + "pulley-interpreter?/interp", ] # Enable support for garbage collection-related things. diff --git a/crates/wasmtime/src/compile.rs b/crates/wasmtime/src/compile.rs index 35877008ebb4..6021c627fb73 100644 --- a/crates/wasmtime/src/compile.rs +++ b/crates/wasmtime/src/compile.rs @@ -78,7 +78,8 @@ pub(crate) fn build_artifacts( .context("failed to parse WebAssembly module")?; let functions = mem::take(&mut translation.function_body_inputs); - let compile_inputs = CompileInputs::for_module(&types, &translation, functions); + let compile_inputs = + CompileInputs::for_module(engine.compiler().triple(), &types, &translation, functions); let unlinked_compile_outputs = compile_inputs.compile(engine)?; let (compiled_funcs, function_indices) = unlinked_compile_outputs.pre_link(); @@ -144,6 +145,7 @@ pub(crate) fn build_component_artifacts( .context("failed to parse WebAssembly module")?; let compile_inputs = CompileInputs::for_component( + engine, &types, &component, module_translations.iter_mut().map(|(i, translation)| { @@ -320,6 +322,9 @@ struct CompileOutput { /// The collection of things we need to compile for a Wasm module or component. #[derive(Default)] struct CompileInputs<'a> { + // Whether or not we need to compile wasm-to-native trampolines. + need_wasm_to_array_trampolines: bool, + inputs: Vec>, } @@ -330,13 +335,20 @@ impl<'a> CompileInputs<'a> { /// Create the `CompileInputs` for a core Wasm module. fn for_module( + triple: &target_lexicon::Triple, types: &'a ModuleTypesBuilder, translation: &'a ModuleTranslation<'a>, functions: PrimaryMap>, ) -> Self { - let mut ret = Self::default(); - let module_index = StaticModuleIndex::from_u32(0); + let mut ret = CompileInputs { + need_wasm_to_array_trampolines: !matches!( + triple.architecture, + target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 + ), + inputs: vec![], + }; + let module_index = StaticModuleIndex::from_u32(0); ret.collect_inputs_in_translations(types, [(module_index, translation, functions)]); ret @@ -345,6 +357,7 @@ impl<'a> CompileInputs<'a> { /// Create a `CompileInputs` for a component. #[cfg(feature = "component-model")] fn for_component( + engine: &'a Engine, types: &'a wasmtime_environ::component::ComponentTypesBuilder, component: &'a wasmtime_environ::component::ComponentTranslation, module_translations: impl IntoIterator< @@ -355,9 +368,17 @@ impl<'a> CompileInputs<'a> { ), >, ) -> Self { - let mut ret = CompileInputs::default(); + let triple = engine.compiler().triple(); + let mut ret = CompileInputs { + need_wasm_to_array_trampolines: !matches!( + triple.architecture, + target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 + ), + inputs: vec![], + }; ret.collect_inputs_in_translations(types.module_types_builder(), module_translations); + let tunables = engine.tunables(); for (idx, trampoline) in component.trampolines.iter() { ret.push_input(move |compiler| { @@ -366,7 +387,7 @@ impl<'a> CompileInputs<'a> { symbol: trampoline.symbol_name(), function: compiler .component_compiler() - .compile_trampoline(component, types, idx)? + .compile_trampoline(component, types, idx, tunables)? .into(), info: None, }) @@ -495,25 +516,28 @@ impl<'a> CompileInputs<'a> { } } - let mut trampoline_types_seen = HashSet::new(); - for (_func_type_index, trampoline_type_index) in types.trampoline_types() { - let is_new = trampoline_types_seen.insert(trampoline_type_index); - if !is_new { - continue; + if self.need_wasm_to_array_trampolines { + let mut trampoline_types_seen = HashSet::new(); + for (_func_type_index, trampoline_type_index) in types.trampoline_types() { + let is_new = trampoline_types_seen.insert(trampoline_type_index); + if !is_new { + continue; + } + let trampoline_func_ty = types[trampoline_type_index].unwrap_func(); + self.push_input(move |compiler| { + let trampoline = + compiler.compile_wasm_to_array_trampoline(trampoline_func_ty)?; + Ok(CompileOutput { + key: CompileKey::wasm_to_array_trampoline(trampoline_type_index), + symbol: format!( + "signatures[{}]::wasm_to_array_trampoline", + trampoline_type_index.as_u32() + ), + function: CompiledFunction::Function(trampoline), + info: None, + }) + }); } - let trampoline_func_ty = types[trampoline_type_index].unwrap_func(); - self.push_input(move |compiler| { - let trampoline = compiler.compile_wasm_to_array_trampoline(trampoline_func_ty)?; - Ok(CompileOutput { - key: CompileKey::wasm_to_array_trampoline(trampoline_type_index), - symbol: format!( - "signatures[{}]::wasm_to_array_trampoline", - trampoline_type_index.as_u32() - ), - function: CompiledFunction::Function(trampoline), - info: None, - }) - }); } } @@ -712,7 +736,8 @@ impl FunctionIndices { )?; } - let mut obj = wasmtime_environ::ObjectBuilder::new(obj, tunables); + let mut obj = + wasmtime_environ::ObjectBuilder::new(obj, tunables, compiler.triple().clone()); let mut artifacts = Artifacts::default(); // Remove this as it's not needed by anything below and we'll debug @@ -804,23 +829,29 @@ impl FunctionIndices { }) .collect(); - let unique_and_sorted_trampoline_sigs = translation - .module - .types - .iter() - .map(|(_, ty)| *ty) - .filter(|idx| types[*idx].is_func()) - .map(|idx| types.trampoline_type(idx)) - .collect::>(); - let wasm_to_array_trampolines = unique_and_sorted_trampoline_sigs - .iter() - .map(|idx| { - let trampoline = types.trampoline_type(*idx); - let key = CompileKey::wasm_to_array_trampoline(trampoline); - let compiled = wasm_to_array_trampolines[&key]; - (*idx, symbol_ids_and_locs[compiled.unwrap_function()].1) - }) - .collect(); + let wasm_to_array_trampolines = match engine.compiler().triple().architecture { + target_lexicon::Architecture::Pulley32 + | target_lexicon::Architecture::Pulley64 => vec![], + _ => { + let unique_and_sorted_trampoline_sigs = translation + .module + .types + .iter() + .map(|(_, ty)| *ty) + .filter(|idx| types[*idx].is_func()) + .map(|idx| types.trampoline_type(idx)) + .collect::>(); + unique_and_sorted_trampoline_sigs + .iter() + .map(|idx| { + let trampoline = types.trampoline_type(*idx); + let key = CompileKey::wasm_to_array_trampoline(trampoline); + let compiled = wasm_to_array_trampolines[&key]; + (*idx, symbol_ids_and_locs[compiled.unwrap_function()].1) + }) + .collect() + } + }; obj.append(translation, funcs, wasm_to_array_trampolines) }) diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index 77ece0f03d63..f1aa159fecd1 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -167,6 +167,7 @@ struct ConfigTunables { generate_address_map: Option, debug_adapter_modules: Option, relaxed_simd_deterministic: Option, + signals_based_traps: Option, } /// User-provided configuration for the compiler. @@ -597,6 +598,24 @@ impl Config { /// [`Store::set_epoch_deadline`](crate::Store::set_epoch_deadline). If this /// deadline is not configured then wasm will immediately trap. /// + /// ## Interaction with blocking host calls + /// + /// Epochs (and fuel) do not assist in handling WebAssembly code blocked in + /// a call to the host. For example if the WebAssembly function calls + /// `wasi:io/poll/poll` to sleep epochs will not assist in waking this up or + /// timing it out. Epochs intentionally only affect running WebAssembly code + /// itself and it's left to the embedder to determine how best to wake up + /// indefinitely blocking code in the host. + /// + /// The typical solution for this, however, is to use + /// [`Config::async_support(true)`](Config::async_support) and the `async` + /// variant of WASI host functions. This models computation as a Rust + /// `Future` which means that when blocking happens the future is only + /// suspended and control yields back to the main event loop. This gives the + /// embedder the opportunity to use `tokio::time::timeout` for example on a + /// wasm computation and have the desired effect of cancelling a blocking + /// operation when a timeout expires. + /// /// ## When to use fuel vs. epochs /// /// In general, epoch-based interruption results in faster @@ -1839,7 +1858,7 @@ impl Config { fn features(&self) -> WasmFeatures { // Wasmtime by default supports all of the wasm 2.0 version of the // specification. - let mut features = WasmFeatures::wasm2(); + let mut features = WasmFeatures::WASM2; // On-by-default features that wasmtime has. Note that these are all // subject to the criteria at @@ -1979,6 +1998,7 @@ impl Config { generate_address_map debug_adapter_modules relaxed_simd_deterministic + signals_based_traps } // If we're going to compile with winch, we must use the winch calling convention. @@ -1989,6 +2009,10 @@ impl Config { if tunables.winch_callable && !tunables.table_lazy_init { bail!("Winch requires the table-lazy-init configuration option"); } + + if tunables.winch_callable && !tunables.signals_based_traps { + bail!("Winch requires signals-based traps to be enabled"); + } } if tunables.static_memory_offset_guard_size < tunables.dynamic_memory_offset_guard_size { @@ -2120,6 +2144,29 @@ impl Config { .settings .insert("preserve_frame_pointers".into(), "true".into()); + if !tunables.signals_based_traps { + let mut ok = self.compiler_config.ensure_setting_unset_or_given( + "enable_table_access_spectre_mitigation".into(), + "false".into(), + ); + ok = ok + && self.compiler_config.ensure_setting_unset_or_given( + "enable_heap_access_spectre_mitigation".into(), + "false".into(), + ); + + // Right now spectre-mitigated bounds checks will load from zero so + // if host-based signal handlers are disabled then that's a mismatch + // and doesn't work right now. Fixing this will require more thought + // of how to implement the bounds check in spectre-only mode. + if !ok { + bail!( + "when signals-based traps are disabled then spectre \ + mitigations must also be disabled" + ); + } + } + // check for incompatible compiler options and set required values if features.contains(WasmFeatures::REFERENCE_TYPES) { if !self @@ -2255,6 +2302,43 @@ impl Config { self.detect_host_feature = Some(detect); self } + + /// Configures Wasmtime to not use signals-based trap handlers, for example + /// disables `SIGILL` and `SIGSEGV` handler registration on Unix platforms. + /// + /// Wasmtime will by default leverage signals-based trap handlers (or the + /// platform equivalent, for example "vectored exception handlers" on + /// Windows) to make generated code more efficient. For example an + /// out-of-bounds load in WebAssembly will result in a `SIGSEGV` on Unix + /// that is caught by a signal handler in Wasmtime by default. Another + /// example is divide-by-zero is reported by hardware rather than + /// explicitly checked and Wasmtime turns that into a trap. + /// + /// Some environments however may not have easy access to signal handlers. + /// For example embedded scenarios may not support virtual memory. Other + /// environments where Wasmtime is embedded within the surrounding + /// environment may require that new signal handlers aren't registered due + /// to the global nature of signal handlers. This option exists to disable + /// the signal handler registration when required. + /// + /// When signals-based trap handlers are disabled then generated code will + /// never rely on segfaults or other signals. Generated code will be slower + /// because bounds checks must be explicit along with other operations like + /// integer division which must check for zero. + /// + /// When this option is disable it additionally requires that the + /// `enable_heap_access_spectre_mitigation` and + /// `enable_table_access_spectre_mitigation` Cranelift settings are + /// disabled. This means that generated code must have spectre mitigations + /// disabled. This is because spectre mitigations rely on faults from + /// loading from the null address to implement bounds checks. + /// + /// This option defaults to `true` meaning that signals-based trap handlers + /// are enabled by default. + pub fn signals_based_traps(&mut self, enable: bool) -> &mut Self { + self.tunables.signals_based_traps = Some(enable); + self + } } impl Default for Config { @@ -2865,7 +2949,7 @@ impl PoolingAllocationConfig { /// table; table elements are pointer-sized in the Wasmtime runtime. /// Therefore, the space reserved for each instance is `tables * /// table_elements * sizeof::<*const ()>`. - pub fn table_elements(&mut self, elements: u32) -> &mut Self { + pub fn table_elements(&mut self, elements: usize) -> &mut Self { self.config.limits.table_elements = elements; self } diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs index 9698d5b03a18..2b4e42046249 100644 --- a/crates/wasmtime/src/engine.rs +++ b/crates/wasmtime/src/engine.rs @@ -88,8 +88,11 @@ impl Engine { /// to `true`, but explicitly disable these two compiler settings /// will cause errors. pub fn new(config: &Config) -> Result { + let config = config.clone(); + let (tunables, features) = config.validate()?; + #[cfg(feature = "runtime")] - { + if tunables.signals_based_traps { // Ensure that crate::runtime::vm's signal handlers are // configured. This is the per-program initialization required for // handling traps, such as configuring signals, vectored exception @@ -99,9 +102,6 @@ impl Engine { crate::runtime::vm::debug_builtins::ensure_exported(); } - let config = config.clone(); - let (tunables, features) = config.validate()?; - #[cfg(any(feature = "cranelift", feature = "winch"))] let (config, compiler) = config.build_compiler(&tunables, features)?; diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs index 18929c05ef73..df4c6e8b5955 100644 --- a/crates/wasmtime/src/engine/serialization.rs +++ b/crates/wasmtime/src/engine/serialization.rs @@ -373,7 +373,7 @@ impl Metadata<'_> { table_lazy_init, relaxed_simd_deterministic, winch_callable, - + signals_based_traps, // This doesn't affect compilation, it's just a runtime setting. dynamic_memory_growth_reserve: _, @@ -439,6 +439,11 @@ impl Metadata<'_> { other.winch_callable, "Winch calling convention", )?; + Self::check_bool( + signals_based_traps, + other.signals_based_traps, + "Signals-based traps", + )?; Ok(()) } diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 0d8eaca2da2c..04cd87d3a53a 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -1,3 +1,31 @@ +// Wasmtime's runtime has lots of fiddly bits where we're doing operations like +// casting between wasm i32/i64 and host `usize` values. There's also in general +// just lots of pieces of low-level manipulation of memory and internals of VM +// runtime state. To help keep all the integer casts correct be a bit more +// strict than the default settings to help weed out bugs ahead of time. +// +// This inevitably leads to wordier code than might otherwise be used because, +// for example, `u64 as usize` is warned against and will be an error on CI. +// This happens pretty frequently and needs to be replaced with `val.try_into()` +// or `usize::try_from(val)` where the error is handled. In some cases the +// correct thing to do is to `.unwrap()` the error to indicate a fatal mistake, +// but in some cases the correct thing is to propagate the error. +// +// Some niche cases that explicitly want truncation are recommended to have a +// function along the lines of +// +// #[allow(clippy::cast_possible_truncation)] +// fn truncate_i32_to_i8(a: i32) -> i8 { a as i8 } +// +// as this explicitly indicates the intent of truncation is desired. Other +// locations should use fallible conversions. +// +// If performance is absolutely critical then it's recommended to use `#[allow]` +// with a comment indicating why performance is critical as well as a short +// explanation of why truncation shouldn't be happening at runtime. This +// situation should be pretty rare though. +#![warn(clippy::cast_possible_truncation)] + #[macro_use] pub(crate) mod func; diff --git a/crates/wasmtime/src/runtime/component/func/host.rs b/crates/wasmtime/src/runtime/component/func/host.rs index ed203fdcedca..a28bb3aa0e6b 100644 --- a/crates/wasmtime/src/runtime/component/func/host.rs +++ b/crates/wasmtime/src/runtime/component/func/host.rs @@ -4,17 +4,17 @@ use crate::component::storage::slice_to_storage_mut; use crate::component::{ComponentNamedList, ComponentType, Lift, Lower, Val}; use crate::prelude::*; use crate::runtime::vm::component::{ - InstanceFlags, VMComponentContext, VMLowering, VMLoweringCallee, + ComponentInstance, InstanceFlags, VMComponentContext, VMLowering, VMLoweringCallee, }; use crate::runtime::vm::{VMFuncRef, VMMemoryDefinition, VMOpaqueContext}; -use crate::{AsContextMut, StoreContextMut, ValRaw}; +use crate::{AsContextMut, CallHook, StoreContextMut, ValRaw}; use alloc::sync::Arc; use core::any::Any; use core::mem::{self, MaybeUninit}; use core::ptr::NonNull; use wasmtime_environ::component::{ - CanonicalAbiInfo, InterfaceType, StringEncoding, TypeFuncIndex, MAX_FLAT_PARAMS, - MAX_FLAT_RESULTS, + CanonicalAbiInfo, ComponentTypes, InterfaceType, StringEncoding, TypeFuncIndex, + MAX_FLAT_PARAMS, MAX_FLAT_RESULTS, }; pub struct HostFunc { @@ -55,9 +55,11 @@ impl HostFunc { { let data = data as *const F; unsafe { - handle_result(|| { + call_host_and_handle_result::(cx, |instance, types, store| { call_host::<_, _, _, _>( - cx, + instance, + types, + store, ty, flags, memory, @@ -131,7 +133,9 @@ where /// must be upheld. Generally that's done by ensuring this is only called from /// the select few places it's intended to be called from. unsafe fn call_host( - cx: *mut VMOpaqueContext, + instance: *mut ComponentInstance, + types: &Arc, + mut cx: StoreContextMut<'_, T>, ty: TypeFuncIndex, mut flags: InstanceFlags, memory: *mut VMMemoryDefinition, @@ -163,10 +167,6 @@ where ret: U, } - let cx = VMComponentContext::from_opaque(cx); - let instance = (*cx).instance(); - let mut cx = StoreContextMut::from_raw((*instance).store()); - let options = Options::new( cx.0.id(), NonNull::new(memory), @@ -181,7 +181,6 @@ where bail!("cannot leave component instance"); } - let types = (*instance).component_types(); let ty = &types[ty]; let param_tys = InterfaceType::Tuple(ty.params); let result_tys = InterfaceType::Tuple(ty.results); @@ -289,15 +288,37 @@ fn validate_inbounds(memory: &[u8], ptr: &ValRaw) -> Result Result<()>) { - match crate::runtime::vm::catch_unwind_and_longjmp(func) { +unsafe fn call_host_and_handle_result( + cx: *mut VMOpaqueContext, + func: impl FnOnce( + *mut ComponentInstance, + &Arc, + StoreContextMut<'_, T>, + ) -> Result<()>, +) { + let cx = VMComponentContext::from_opaque(cx); + let instance = (*cx).instance(); + let types = (*instance).component_types(); + let raw_store = (*instance).store(); + let mut store = StoreContextMut::from_raw(raw_store); + + let res = crate::runtime::vm::catch_unwind_and_longjmp(|| { + store.0.call_hook(CallHook::CallingHost)?; + let res = func(instance, types, store.as_context_mut()); + store.0.call_hook(CallHook::ReturningFromHost)?; + res + }); + + match res { Ok(()) => {} Err(e) => crate::trap::raise(e), } } unsafe fn call_host_dynamic( - cx: *mut VMOpaqueContext, + instance: *mut ComponentInstance, + types: &Arc, + mut store: StoreContextMut<'_, T>, ty: TypeFuncIndex, mut flags: InstanceFlags, memory: *mut VMMemoryDefinition, @@ -309,10 +330,6 @@ unsafe fn call_host_dynamic( where F: FnOnce(StoreContextMut<'_, T>, &[Val], &mut [Val]) -> Result<()>, { - let cx = VMComponentContext::from_opaque(cx); - let instance = (*cx).instance(); - let mut store = StoreContextMut::from_raw((*instance).store()); - let types = (*instance).component_types(); let options = Options::new( store.0.id(), NonNull::new(memory), @@ -423,9 +440,11 @@ extern "C" fn dynamic_entrypoint( { let data = data as *const F; unsafe { - handle_result(|| { + call_host_and_handle_result(cx, |instance, types, store| { call_host_dynamic::( - cx, + instance, + types, + store, ty, flags, memory, diff --git a/crates/wasmtime/src/runtime/component/func/typed.rs b/crates/wasmtime/src/runtime/component/func/typed.rs index ec1df7b3afc1..a2ab99c55ba8 100644 --- a/crates/wasmtime/src/runtime/component/func/typed.rs +++ b/crates/wasmtime/src/runtime/component/func/typed.rs @@ -837,7 +837,7 @@ macro_rules! integers { unsafe impl Lift for $primitive { #[inline] - #[allow(trivial_numeric_casts)] + #[allow(trivial_numeric_casts, clippy::cast_possible_truncation)] fn lift(_cx: &mut LiftContext<'_>, ty: InterfaceType, src: &Self::Lower) -> Result { debug_assert!(matches!(ty, InterfaceType::$ty)); Ok(src.$get() as $primitive) @@ -1110,8 +1110,8 @@ unsafe impl Lower for str { debug_assert!(offset % (Self::ALIGN32 as usize) == 0); let (ptr, len) = lower_string(cx, self)?; // FIXME: needs memory64 handling - *cx.get(offset + 0) = (ptr as i32).to_le_bytes(); - *cx.get(offset + 4) = (len as i32).to_le_bytes(); + *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes(); + *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes(); Ok(()) } } @@ -1457,8 +1457,8 @@ where }; debug_assert!(offset % (Self::ALIGN32 as usize) == 0); let (ptr, len) = lower_list(cx, elem, self)?; - *cx.get(offset + 0) = (ptr as i32).to_le_bytes(); - *cx.get(offset + 4) = (len as i32).to_le_bytes(); + *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes(); + *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes(); Ok(()) } } diff --git a/crates/wasmtime/src/runtime/component/resource_table.rs b/crates/wasmtime/src/runtime/component/resource_table.rs index 22a72fb3fee2..2314a970413a 100644 --- a/crates/wasmtime/src/runtime/component/resource_table.rs +++ b/crates/wasmtime/src/runtime/component/resource_table.rs @@ -161,7 +161,7 @@ impl ResourceTable { fn push_(&mut self, e: TableEntry) -> Result { if let Some(free) = self.pop_free_list() { self.entries[free] = Entry::Occupied { entry: e }; - Ok(free as u32) + Ok(free.try_into().unwrap()) } else { let ix = self .entries diff --git a/crates/wasmtime/src/runtime/component/resources.rs b/crates/wasmtime/src/runtime/component/resources.rs index 678b0f8f78e8..312c8216ccd9 100644 --- a/crates/wasmtime/src/runtime/component/resources.rs +++ b/crates/wasmtime/src/runtime/component/resources.rs @@ -369,7 +369,7 @@ impl HostResourceIndex { } impl<'a> HostResourceTables<'a> { - pub fn new_host(store: &'a mut StoreOpaque) -> HostResourceTables<'_> { + pub fn new_host(store: &'a mut StoreOpaque) -> HostResourceTables<'a> { let (calls, host_table, host_resource_data) = store.component_resource_state(); HostResourceTables::from_parts( ResourceTables { diff --git a/crates/wasmtime/src/runtime/component/types.rs b/crates/wasmtime/src/runtime/component/types.rs index 06824897eb05..6895ea4aa3fd 100644 --- a/crates/wasmtime/src/runtime/component/types.rs +++ b/crates/wasmtime/src/runtime/component/types.rs @@ -733,7 +733,7 @@ impl Module { pub fn imports<'a>( &'a self, engine: &'a Engine, - ) -> impl ExactSizeIterator + 'a { + ) -> impl ExactSizeIterator + 'a { self.0.types[self.0.index] .imports .iter() @@ -749,7 +749,7 @@ impl Module { pub fn exports<'a>( &'a self, engine: &'a Engine, - ) -> impl ExactSizeIterator + 'a { + ) -> impl ExactSizeIterator + 'a { self.0.types[self.0.index].exports.iter().map(|(name, ty)| { ( name.as_str(), @@ -780,7 +780,7 @@ impl Component { pub fn imports<'a>( &'a self, engine: &'a Engine, - ) -> impl ExactSizeIterator + 'a { + ) -> impl ExactSizeIterator + 'a { self.0.types[self.0.index].imports.iter().map(|(name, ty)| { ( name.as_str(), @@ -801,7 +801,7 @@ impl Component { pub fn exports<'a>( &'a self, engine: &'a Engine, - ) -> impl ExactSizeIterator + 'a { + ) -> impl ExactSizeIterator + 'a { self.0.types[self.0.index].exports.iter().map(|(name, ty)| { ( name.as_str(), @@ -832,7 +832,7 @@ impl ComponentInstance { pub fn exports<'a>( &'a self, engine: &'a Engine, - ) -> impl ExactSizeIterator { + ) -> impl ExactSizeIterator { self.0.types[self.0.index].exports.iter().map(|(name, ty)| { ( name.as_str(), diff --git a/crates/wasmtime/src/runtime/component/values.rs b/crates/wasmtime/src/runtime/component/values.rs index 0221ea50f847..a57e783a6e94 100644 --- a/crates/wasmtime/src/runtime/component/values.rs +++ b/crates/wasmtime/src/runtime/component/values.rs @@ -187,11 +187,11 @@ impl Val { let u32_count = cx.types.canonical_abi(&ty).flat_count(usize::MAX).unwrap(); let ty = &cx.types[i]; let mut flags = Vec::new(); - for i in 0..u32_count { + for i in 0..u32::try_from(u32_count).unwrap() { push_flags( ty, &mut flags, - (i as u32) * 32, + i * 32, u32::lift(cx, InterfaceType::U32, next(src))?, ); } @@ -480,8 +480,8 @@ impl Val { let ty = &cx.types[ty]; let (ptr, len) = lower_list(cx, ty.element, values)?; // FIXME: needs memory64 handling - *cx.get(offset + 0) = (ptr as i32).to_le_bytes(); - *cx.get(offset + 4) = (len as i32).to_le_bytes(); + *cx.get(offset + 0) = u32::try_from(ptr).unwrap().to_le_bytes(); + *cx.get(offset + 4) = u32::try_from(len).unwrap().to_le_bytes(); Ok(()) } (InterfaceType::List(_), _) => unexpected(ty, self), @@ -947,7 +947,7 @@ fn get_enum_discriminant(ty: &TypeEnum, n: &str) -> Result { ty.names .get_index_of(n) .ok_or_else(|| anyhow::anyhow!("enum variant name `{n}` is not valid")) - .map(|i| i as u32) + .map(|i| i.try_into().unwrap()) } fn get_variant_discriminant<'a>( @@ -958,7 +958,7 @@ fn get_variant_discriminant<'a>( .cases .get_full(name) .ok_or_else(|| anyhow::anyhow!("unknown variant case: `{name}`"))?; - Ok((i as u32, ty)) + Ok((i.try_into().unwrap(), ty)) } fn next<'a>(src: &mut Iter<'a, ValRaw>) -> &'a ValRaw { diff --git a/crates/wasmtime/src/runtime/coredump.rs b/crates/wasmtime/src/runtime/coredump.rs index 0d20a2067aad..fe6fa4377e6e 100644 --- a/crates/wasmtime/src/runtime/coredump.rs +++ b/crates/wasmtime/src/runtime/coredump.rs @@ -137,16 +137,18 @@ impl WasmCoreDump { // to balance these conflicting desires, we break the memory up // into reasonably-sized chunks and then trim runs of zeroes // from the start and end of each chunk. - const CHUNK_SIZE: u32 = 4096; - for (i, chunk) in mem - .data(&store) - .chunks_exact(CHUNK_SIZE as usize) - .enumerate() - { + const CHUNK_SIZE: usize = 4096; + for (i, chunk) in mem.data(&store).chunks_exact(CHUNK_SIZE).enumerate() { if let Some(start) = chunk.iter().position(|byte| *byte != 0) { let end = chunk.iter().rposition(|byte| *byte != 0).unwrap() + 1; - let offset = (i as u32) * CHUNK_SIZE + (start as u32); - let offset = wasm_encoder::ConstExpr::i32_const(offset as i32); + let offset = i * CHUNK_SIZE + start; + let offset = if ty.is_64() { + let offset = u64::try_from(offset).unwrap(); + wasm_encoder::ConstExpr::i64_const(offset as i64) + } else { + let offset = u32::try_from(offset).unwrap(); + wasm_encoder::ConstExpr::i32_const(offset as i32) + }; data.active(memory_idx, &offset, chunk[start..end].iter().copied()); } } diff --git a/crates/wasmtime/src/runtime/debug.rs b/crates/wasmtime/src/runtime/debug.rs index b3a5d94ddb64..6636e19b56e0 100644 --- a/crates/wasmtime/src/runtime/debug.rs +++ b/crates/wasmtime/src/runtime/debug.rs @@ -63,8 +63,11 @@ fn relocate_dwarf_sections(bytes: &mut [u8], code_region: (*const u8, usize)) -> } for (offset, value) in relocations { - let (loc, _) = object::from_bytes_mut::>(&mut bytes[offset as usize..]) - .map_err(|()| anyhow!("invalid dwarf relocations"))?; + let (loc, _) = offset + .try_into() + .ok() + .and_then(|offset| object::from_bytes_mut::>(&mut bytes[offset..]).ok()) + .ok_or_else(|| anyhow!("invalid dwarf relocations"))?; loc.set(NE, value); } Ok(()) @@ -126,7 +129,8 @@ fn convert_object_elf_to_loadable_file( let text_range = match sections.section_by_name(e, b".text") { Some((i, text)) => { let range = text.file_range(e); - let off = header.e_shoff.get(e) as usize + i.0 * header.e_shentsize.get(e) as usize; + let e_shoff = usize::try_from(header.e_shoff.get(e)).unwrap(); + let off = e_shoff + i.0 * header.e_shentsize.get(e) as usize; let section: &mut SectionHeader64 = object::from_bytes_mut(&mut bytes[off..]).unwrap().0; @@ -160,6 +164,8 @@ fn convert_object_elf_to_loadable_file( let header: &mut FileHeader64 = object::from_bytes_mut(bytes).unwrap().0; header.e_type.set(e, ET_DYN); header.e_phoff.set(e, ph_off as u64); - header.e_phentsize.set(e, e_phentsize as u16); - header.e_phnum.set(e, e_phnum as u16); + header + .e_phentsize + .set(e, u16::try_from(e_phentsize).unwrap()); + header.e_phnum.set(e, u16::try_from(e_phnum).unwrap()); } diff --git a/crates/wasmtime/src/runtime/externals/table.rs b/crates/wasmtime/src/runtime/externals/table.rs index eee9a06622a0..456a5a03ec15 100644 --- a/crates/wasmtime/src/runtime/externals/table.rs +++ b/crates/wasmtime/src/runtime/externals/table.rs @@ -135,7 +135,7 @@ impl Table { fn wasmtime_table( &self, store: &mut StoreOpaque, - lazy_init_range: impl Iterator, + lazy_init_range: impl Iterator, ) -> *mut runtime::Table { unsafe { let export = &store[self.0]; @@ -153,7 +153,7 @@ impl Table { /// # Panics /// /// Panics if `store` does not own this table. - pub fn get(&self, mut store: impl AsContextMut, index: u32) -> Option { + pub fn get(&self, mut store: impl AsContextMut, index: u64) -> Option { let mut store = AutoAssertNoGc::new(store.as_context_mut().0); let table = self.wasmtime_table(&mut store, iter::once(index)); unsafe { @@ -205,7 +205,7 @@ impl Table { /// # Panics /// /// Panics if `store` does not own this table. - pub fn set(&self, mut store: impl AsContextMut, index: u32, val: Ref) -> Result<()> { + pub fn set(&self, mut store: impl AsContextMut, index: u64, val: Ref) -> Result<()> { let store = store.as_context_mut().0; let ty = self.ty(&store); let val = val.into_table_element(store, ty.element())?; @@ -222,12 +222,14 @@ impl Table { /// # Panics /// /// Panics if `store` does not own this table. - pub fn size(&self, store: impl AsContext) -> u32 { + pub fn size(&self, store: impl AsContext) -> u64 { self.internal_size(store.as_context().0) } - pub(crate) fn internal_size(&self, store: &StoreOpaque) -> u32 { - unsafe { (*store[self.0].definition).current_elements } + pub(crate) fn internal_size(&self, store: &StoreOpaque) -> u64 { + // unwrap here should be ok because the runtime should always guarantee + // that we can fit the number of elements in a 64-bit integer. + unsafe { u64::try_from((*store[self.0].definition).current_elements).unwrap() } } /// Grows the size of this table by `delta` more elements, initialization @@ -251,7 +253,7 @@ impl Table { /// (see also: [`Store::limiter_async`](`crate::Store::limiter_async`)). /// When using an async resource limiter, use [`Table::grow_async`] /// instead. - pub fn grow(&self, mut store: impl AsContextMut, delta: u32, init: Ref) -> Result { + pub fn grow(&self, mut store: impl AsContextMut, delta: u64, init: Ref) -> Result { let store = store.as_context_mut().0; let ty = self.ty(&store); let init = init.into_table_element(store, ty.element())?; @@ -261,7 +263,9 @@ impl Table { Some(size) => { let vm = (*table).vmtable(); *store[self.0].definition = vm; - Ok(size) + // unwrap here should be ok because the runtime should always guarantee + // that we can fit the table size in a 64-bit integer. + Ok(u64::try_from(size).unwrap()) } None => bail!("failed to grow table by `{}`", delta), } @@ -279,9 +283,9 @@ impl Table { pub async fn grow_async( &self, mut store: impl AsContextMut, - delta: u32, + delta: u64, init: Ref, - ) -> Result + ) -> Result where T: Send, { @@ -310,10 +314,10 @@ impl Table { pub fn copy( mut store: impl AsContextMut, dst_table: &Table, - dst_index: u32, + dst_index: u64, src_table: &Table, - src_index: u32, - len: u32, + src_index: u64, + len: u64, ) -> Result<()> { let store = store.as_context_mut().0; @@ -328,7 +332,7 @@ impl Table { )?; let dst_table = dst_table.wasmtime_table(store, iter::empty()); - let src_range = src_index..(src_index.checked_add(len).unwrap_or(u32::MAX)); + let src_range = src_index..(src_index.checked_add(len).unwrap_or(u64::MAX)); let src_table = src_table.wasmtime_table(store, src_range); unsafe { runtime::Table::copy( @@ -360,7 +364,7 @@ impl Table { /// # Panics /// /// Panics if `store` does not own either `dst_table` or `src_table`. - pub fn fill(&self, mut store: impl AsContextMut, dst: u32, val: Ref, len: u32) -> Result<()> { + pub fn fill(&self, mut store: impl AsContextMut, dst: u64, val: Ref, len: u64) -> Result<()> { let store = store.as_context_mut().0; let ty = self.ty(&store); let val = val.into_table_element(store, ty.element())?; @@ -404,7 +408,7 @@ impl Table { wasmtime_export .table .table - .wasm_ty + .ref_type .canonicalize_for_runtime_usage(&mut |module_index| { crate::runtime::vm::Instance::from_vmctx(wasmtime_export.vmctx, |instance| { instance.engine_type_index(module_index) diff --git a/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs b/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs index 34e449aa70da..a340d1913906 100644 --- a/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs +++ b/crates/wasmtime/src/runtime/gc/enabled/arrayref.rs @@ -2,7 +2,7 @@ use crate::runtime::vm::VMGcRef; use crate::store::StoreId; -use crate::vm::{GcArrayLayout, GcLayout, VMArrayRef, VMGcHeader}; +use crate::vm::{VMArrayRef, VMGcHeader}; use crate::{ prelude::*, store::{AutoAssertNoGc, StoreContextMut, StoreOpaque}, @@ -11,7 +11,7 @@ use crate::{ }; use crate::{AnyRef, FieldType}; use core::mem::{self, MaybeUninit}; -use wasmtime_environ::{VMGcKind, VMSharedTypeIndex}; +use wasmtime_environ::{GcArrayLayout, GcLayout, VMGcKind, VMSharedTypeIndex}; /// An allocator for a particular Wasm GC array type. /// diff --git a/crates/wasmtime/src/runtime/gc/enabled/structref.rs b/crates/wasmtime/src/runtime/gc/enabled/structref.rs index b707d2c8e388..c0cbe2de512a 100644 --- a/crates/wasmtime/src/runtime/gc/enabled/structref.rs +++ b/crates/wasmtime/src/runtime/gc/enabled/structref.rs @@ -2,7 +2,7 @@ use crate::runtime::vm::VMGcRef; use crate::store::StoreId; -use crate::vm::{GcLayout, GcStructLayout, VMGcHeader, VMStructRef}; +use crate::vm::{VMGcHeader, VMStructRef}; use crate::{ prelude::*, store::{AutoAssertNoGc, StoreContextMut, StoreOpaque}, @@ -11,7 +11,7 @@ use crate::{ }; use crate::{AnyRef, FieldType}; use core::mem::{self, MaybeUninit}; -use wasmtime_environ::{VMGcKind, VMSharedTypeIndex}; +use wasmtime_environ::{GcLayout, GcStructLayout, VMGcKind, VMSharedTypeIndex}; /// An allocator for a particular Wasm GC struct type. /// diff --git a/crates/wasmtime/src/runtime/instantiate.rs b/crates/wasmtime/src/runtime/instantiate.rs index a8abc8147c50..e0e7ae492141 100644 --- a/crates/wasmtime/src/runtime/instantiate.rs +++ b/crates/wasmtime/src/runtime/instantiate.rs @@ -274,9 +274,12 @@ impl CompiledModule { .meta .dwarf .binary_search_by_key(&(id as u8), |(id, _)| *id) - .map(|i| { + .ok() + .and_then(|i| { let (_, range) = &self.meta.dwarf[i]; - &self.code_memory().dwarf()[range.start as usize..range.end as usize] + let start = range.start.try_into().ok()?; + let end = range.end.try_into().ok()?; + self.code_memory().dwarf().get(start..end) }) .unwrap_or(&[]); Ok(EndianSlice::new(data, gimli::LittleEndian)) diff --git a/crates/wasmtime/src/runtime/limits.rs b/crates/wasmtime/src/runtime/limits.rs index 76faf312cd21..a3d3bad646ca 100644 --- a/crates/wasmtime/src/runtime/limits.rs +++ b/crates/wasmtime/src/runtime/limits.rs @@ -103,7 +103,12 @@ pub trait ResourceLimiter { /// /// See the details on the return values for `memory_growing` for what the /// return value of this function indicates. - fn table_growing(&mut self, current: u32, desired: u32, maximum: Option) -> Result; + fn table_growing( + &mut self, + current: usize, + desired: usize, + maximum: Option, + ) -> Result; /// Notifies the resource limiter that growing a linear memory, permitted by /// the `table_growing` method, has failed. @@ -185,9 +190,9 @@ pub trait ResourceLimiterAsync { /// Asynchronous version of [`ResourceLimiter::table_growing`] async fn table_growing( &mut self, - current: u32, - desired: u32, - maximum: Option, + current: usize, + desired: usize, + maximum: Option, ) -> Result; /// Identical to [`ResourceLimiter::table_grow_failed`] @@ -244,7 +249,7 @@ impl StoreLimitsBuilder { /// they're all allowed to reach up to the `limit` specified. /// /// By default, table elements will not be limited. - pub fn table_elements(mut self, limit: u32) -> Self { + pub fn table_elements(mut self, limit: usize) -> Self { self.0.table_elements = Some(limit); self } @@ -310,7 +315,7 @@ impl StoreLimitsBuilder { #[derive(Clone, Debug)] pub struct StoreLimits { memory_size: Option, - table_elements: Option, + table_elements: Option, instances: usize, tables: usize, memories: usize, @@ -360,7 +365,12 @@ impl ResourceLimiter for StoreLimits { } } - fn table_growing(&mut self, _current: u32, desired: u32, maximum: Option) -> Result { + fn table_growing( + &mut self, + _current: usize, + desired: usize, + maximum: Option, + ) -> Result { let allow = match self.table_elements { Some(limit) if desired > limit => false, _ => match maximum { diff --git a/crates/wasmtime/src/runtime/linker.rs b/crates/wasmtime/src/runtime/linker.rs index 316613270b16..f5937628c295 100644 --- a/crates/wasmtime/src/runtime/linker.rs +++ b/crates/wasmtime/src/runtime/linker.rs @@ -129,7 +129,7 @@ pub(crate) enum DefinitionType { // information but additionally the current size of the table/memory, as // this is used during linking since the min size specified in the type may // no longer be the current size of the table/memory. - Table(wasmtime_environ::Table, u32), + Table(wasmtime_environ::Table, u64), Memory(wasmtime_environ::Memory, u64), Tag(wasmtime_environ::Tag), } @@ -1227,7 +1227,7 @@ impl Linker { pub fn iter<'a: 'p, 'p>( &'a self, mut store: impl AsContextMut + 'p, - ) -> impl Iterator + 'p { + ) -> impl Iterator + 'p { self.map.iter().map(move |(key, item)| { let store = store.as_context_mut(); ( diff --git a/crates/wasmtime/src/runtime/module.rs b/crates/wasmtime/src/runtime/module.rs index 2b277e254f00..f507aefc11f2 100644 --- a/crates/wasmtime/src/runtime/module.rs +++ b/crates/wasmtime/src/runtime/module.rs @@ -881,14 +881,14 @@ impl Module { .memory_plans .values() .skip(em.num_imported_memories) - .map(|plan| plan.memory.minimum) + .map(|plan| plan.memory.limits.min) .max(); let num_tables = u32::try_from(em.table_plans.len() - em.num_imported_tables).unwrap(); let max_initial_table_size = em .table_plans .values() .skip(em.num_imported_tables) - .map(|plan| plan.table.minimum) + .map(|plan| plan.table.limits.min) .max(); ResourcesRequired { num_memories, diff --git a/crates/wasmtime/src/runtime/resources.rs b/crates/wasmtime/src/runtime/resources.rs index 540f7b37b299..b9f7a6b21418 100644 --- a/crates/wasmtime/src/runtime/resources.rs +++ b/crates/wasmtime/src/runtime/resources.rs @@ -17,7 +17,7 @@ pub struct ResourcesRequired { /// The number of tables that are required. pub num_tables: u32, /// The maximum initial size required by any table. - pub max_initial_table_size: Option, + pub max_initial_table_size: Option, } impl ResourcesRequired { diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs index 8b80c77529ac..cc6b60ac407b 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -2529,9 +2529,9 @@ unsafe impl crate::runtime::vm::Store for StoreInner { fn table_growing( &mut self, - current: u32, - desired: u32, - maximum: Option, + current: usize, + desired: usize, + maximum: Option, ) -> Result { // Need to borrow async_cx before the mut borrow of the limiter. // self.async_cx() panicks when used with a non-async store, so diff --git a/crates/wasmtime/src/runtime/trampoline/table.rs b/crates/wasmtime/src/runtime/trampoline/table.rs index d96d6a2950bf..cbf580b578dc 100644 --- a/crates/wasmtime/src/runtime/trampoline/table.rs +++ b/crates/wasmtime/src/runtime/trampoline/table.rs @@ -11,9 +11,9 @@ pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result None, wasmtime_environ::WasmCompositeType::Array(a) => { - Some(gc_runtime.array_layout(a).into()) + Some(gc_runtime.layouts().array_layout(a).into()) } wasmtime_environ::WasmCompositeType::Struct(s) => { - Some(gc_runtime.struct_layout(s).into()) + Some(gc_runtime.layouts().struct_layout(s).into()) } wasmtime_environ::WasmCompositeType::Cont(_) => None, // TODO(dhil): revisit later. }; diff --git a/crates/wasmtime/src/runtime/types.rs b/crates/wasmtime/src/runtime/types.rs index 72985e213960..6c2888739efa 100644 --- a/crates/wasmtime/src/runtime/types.rs +++ b/crates/wasmtime/src/runtime/types.rs @@ -1,9 +1,9 @@ use crate::prelude::*; use core::fmt::{self, Display, Write}; use wasmtime_environ::{ - EngineOrModuleTypeIndex, EntityType, Global, Memory, ModuleTypes, Table, TypeTrace, - VMSharedTypeIndex, WasmArrayType, WasmCompositeType, WasmFieldType, WasmFuncType, WasmHeapType, - WasmRefType, WasmStorageType, WasmStructType, WasmSubType, WasmValType, + EngineOrModuleTypeIndex, EntityType, Global, IndexType, Limits, Memory, ModuleTypes, Table, + TypeTrace, VMSharedTypeIndex, WasmArrayType, WasmCompositeType, WasmFieldType, WasmFuncType, + WasmHeapType, WasmRefType, WasmStorageType, WasmStructType, WasmSubType, WasmValType, }; use crate::{type_registry::RegisteredType, Engine}; @@ -2659,43 +2659,78 @@ impl TableType { /// Creates a new table descriptor which will contain the specified /// `element` and have the `limits` applied to its length. pub fn new(element: RefType, min: u32, max: Option) -> TableType { - let wasm_ty = element.to_wasm_type(); + let ref_type = element.to_wasm_type(); debug_assert!( - wasm_ty.is_canonicalized_for_runtime_usage(), - "should be canonicalized for runtime usage: {wasm_ty:?}" + ref_type.is_canonicalized_for_runtime_usage(), + "should be canonicalized for runtime usage: {ref_type:?}" + ); + + let limits = Limits { + min: u64::from(min), + max: max.map(|x| u64::from(x)), + }; + + TableType { + element, + ty: Table { + idx_type: IndexType::I32, + limits, + ref_type, + }, + } + } + + /// Crates a new descriptor for a 64-bit table. + /// + /// Note that 64-bit tables are part of the memory64 proposal for + /// WebAssembly which is not standardized yet. + pub fn new64(element: RefType, min: u64, max: Option) -> TableType { + let ref_type = element.to_wasm_type(); + + debug_assert!( + ref_type.is_canonicalized_for_runtime_usage(), + "should be canonicalized for runtime usage: {ref_type:?}" ); TableType { element, ty: Table { - wasm_ty, - minimum: min, - maximum: max, + ref_type, + idx_type: IndexType::I64, + limits: Limits { min, max }, }, } } + /// Returns whether or not this table is a 64-bit table. + /// + /// Note that 64-bit tables are part of the memory64 proposal for + /// WebAssembly which is not standardized yet. + pub fn is_64(&self) -> bool { + matches!(self.ty.idx_type, IndexType::I64) + } + /// Returns the element value type of this table. pub fn element(&self) -> &RefType { &self.element } /// Returns minimum number of elements this table must have - pub fn minimum(&self) -> u32 { - self.ty.minimum + pub fn minimum(&self) -> u64 { + self.ty.limits.min } /// Returns the optionally-specified maximum number of elements this table /// can have. /// /// If this returns `None` then the table is not limited in size. - pub fn maximum(&self) -> Option { - self.ty.maximum + pub fn maximum(&self) -> Option { + self.ty.limits.max } pub(crate) fn from_wasmtime_table(engine: &Engine, table: &Table) -> TableType { - let element = RefType::from_wasm_type(engine, &table.wasm_ty); + let element = RefType::from_wasm_type(engine, &table.ref_type); TableType { element, ty: *table, @@ -2743,10 +2778,9 @@ impl Default for MemoryTypeBuilder { fn default() -> Self { MemoryTypeBuilder { ty: Memory { - minimum: 0, - maximum: None, + idx_type: IndexType::I32, + limits: Limits { min: 0, max: None }, shared: false, - memory64: false, page_size_log2: Memory::DEFAULT_PAGE_SIZE_LOG2, }, } @@ -2755,7 +2789,12 @@ impl Default for MemoryTypeBuilder { impl MemoryTypeBuilder { fn validate(&self) -> Result<()> { - if self.ty.maximum.map_or(false, |max| max < self.ty.minimum) { + if self + .ty + .limits + .max + .map_or(false, |max| max < self.ty.limits.min) + { bail!("maximum page size cannot be smaller than the minimum page size"); } @@ -2768,7 +2807,7 @@ impl MemoryTypeBuilder { ), } - if self.ty.shared && self.ty.maximum.is_none() { + if self.ty.shared && self.ty.limits.max.is_none() { bail!("shared memories must have a maximum size"); } @@ -2797,7 +2836,7 @@ impl MemoryTypeBuilder { /// /// The default minimum is `0`. pub fn min(&mut self, minimum: u64) -> &mut Self { - self.ty.minimum = minimum; + self.ty.limits.min = minimum; self } @@ -2806,7 +2845,7 @@ impl MemoryTypeBuilder { /// /// The default maximum is `None`. pub fn max(&mut self, maximum: Option) -> &mut Self { - self.ty.maximum = maximum; + self.ty.limits.max = maximum; self } @@ -2820,7 +2859,10 @@ impl MemoryTypeBuilder { /// proposal](https://github.com/WebAssembly/memory64) for WebAssembly which /// is not fully standardized yet. pub fn memory64(&mut self, memory64: bool) -> &mut Self { - self.ty.memory64 = memory64; + self.ty.idx_type = match memory64 { + true => IndexType::I64, + false => IndexType::I32, + }; self } @@ -2960,7 +3002,7 @@ impl MemoryType { /// Note that 64-bit memories are part of the memory64 proposal for /// WebAssembly which is not standardized yet. pub fn is_64(&self) -> bool { - self.ty.memory64 + matches!(self.ty.idx_type, IndexType::I64) } /// Returns whether this is a shared memory or not. @@ -2976,7 +3018,7 @@ impl MemoryType { /// Note that the return value, while a `u64`, will always fit into a `u32` /// for 32-bit memories. pub fn minimum(&self) -> u64 { - self.ty.minimum + self.ty.limits.min } /// Returns the optionally-specified maximum number of pages this memory @@ -2987,7 +3029,7 @@ impl MemoryType { /// Note that the return value, while a `u64`, will always fit into a `u32` /// for 32-bit memories. pub fn maximum(&self) -> Option { - self.ty.maximum + self.ty.limits.max } /// This memory's page size, in bytes. diff --git a/crates/wasmtime/src/runtime/types/matching.rs b/crates/wasmtime/src/runtime/types/matching.rs index d821e647c9e0..ab3dedc30dde 100644 --- a/crates/wasmtime/src/runtime/types/matching.rs +++ b/crates/wasmtime/src/runtime/types/matching.rs @@ -2,8 +2,8 @@ use crate::type_registry::RegisteredType; use crate::{linker::DefinitionType, Engine, FuncType}; use crate::{prelude::*, ArrayType, StructType}; use wasmtime_environ::{ - EntityType, Global, Memory, ModuleTypes, Table, TypeTrace, VMSharedTypeIndex, WasmHeapType, - WasmRefType, WasmSubType, WasmValType, + EntityType, Global, IndexType, Memory, ModuleTypes, Table, TypeTrace, VMSharedTypeIndex, + WasmHeapType, WasmRefType, WasmSubType, WasmValType, }; pub struct MatchCx<'a> { @@ -157,17 +157,18 @@ fn global_ty(expected: &Global, actual: &Global) -> Result<()> { Ok(()) } -fn table_ty(expected: &Table, actual: &Table, actual_runtime_size: Option) -> Result<()> { +fn table_ty(expected: &Table, actual: &Table, actual_runtime_size: Option) -> Result<()> { equal_ty( - WasmValType::Ref(expected.wasm_ty), - WasmValType::Ref(actual.wasm_ty), + WasmValType::Ref(expected.ref_type), + WasmValType::Ref(actual.ref_type), "table", )?; + match_index(expected.idx_type, actual.idx_type, "table")?; match_limits( - expected.minimum.into(), - expected.maximum.map(|i| i.into()), - actual_runtime_size.unwrap_or(actual.minimum).into(), - actual.maximum.map(|i| i.into()), + expected.limits.min, + expected.limits.max, + actual_runtime_size.unwrap_or(actual.limits.min), + actual.limits.max, "table", )?; Ok(()) @@ -181,18 +182,12 @@ fn memory_ty(expected: &Memory, actual: &Memory, actual_runtime_size: Option Result<()> { + if expected == actual { + return Ok(()); + } + const S64: &str = "64-bit"; + const S32: &str = "32-bit"; + let expected = if matches!(expected, IndexType::I64) { + S64 + } else { + S32 + }; + let actual = if matches!(actual, IndexType::I64) { + S64 + } else { + S32 + }; + bail!( + "{desc} types incompatible: expected {expected} {desc}, \ + found {actual} {desc}", + ) +} + fn match_limits( expected_min: u64, expected_max: Option, diff --git a/crates/wasmtime/src/runtime/vm.rs b/crates/wasmtime/src/runtime/vm.rs index dbe248079142..0d1e320355b3 100644 --- a/crates/wasmtime/src/runtime/vm.rs +++ b/crates/wasmtime/src/runtime/vm.rs @@ -149,9 +149,9 @@ pub unsafe trait Store { /// table grow operation. fn table_growing( &mut self, - current: u32, - desired: u32, - maximum: Option, + current: usize, + desired: usize, + maximum: Option, ) -> Result; /// Callback invoked to notify the store's resource limiter that a table diff --git a/crates/wasmtime/src/runtime/vm/component.rs b/crates/wasmtime/src/runtime/vm/component.rs index a9847355c49b..96c7e4db4173 100644 --- a/crates/wasmtime/src/runtime/vm/component.rs +++ b/crates/wasmtime/src/runtime/vm/component.rs @@ -23,6 +23,8 @@ use sptr::Strict; use wasmtime_environ::component::*; use wasmtime_environ::{HostPtr, PrimaryMap, VMSharedTypeIndex}; +#[allow(clippy::cast_possible_truncation)] // it's intended this is truncated on + // 32-bit platforms const INVALID_PTR: usize = 0xdead_dead_beef_beef_u64 as usize; mod libcalls; diff --git a/crates/wasmtime/src/runtime/vm/component/libcalls.rs b/crates/wasmtime/src/runtime/vm/component/libcalls.rs index 34d2a0c1813e..69ff4d628010 100644 --- a/crates/wasmtime/src/runtime/vm/component/libcalls.rs +++ b/crates/wasmtime/src/runtime/vm/component/libcalls.rs @@ -27,6 +27,7 @@ macro_rules! signature { (@ty ptr_u8) => (*mut u8); (@ty ptr_u16) => (*mut u16); (@ty ptr_size) => (*mut usize); + (@ty u8) => (u8); (@ty u32) => (u32); (@ty u64) => (u64); (@ty vmctx) => (*mut VMComponentContext); @@ -569,3 +570,7 @@ unsafe fn resource_enter_call(vmctx: *mut VMComponentContext) -> Result<()> { unsafe fn resource_exit_call(vmctx: *mut VMComponentContext) -> Result<()> { ComponentInstance::from_vmctx(vmctx, |instance| instance.resource_exit_call()) } + +unsafe fn trap(_vmctx: *mut VMComponentContext, code: u8) -> Result<()> { + Err(wasmtime_environ::Trap::from_u8(code).unwrap()).err2anyhow() +} diff --git a/crates/wasmtime/src/runtime/vm/cow.rs b/crates/wasmtime/src/runtime/vm/cow.rs index ded449f8e340..392ff6c1fb58 100644 --- a/crates/wasmtime/src/runtime/vm/cow.rs +++ b/crates/wasmtime/src/runtime/vm/cow.rs @@ -72,10 +72,13 @@ impl MemoryImage { data: &[u8], mmap: Option<&MmapVec>, ) -> Result> { + let assert_page_aligned = |val: usize| { + assert_eq!(val % (page_size as usize), 0); + }; // Sanity-check that various parameters are page-aligned. let len = data.len(); assert_eq!(offset % u64::from(page_size), 0); - assert_eq!((len as u32) % page_size, 0); + assert_page_aligned(len); let linear_memory_offset = match usize::try_from(offset) { Ok(offset) => offset, Err(_) => return Ok(None), @@ -101,10 +104,10 @@ impl MemoryImage { let data_start = data.as_ptr() as usize; let data_end = data_start + data.len(); assert!(start <= data_start && data_end <= end); - assert_eq!((start as u32) % page_size, 0); - assert_eq!((data_start as u32) % page_size, 0); - assert_eq!((data_end as u32) % page_size, 0); - assert_eq!((mmap.original_offset() as u32) % page_size, 0); + assert_page_aligned(start); + assert_page_aligned(data_start); + assert_page_aligned(data_end); + assert_page_aligned(mmap.original_offset()); #[cfg(feature = "std")] if let Some(file) = mmap.original_file() { @@ -167,7 +170,8 @@ impl ModuleMemoryImages { _ => return Ok(None), }; let mut memories = PrimaryMap::with_capacity(map.len()); - let page_size = crate::runtime::vm::host_page_size() as u32; + let page_size = crate::runtime::vm::host_page_size(); + let page_size = u32::try_from(page_size).unwrap(); for (memory_index, init) in map { // mmap-based-initialization only works for defined memories with a // known starting point of all zeros, so bail out if the mmeory is @@ -752,7 +756,7 @@ mod test { use crate::runtime::vm::mmap::Mmap; use crate::runtime::vm::sys::vm::decommit_pages; use std::sync::Arc; - use wasmtime_environ::Memory; + use wasmtime_environ::{IndexType, Limits, Memory}; fn create_memfd_with_data(offset: usize, data: &[u8]) -> Result { // Offset must be page-aligned. @@ -774,10 +778,9 @@ mod test { MemoryPlan { style, memory: Memory { - minimum: 0, - maximum: None, + idx_type: IndexType::I32, + limits: Limits { min: 0, max: None }, shared: false, - memory64: false, page_size_log2: Memory::DEFAULT_PAGE_SIZE_LOG2, }, pre_guard_size: 0, diff --git a/crates/wasmtime/src/runtime/vm/gc.rs b/crates/wasmtime/src/runtime/vm/gc.rs index beafb0c71951..cfbc6677649f 100644 --- a/crates/wasmtime/src/runtime/vm/gc.rs +++ b/crates/wasmtime/src/runtime/vm/gc.rs @@ -22,7 +22,7 @@ use crate::prelude::*; use crate::runtime::vm::GcHeapAllocationIndex; use core::ptr; use core::{any::Any, num::NonZeroUsize}; -use wasmtime_environ::{StackMap, VMGcKind, VMSharedTypeIndex}; +use wasmtime_environ::{GcArrayLayout, GcStructLayout, StackMap, VMGcKind, VMSharedTypeIndex}; /// Used by the runtime to lookup information about a module given a /// program counter value. diff --git a/crates/wasmtime/src/runtime/vm/gc/disabled.rs b/crates/wasmtime/src/runtime/vm/gc/disabled.rs index 24aa269ffbae..4b459e715e80 100644 --- a/crates/wasmtime/src/runtime/vm/gc/disabled.rs +++ b/crates/wasmtime/src/runtime/vm/gc/disabled.rs @@ -6,8 +6,10 @@ #![allow(missing_docs)] use crate::prelude::*; -use crate::runtime::vm::{GcArrayLayout, GcHeap, GcRuntime, GcStructLayout}; -use wasmtime_environ::{WasmArrayType, WasmStructType}; +use crate::runtime::vm::{GcHeap, GcRuntime}; +use wasmtime_environ::{ + GcArrayLayout, GcStructLayout, GcTypeLayouts, WasmArrayType, WasmStructType, +}; pub fn default_gc_runtime() -> impl GcRuntime { DisabledCollector @@ -20,11 +22,7 @@ unsafe impl GcRuntime for DisabledCollector { unreachable!() } - fn array_layout(&self, _ty: &WasmArrayType) -> GcArrayLayout { - unreachable!() - } - - fn struct_layout(&self, _ty: &WasmStructType) -> GcStructLayout { + fn layouts(&self) -> &dyn GcTypeLayouts { unreachable!() } } diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled.rs b/crates/wasmtime/src/runtime/vm/gc/enabled.rs index ca8ab8859a87..0a7466537608 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled.rs @@ -17,7 +17,7 @@ use crate::runtime::vm::GcRuntime; /// Get the default GC runtime. pub fn default_gc_runtime() -> impl GcRuntime { - DrcCollector + DrcCollector::default() } /// The default GC heap capacity: 512KiB. @@ -27,3 +27,15 @@ const DEFAULT_GC_HEAP_CAPACITY: usize = 1 << 19; /// The default GC heap capacity for miri: 64KiB. #[cfg(miri)] const DEFAULT_GC_HEAP_CAPACITY: usize = 1 << 16; + +// Explicit methods with `#[allow]` to clearly indicate that truncation is +// desired when used. +#[allow(clippy::cast_possible_truncation)] +fn truncate_i32_to_i16(a: i32) -> i16 { + a as i16 +} + +#[allow(clippy::cast_possible_truncation)] +fn truncate_i32_to_i8(a: i32) -> i8 { + a as i8 +} diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/arrayref.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/arrayref.rs index d6d192226e00..412ccabbd759 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/arrayref.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/arrayref.rs @@ -1,12 +1,12 @@ +use super::{truncate_i32_to_i16, truncate_i32_to_i8}; use crate::{ prelude::*, runtime::vm::{GcHeap, GcStore, VMGcRef}, store::{AutoAssertNoGc, StoreOpaque}, - vm::GcArrayLayout, AnyRef, ExternRef, HeapType, RootedGcRefImpl, StorageType, Val, ValType, }; use core::fmt; -use wasmtime_environ::VMGcKind; +use wasmtime_environ::{GcArrayLayout, VMGcKind}; /// A `VMGcRef` that we know points to a `array`. /// @@ -193,8 +193,8 @@ impl VMArrayRef { let offset = layout.elem_offset(index, ty.byte_size_in_gc_heap()); let mut data = store.unwrap_gc_store_mut().gc_object_data(self.as_gc_ref()); match val { - Val::I32(i) if ty.is_i8() => data.write_i8(offset, i as i8), - Val::I32(i) if ty.is_i16() => data.write_i16(offset, i as i16), + Val::I32(i) if ty.is_i8() => data.write_i8(offset, truncate_i32_to_i8(i)), + Val::I32(i) if ty.is_i16() => data.write_i16(offset, truncate_i32_to_i16(i)), Val::I32(i) => data.write_i32(offset, i), Val::I64(i) => data.write_i64(offset, i), Val::F32(f) => data.write_u32(offset, f), @@ -279,11 +279,11 @@ impl VMArrayRef { Val::I32(i) if ty.is_i8() => store .gc_store_mut()? .gc_object_data(self.as_gc_ref()) - .write_i8(offset, i as i8), + .write_i8(offset, truncate_i32_to_i8(i)), Val::I32(i) if ty.is_i16() => store .gc_store_mut()? .gc_object_data(self.as_gc_ref()) - .write_i16(offset, i as i16), + .write_i16(offset, truncate_i32_to_i16(i)), Val::I32(i) => store .gc_store_mut()? .gc_object_data(self.as_gc_ref()) diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs index 2d3c729d8d3c..c5ae2c6c241c 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/drc.rs @@ -45,9 +45,8 @@ use super::free_list::FreeList; use super::{VMArrayRef, VMGcObjectDataMut, VMStructRef}; use crate::prelude::*; use crate::runtime::vm::{ - ExternRefHostDataId, ExternRefHostDataTable, GarbageCollection, GcArrayLayout, GcHeap, - GcHeapObject, GcProgress, GcRootsIter, GcRuntime, GcStructLayout, Mmap, TypedGcRef, - VMExternRef, VMGcHeader, VMGcRef, + ExternRefHostDataId, ExternRefHostDataTable, GarbageCollection, GcHeap, GcHeapObject, + GcProgress, GcRootsIter, GcRuntime, Mmap, TypedGcRef, VMExternRef, VMGcHeader, VMGcRef, }; use core::ops::{Deref, DerefMut}; use core::{ @@ -59,7 +58,8 @@ use core::{ ptr::{self, NonNull}, }; use hashbrown::HashSet; -use wasmtime_environ::{VMGcKind, VMSharedTypeIndex, WasmStorageType, WasmValType}; +use wasmtime_environ::drc::DrcTypeLayouts; +use wasmtime_environ::{GcArrayLayout, GcStructLayout, GcTypeLayouts, VMGcKind, VMSharedTypeIndex}; /// The deferred reference-counting (DRC) collector. /// @@ -68,93 +68,20 @@ use wasmtime_environ::{VMGcKind, VMSharedTypeIndex, WasmStorageType, WasmValType /// /// This is not a moving collector; it doesn't have a nursery or do any /// compaction. -pub struct DrcCollector; - -/// Align `offset` up to `bytes`, updating `max_align` if `align` is the -/// new maximum alignment, and returning the aligned offset. -fn align_up(offset: &mut u32, max_align: &mut u32, align: u32) -> u32 { - debug_assert!(max_align.is_power_of_two()); - debug_assert!(align.is_power_of_two()); - *offset = offset.checked_add(align - 1).unwrap() & !(align - 1); - *max_align = core::cmp::max(*max_align, align); - *offset +#[derive(Default)] +pub struct DrcCollector { + layouts: DrcTypeLayouts, } -/// Define a new field of size and alignment `bytes`, updating the object's -/// total `size` and `align` as necessary. The offset of the new field is -/// returned. -fn field(size: &mut u32, align: &mut u32, bytes: u32) -> u32 { - let offset = align_up(size, align, bytes); - *size += bytes; - offset -} - -fn size_of_wasm_ty(ty: &WasmStorageType) -> u32 { - match ty { - WasmStorageType::I8 => 1, - WasmStorageType::I16 => 2, - WasmStorageType::Val(ty) => match ty { - WasmValType::I32 | WasmValType::F32 | WasmValType::Ref(_) => 4, - WasmValType::I64 | WasmValType::F64 => 8, - WasmValType::V128 => 16, - }, +unsafe impl GcRuntime for DrcCollector { + fn layouts(&self) -> &dyn GcTypeLayouts { + &self.layouts } -} -unsafe impl GcRuntime for DrcCollector { fn new_gc_heap(&self) -> Result> { let heap = DrcHeap::new()?; Ok(Box::new(heap) as _) } - - fn array_layout(&self, ty: &wasmtime_environ::WasmArrayType) -> GcArrayLayout { - let mut size = VMDrcHeader::HEADER_SIZE; - let mut align = VMDrcHeader::HEADER_ALIGN; - let length_field_offset = field(&mut size, &mut align, 4); - debug_assert_eq!( - length_field_offset, - u32::try_from(core::mem::offset_of!(VMDrcArrayHeader, length)).unwrap(), - ); - let elem_size = size_of_wasm_ty(&ty.0.element_type); - let elems_offset = align_up(&mut size, &mut align, elem_size); - GcArrayLayout { - size, - align, - length_field_offset, - elems_offset, - elem_size, - } - } - - fn struct_layout(&self, ty: &wasmtime_environ::WasmStructType) -> GcStructLayout { - // Process each field, aligning it to its natural alignment. - // - // We don't try and do any fancy field reordering to minimize padding - // (yet?) because (a) the toolchain probably already did that and (b) - // we're just doing the simple thing first. We can come back and improve - // things here if we find that (a) isn't actually holding true in - // practice. - let mut size = VMDrcHeader::HEADER_SIZE; - let mut align = VMDrcHeader::HEADER_ALIGN; - let fields = ty - .fields - .iter() - .map(|f| { - let field_size = size_of_wasm_ty(&f.element_type); - field(&mut size, &mut align, field_size) - }) - .collect(); - - // Ensure that the final size is a multiple of the alignment, for - // simplicity. - align_up(&mut size, &mut 16, align); - - GcStructLayout { - size, - align, - fields, - } - } } /// A deferred reference-counting (DRC) heap. @@ -561,18 +488,7 @@ unsafe impl GcHeapObject for VMDrcHeader { } } -const _: () = { - assert!((VMDrcHeader::HEADER_SIZE as usize) == core::mem::size_of::()); - assert!((VMDrcHeader::HEADER_ALIGN as usize) == core::mem::align_of::()); -}; - impl VMDrcHeader { - /// The size of `VMDrcHeader` on *all* architectures. - const HEADER_SIZE: u32 = VMGcHeader::HEADER_SIZE + 8; - - /// The alignment of `VMDrcHeader` on *all* architectures. - const HEADER_ALIGN: u32 = 8; - /// The size of this header's object. /// /// This is stored in the inner `VMGcHeader`'s reserved bits. @@ -1076,6 +992,26 @@ impl DerefMut for DebugOnly { mod tests { use super::*; + #[test] + fn vm_drc_header_size_align() { + assert_eq!( + (wasmtime_environ::drc::HEADER_SIZE as usize), + core::mem::size_of::() + ); + assert_eq!( + (wasmtime_environ::drc::HEADER_ALIGN as usize), + core::mem::align_of::() + ); + } + + #[test] + fn vm_drc_array_header_length_offset() { + assert_eq!( + wasmtime_environ::drc::ARRAY_LENGTH_OFFSET, + u32::try_from(core::mem::offset_of!(VMDrcArrayHeader, length)).unwrap(), + ); + } + #[test] fn ref_count_is_at_correct_offset() { let extern_data = VMDrcHeader { diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs index 8e62253896ba..85e766823d77 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/free_list.rs @@ -14,8 +14,8 @@ pub(crate) struct FreeList { /// Our minimum and maximum supported alignment. Every allocation is aligned to /// this. -const ALIGN_USIZE: usize = 8; -const ALIGN_U32: u32 = ALIGN_USIZE as u32; +const ALIGN_U32: u32 = 8; +const ALIGN_USIZE: usize = ALIGN_U32 as usize; /// Our minimum allocation size. const MIN_BLOCK_SIZE: u32 = 24; diff --git a/crates/wasmtime/src/runtime/vm/gc/enabled/structref.rs b/crates/wasmtime/src/runtime/vm/gc/enabled/structref.rs index d0bd18d43b28..a7f48d86e1fc 100644 --- a/crates/wasmtime/src/runtime/vm/gc/enabled/structref.rs +++ b/crates/wasmtime/src/runtime/vm/gc/enabled/structref.rs @@ -1,12 +1,12 @@ +use super::{truncate_i32_to_i16, truncate_i32_to_i8}; use crate::{ prelude::*, runtime::vm::{GcHeap, GcStore, VMGcRef}, store::AutoAssertNoGc, - vm::GcStructLayout, AnyRef, ExternRef, HeapType, RootedGcRefImpl, StorageType, Val, ValType, }; use core::fmt; -use wasmtime_environ::VMGcKind; +use wasmtime_environ::{GcStructLayout, VMGcKind}; /// A `VMGcRef` that we know points to a `struct`. /// @@ -187,8 +187,8 @@ impl VMStructRef { let offset = layout.fields[field]; let mut data = store.gc_store_mut()?.gc_object_data(self.as_gc_ref()); match val { - Val::I32(i) if ty.is_i8() => data.write_i8(offset, i as i8), - Val::I32(i) if ty.is_i16() => data.write_i16(offset, i as i16), + Val::I32(i) if ty.is_i8() => data.write_i8(offset, truncate_i32_to_i8(i)), + Val::I32(i) if ty.is_i16() => data.write_i16(offset, truncate_i32_to_i16(i)), Val::I32(i) => data.write_i32(offset, i), Val::I64(i) => data.write_i64(offset, i), Val::F32(f) => data.write_u32(offset, f), @@ -273,11 +273,11 @@ impl VMStructRef { Val::I32(i) if ty.is_i8() => store .gc_store_mut()? .gc_object_data(self.as_gc_ref()) - .write_i8(offset, i as i8), + .write_i8(offset, truncate_i32_to_i8(i)), Val::I32(i) if ty.is_i16() => store .gc_store_mut()? .gc_object_data(self.as_gc_ref()) - .write_i16(offset, i as i16), + .write_i16(offset, truncate_i32_to_i16(i)), Val::I32(i) => store .gc_store_mut()? .gc_object_data(self.as_gc_ref()) diff --git a/crates/wasmtime/src/runtime/vm/gc/gc_runtime.rs b/crates/wasmtime/src/runtime/vm/gc/gc_runtime.rs index d36e64ecd740..07980b362fef 100644 --- a/crates/wasmtime/src/runtime/vm/gc/gc_runtime.rs +++ b/crates/wasmtime/src/runtime/vm/gc/gc_runtime.rs @@ -8,7 +8,7 @@ use crate::runtime::vm::{ use core::marker; use core::ptr; use core::{any::Any, num::NonZeroUsize}; -use wasmtime_environ::{VMSharedTypeIndex, WasmArrayType, WasmStructType}; +use wasmtime_environ::{GcArrayLayout, GcStructLayout, GcTypeLayouts, VMSharedTypeIndex}; use super::VMGcObjectDataMut; @@ -34,14 +34,11 @@ use super::VMGcObjectDataMut; /// safety. Implementations of this trait may not add new safety invariants, not /// already documented in this trait's interface, that callers need to uphold. pub unsafe trait GcRuntime: 'static + Send + Sync { + /// Get this collector's GC type layouts. + fn layouts(&self) -> &dyn GcTypeLayouts; + /// Construct a new GC heap. fn new_gc_heap(&self) -> Result>; - - /// Get this collector's layout for the given array type. - fn array_layout(&self, ty: &WasmArrayType) -> GcArrayLayout; - - /// Get this collector's layout for the given struct type. - fn struct_layout(&self, ty: &WasmStructType) -> GcStructLayout; } /// A heap that manages garbage-collected objects. @@ -386,117 +383,6 @@ pub unsafe trait GcHeap: 'static + Send + Sync { fn reset(&mut self); } -/// The layout of a GC-managed object. -#[derive(Clone, Debug)] -pub enum GcLayout { - /// The layout of a GC-managed array object. - #[allow(dead_code)] // Not used yet, but added for completeness. - Array(GcArrayLayout), - - /// The layout of a GC-managed struct object. - Struct(GcStructLayout), -} - -impl From for GcLayout { - fn from(layout: GcArrayLayout) -> Self { - Self::Array(layout) - } -} - -impl From for GcLayout { - fn from(layout: GcStructLayout) -> Self { - Self::Struct(layout) - } -} - -impl GcLayout { - /// Get the underlying `GcStructLayout`, or panic. - #[track_caller] - pub fn unwrap_struct(&self) -> &GcStructLayout { - match self { - Self::Struct(s) => s, - _ => panic!("GcLayout::unwrap_struct on non-struct GC layout"), - } - } - - /// Get the underlying `GcArrayLayout`, or panic. - #[track_caller] - pub fn unwrap_array(&self) -> &GcArrayLayout { - match self { - Self::Array(a) => a, - _ => panic!("GcLayout::unwrap_array on non-array GC layout"), - } - } -} - -/// The layout of a GC-managed array. -/// -/// This layout is only valid for use with the GC runtime that created it. It is -/// not valid to use one GC runtime's layout with another GC runtime, doing so -/// is memory safe but will lead to general incorrectness like panics and wrong -/// results. -/// -/// All offsets are from the start of the object; that is, the size of the GC -/// header (for example) is included in the offset. -/// -/// All arrays are composed of the generic `VMGcHeader`, followed by -/// collector-specific fields, followed by the contiguous array elements -/// themselves. The array elements must be aligned to the element type's natural -/// alignment. -#[derive(Clone, Debug)] -#[allow(dead_code)] // Not used yet, but added for completeness. -pub struct GcArrayLayout { - /// The size of this array object, ignoring its elements. - pub size: u32, - - /// The alignment of this array. - pub align: u32, - - /// The offset of the array's length. - pub length_field_offset: u32, - - /// The offset from where this array's contiguous elements begin. - pub elems_offset: u32, - - /// The size and natural alignment of each element in this array. - pub elem_size: u32, -} - -impl GcArrayLayout { - /// Get the total size of this array for a given length of elements. - pub fn size_for_len(&self, len: u32) -> u32 { - self.size + len * self.elem_size - } - - /// Get the offset of the `i`th element in an array with this layout. - #[inline] - pub fn elem_offset(&self, i: u32, elem_size: u32) -> u32 { - self.elems_offset + i * elem_size - } -} - -/// The layout for a GC-managed struct type. -/// -/// This layout is only valid for use with the GC runtime that created it. It is -/// not valid to use one GC runtime's layout with another GC runtime, doing so -/// is memory safe but will lead to general incorrectness like panics and wrong -/// results. -/// -/// All offsets are from the start of the object; that is, the size of the GC -/// header (for example) is included in the offset. -#[derive(Clone, Debug)] -pub struct GcStructLayout { - /// The size of this struct. - pub size: u32, - - /// The alignment of this struct. - pub align: u32, - - /// The fields of this struct. The `i`th entry is the `i`th struct field's - /// offset in the struct. - pub fields: Vec, -} - /// A list of GC roots. /// /// This is effectively a builder for a `GcRootsIter` that will be given to a GC diff --git a/crates/wasmtime/src/runtime/vm/gc/i31.rs b/crates/wasmtime/src/runtime/vm/gc/i31.rs index e79ece0c3f93..98e3e3c078b6 100644 --- a/crates/wasmtime/src/runtime/vm/gc/i31.rs +++ b/crates/wasmtime/src/runtime/vm/gc/i31.rs @@ -2,6 +2,7 @@ use super::VMGcRef; use core::fmt; +use wasmtime_environ::Unsigned; /// A 31-bit integer for use with `i31ref`. #[derive(Clone, Copy, PartialEq, Eq, Hash)] @@ -68,9 +69,8 @@ impl I31 { /// If the value doesn't fit in the bottom 31 bits, it is wrapped such that /// the wrapped value does. #[inline] - #[allow(clippy::cast_sign_loss)] pub fn wrapping_i32(value: i32) -> Self { - Self::wrapping_u32(value as u32) + Self::wrapping_u32(value.unsigned()) } /// Get this `I31`'s value as an unsigned integer. diff --git a/crates/wasmtime/src/runtime/vm/helpers.c b/crates/wasmtime/src/runtime/vm/helpers.c index 08fcfeb75018..d5c24fe25bba 100644 --- a/crates/wasmtime/src/runtime/vm/helpers.c +++ b/crates/wasmtime/src/runtime/vm/helpers.c @@ -1,3 +1,8 @@ +// When using _FORTIFY_SOURCE with `longjmp` causes longjmp_chk to be used +// instead. longjmp_chk ensures that the jump target is on the existing stack. +// For our use case of jumping between stacks we need to disable it. +#undef _FORTIFY_SOURCE + #include #include #include diff --git a/crates/wasmtime/src/runtime/vm/instance.rs b/crates/wasmtime/src/runtime/vm/instance.rs index cca43b5723f1..88a3fa9203c4 100644 --- a/crates/wasmtime/src/runtime/vm/instance.rs +++ b/crates/wasmtime/src/runtime/vm/instance.rs @@ -205,7 +205,7 @@ impl Instance { let size = memory_plans .iter() .next() - .map(|plan| plan.1.memory.minimum) + .map(|plan| plan.1.memory.limits.min) .unwrap_or(0) * 64 * 1024; @@ -699,9 +699,9 @@ impl Instance { pub(crate) fn table_grow( &mut self, table_index: TableIndex, - delta: u32, + delta: u64, init_value: TableElement, - ) -> Result, Error> { + ) -> Result, Error> { self.with_defined_table_index_and_instance(table_index, |i, instance| { instance.defined_table_grow(i, delta, init_value) }) @@ -710,9 +710,9 @@ impl Instance { fn defined_table_grow( &mut self, table_index: DefinedTableIndex, - delta: u32, + delta: u64, init_value: TableElement, - ) -> Result, Error> { + ) -> Result, Error> { let store = unsafe { &mut *self.store() }; let table = &mut self .tables @@ -845,9 +845,9 @@ impl Instance { &mut self, table_index: TableIndex, elem_index: ElemIndex, - dst: u32, - src: u32, - len: u32, + dst: u64, + src: u64, + len: u64, ) -> Result<(), Trap> { // TODO: this `clone()` shouldn't be necessary but is used for now to // inform `rustc` that the lifetime of the elements here are @@ -875,9 +875,9 @@ impl Instance { const_evaluator: &mut ConstExprEvaluator, table_index: TableIndex, elements: &TableSegmentElements, - dst: u32, - src: u32, - len: u32, + dst: u64, + src: u64, + len: u64, ) -> Result<(), Trap> { // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-init @@ -907,7 +907,7 @@ impl Instance { let mut context = ConstEvalContext::new(self, &module); match module.table_plans[table_index] .table - .wasm_ty + .ref_type .heap_type .top() { @@ -983,6 +983,7 @@ impl Instance { let src = self.validate_inbounds(src_mem.current_length(), src, len)?; let dst = self.validate_inbounds(dst_mem.current_length(), dst, len)?; + let len = usize::try_from(len).unwrap(); // Bounds and casts are checked above, by this point we know that // everything is safe. @@ -991,7 +992,7 @@ impl Instance { let src = src_mem.base.add(src); // FIXME audit whether this is safe in the presence of shared memory // (https://github.com/bytecodealliance/wasmtime/issues/4203). - ptr::copy(src, dst, len as usize); + ptr::copy(src, dst, len); } Ok(()) @@ -1006,7 +1007,7 @@ impl Instance { if end > max { Err(oob()) } else { - Ok(ptr as usize) + Ok(ptr.try_into().unwrap()) } } @@ -1024,6 +1025,7 @@ impl Instance { ) -> Result<(), Trap> { let memory = self.get_memory(memory_index); let dst = self.validate_inbounds(memory.current_length(), dst, len)?; + let len = usize::try_from(len).unwrap(); // Bounds and casts are checked above, by this point we know that // everything is safe. @@ -1031,7 +1033,7 @@ impl Instance { let dst = memory.base.add(dst); // FIXME audit whether this is safe in the presence of shared memory // (https://github.com/bytecodealliance/wasmtime/issues/4203). - ptr::write_bytes(dst, val, len as usize); + ptr::write_bytes(dst, val, len); } Ok(()) @@ -1112,7 +1114,7 @@ impl Instance { pub(crate) fn get_table_with_lazy_init( &mut self, table_index: TableIndex, - range: impl Iterator, + range: impl Iterator, ) -> *mut Table { self.with_defined_table_index_and_instance(table_index, |idx, instance| { instance.get_defined_table_with_lazy_init(idx, range) @@ -1126,7 +1128,7 @@ impl Instance { pub fn get_defined_table_with_lazy_init( &mut self, idx: DefinedTableIndex, - range: impl Iterator, + range: impl Iterator, ) -> *mut Table { let elt_ty = self.tables[idx].1.element_type(); @@ -1159,7 +1161,8 @@ impl Instance { TableInitialValue::Null { precomputed } => precomputed, TableInitialValue::Expr(_) => unreachable!(), }; - let func_index = precomputed.get(i as usize).cloned(); + // Panicking here helps catch bugs rather than silently truncating by accident. + let func_index = precomputed.get(usize::try_from(i).unwrap()).cloned(); let func_ref = func_index .and_then(|func_index| self.get_func_ref(func_index)) .unwrap_or(ptr::null_mut()); @@ -1506,7 +1509,7 @@ impl InstanceHandle { pub fn get_defined_table_with_lazy_init( &mut self, index: DefinedTableIndex, - range: impl Iterator, + range: impl Iterator, ) -> *mut Table { let index = self.instance().module().table_index(index); self.instance_mut().get_table_with_lazy_init(index, range) diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator.rs index 7d617f0dc5a8..3734b95521c1 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator.rs @@ -545,7 +545,7 @@ fn check_table_init_bounds(instance: &mut Instance, module: &Module) -> Result<( let end = start.checked_add(usize::try_from(segment.elements.len()).unwrap()); match end { - Some(end) if end <= table.size() as usize => { + Some(end) if end <= table.size() => { // Initializer is in bounds } _ => { @@ -574,7 +574,7 @@ fn initialize_tables(instance: &mut Instance, module: &Module) -> Result<()> { }; let idx = module.table_index(table); let table = unsafe { instance.get_defined_table(table).as_mut().unwrap() }; - match module.table_plans[idx].table.wasm_ty.heap_type.top() { + match module.table_plans[idx].table.ref_type.heap_type.top() { WasmHeapTopType::Extern => { let gc_ref = VMGcRef::from_raw_u32(raw.get_externref()); let gc_store = unsafe { (*instance.store()).gc_store() }; @@ -622,7 +622,7 @@ fn initialize_tables(instance: &mut Instance, module: &Module) -> Result<()> { &mut const_evaluator, segment.table_index, &segment.elements, - start.get_u32(), + start.get_u64(), 0, segment.elements.len(), ) @@ -637,16 +637,15 @@ fn get_memory_init_start( instance: &mut Instance, module: &Module, ) -> Result { - let mem64 = instance.module().memory_plans[init.memory_index] - .memory - .memory64; let mut context = ConstEvalContext::new(instance, module); let mut const_evaluator = ConstExprEvaluator::default(); unsafe { const_evaluator.eval(&mut context, &init.offset) }.map(|v| { - if mem64 { - v.get_u64() - } else { - v.get_u32().into() + match instance.module().memory_plans[init.memory_index] + .memory + .idx_type + { + wasmtime_environ::IndexType::I32 => v.get_u32().into(), + wasmtime_environ::IndexType::I64 => v.get_u64(), } }) } @@ -707,15 +706,15 @@ fn initialize_memories(instance: &mut Instance, module: &Module) -> Result<()> { memory: wasmtime_environ::MemoryIndex, expr: &wasmtime_environ::ConstExpr, ) -> Option { - let mem64 = self.instance.module().memory_plans[memory].memory.memory64; let mut context = ConstEvalContext::new(self.instance, self.module); let val = unsafe { self.const_evaluator.eval(&mut context, expr) } .expect("const expression should be valid"); - Some(if mem64 { - val.get_u64() - } else { - val.get_u32().into() - }) + Some( + match self.instance.module().memory_plans[memory].memory.idx_type { + wasmtime_environ::IndexType::I32 => val.get_u32().into(), + wasmtime_environ::IndexType::I64 => val.get_u64(), + }, + ) } fn write( diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs index 6eaa55e0a1a8..3d3ce9dd10be 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs @@ -131,7 +131,7 @@ pub struct InstanceLimits { pub max_tables_per_module: u32, /// Maximum number of table elements per table. - pub table_elements: u32, + pub table_elements: usize, /// Maximum number of linear memories per instance. pub max_memories_per_module: u32, diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/index_allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/index_allocator.rs index 0127bff01fe9..2b6cbb4dcc82 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/index_allocator.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/index_allocator.rs @@ -491,9 +491,9 @@ mod test { fn test_next_available_allocation_strategy() { for size in 0..20 { let state = ModuleAffinityIndexAllocator::new(size, 0); - assert_eq!(state.num_empty_slots() as u32, size); + assert_eq!(state.num_empty_slots(), usize::try_from(size).unwrap()); for i in 0..size { - assert_eq!(state.num_empty_slots() as u32, size - i); + assert_eq!(state.num_empty_slots(), usize::try_from(size - i).unwrap()); assert_eq!(state.alloc(None).unwrap().index(), i as usize); } assert!(state.alloc(None).is_none()); diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs index 2e5dd793b94b..33cc098dc85d 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/memory_pool.rs @@ -378,7 +378,8 @@ impl MemoryPool { // the process to continue, because we never perform a // mmap that would leave an open space for someone // else to come in and map something. - slot.instantiate(initial_size as usize, image, memory_plan)?; + let initial_size = usize::try_from(initial_size).unwrap(); + slot.instantiate(initial_size, image, memory_plan)?; Memory::new_static( memory_plan, diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs index 9db1cde6d3b6..8141391cb94d 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs @@ -35,7 +35,7 @@ impl TablePool { // from its actual elements. let table_size = round_up_to_pow2( crate::runtime::vm::table::MAX_TABLE_ELEM_SIZE - .checked_mul(config.limits.table_elements as usize) + .checked_mul(config.limits.table_elements) .ok_or_else(|| anyhow!("table size exceeds addressable memory"))?, page_size, ); @@ -83,11 +83,11 @@ impl TablePool { } for (i, plan) in module.table_plans.iter().skip(module.num_imported_tables) { - if plan.table.minimum > u32::try_from(self.table_elements).unwrap() { + if plan.table.limits.min > u64::try_from(self.table_elements)? { bail!( "table index {} has a minimum element size of {} which exceeds the limit of {}", i.as_u32(), - plan.table.minimum, + plan.table.limits.min, self.table_elements, ); } @@ -131,7 +131,7 @@ impl TablePool { let base = self.get(allocation_index); let element_size = - crate::vm::table::wasm_to_table_type(table_plan.table.wasm_ty).element_size(); + crate::vm::table::wasm_to_table_type(table_plan.table.ref_type).element_size(); unsafe { commit_pages(base as *mut u8, self.table_elements * element_size)?; @@ -195,7 +195,7 @@ impl TablePool { let element_size = table.element_type().element_size(); - let size = round_up_to_pow2(table.size() as usize * element_size, self.page_size); + let size = round_up_to_pow2(table.size() * element_size, self.page_size); // `memset` the first `keep_resident` bytes. let size_to_memset = size.min(self.keep_resident); diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs index 2bfe64612216..76dcdd99940d 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/unix_stack_pool.rs @@ -205,8 +205,9 @@ impl StackPool { let index = (start_of_stack - base) / self.stack_size; assert!(index < self.max_stacks); + let index = u32::try_from(index).unwrap(); - self.index_allocator.free(SlotId(index as u32)); + self.index_allocator.free(SlotId(index)); } } diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/wasmfx_allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/wasmfx_allocator.rs index bcbd76016f48..40cbfd9d0183 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/wasmfx_allocator.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/wasmfx_allocator.rs @@ -221,7 +221,8 @@ pub mod wasmfx_pooling { &mut self.continuations[index] as *mut VMContRef ); - self.index_allocator.free(SlotId(index as u32)); + let index = u32::try_from(index).unwrap(); + self.index_allocator.free(SlotId(index)); } } diff --git a/crates/wasmtime/src/runtime/vm/libcalls.rs b/crates/wasmtime/src/runtime/vm/libcalls.rs index 0304b9b56dae..7808dc141948 100644 --- a/crates/wasmtime/src/runtime/vm/libcalls.rs +++ b/crates/wasmtime/src/runtime/vm/libcalls.rs @@ -62,7 +62,8 @@ use crate::runtime::vm::vmcontext::VMFuncRef; use crate::runtime::vm::{Instance, TrapReason, VMGcRef}; #[cfg(feature = "threads")] use core::time::Duration; -use wasmtime_environ::{DataIndex, ElemIndex, FuncIndex, MemoryIndex, TableIndex, Trap, Unsigned}; +use wasmtime_environ::Unsigned; +use wasmtime_environ::{DataIndex, ElemIndex, FuncIndex, MemoryIndex, TableIndex, Trap}; #[cfg(feature = "wmemcheck")] use wasmtime_wmemcheck::AccessError::{ DoubleMalloc, InvalidFree, InvalidRead, InvalidWrite, OutOfBounds, @@ -141,6 +142,8 @@ pub mod raw { (@ty i32) => (u32); (@ty i64) => (u64); + (@ty f64) => (f64); + (@ty u8) => (u8); (@ty reference) => (u32); (@ty pointer) => (*mut u8); (@ty vmctx) => (*mut VMContext); @@ -207,9 +210,9 @@ fn memory32_grow( unsafe fn table_grow_func_ref( instance: &mut Instance, table_index: u32, - delta: u32, + delta: u64, init_value: *mut u8, -) -> Result { +) -> Result<*mut u8> { let table_index = TableIndex::from_u32(table_index); let element = match instance.table_element_type(table_index) { @@ -218,10 +221,11 @@ unsafe fn table_grow_func_ref( TableElementType::Cont => unreachable!(), }; - Ok(match instance.table_grow(table_index, delta, element)? { + let result = match instance.table_grow(table_index, delta, element)? { Some(r) => r, - None => (-1_i32).unsigned(), - }) + None => usize::MAX, + }; + Ok(result as *mut _) } /// Implementation of `table.grow` for GC-reference tables. @@ -229,9 +233,9 @@ unsafe fn table_grow_func_ref( unsafe fn table_grow_gc_ref( instance: &mut Instance, table_index: u32, - delta: u32, + delta: u64, init_value: u32, -) -> Result { +) -> Result<*mut u8> { let table_index = TableIndex::from_u32(table_index); let element = match instance.table_element_type(table_index) { @@ -239,26 +243,25 @@ unsafe fn table_grow_gc_ref( TableElementType::GcRef => VMGcRef::from_raw_u32(init_value) .map(|r| (*instance.store()).gc_store().clone_gc_ref(&r)) .into(), - TableElementType::Cont => { - panic!("Wrong table growing function") - } + TableElementType::Cont => unreachable!(), }; - Ok(match instance.table_grow(table_index, delta, element)? { + let result = match instance.table_grow(table_index, delta, element)? { Some(r) => r, - None => (-1_i32).unsigned(), - }) + None => usize::MAX, + }; + Ok(result as *mut _) } unsafe fn table_grow_cont_obj( instance: &mut Instance, table_index: u32, - delta: u32, + delta: u64, // The following two values together form the intitial Option. // A None value is indicated by the pointer being null. init_value_contref: *mut u8, init_value_revision: u64, -) -> Result { +) -> Result<*mut u8> { use core::ptr::NonNull; let init_value = if init_value_contref.is_null() { None @@ -276,19 +279,20 @@ unsafe fn table_grow_cont_obj( _ => panic!("Wrong table growing function"), }; - Ok(match instance.table_grow(table_index, delta, element)? { + let result = match instance.table_grow(table_index, delta, element)? { Some(r) => r, - None => (-1_i32).unsigned(), - }) + None => usize::MAX, + }; + Ok(result as *mut _) } /// Implementation of `table.fill` for `funcref`s. unsafe fn table_fill_func_ref( instance: &mut Instance, table_index: u32, - dst: u32, + dst: u64, val: *mut u8, - len: u32, + len: u64, ) -> Result<(), Trap> { let table_index = TableIndex::from_u32(table_index); let table = &mut *instance.get_table(table_index); @@ -306,9 +310,9 @@ unsafe fn table_fill_func_ref( unsafe fn table_fill_gc_ref( instance: &mut Instance, table_index: u32, - dst: u32, + dst: u64, val: u32, - len: u32, + len: u64, ) -> Result<(), Trap> { let table_index = TableIndex::from_u32(table_index); let table = &mut *instance.get_table(table_index); @@ -328,10 +332,10 @@ unsafe fn table_fill_gc_ref( unsafe fn table_fill_cont_obj( instance: &mut Instance, table_index: u32, - dst: u32, + dst: u64, value_contref: *mut u8, value_revision: u64, - len: u32, + len: u64, ) -> Result<(), Trap> { use core::ptr::NonNull; let table_index = TableIndex::from_u32(table_index); @@ -358,15 +362,15 @@ unsafe fn table_copy( instance: &mut Instance, dst_table_index: u32, src_table_index: u32, - dst: u32, - src: u32, - len: u32, + dst: u64, + src: u64, + len: u64, ) -> Result<(), Trap> { let dst_table_index = TableIndex::from_u32(dst_table_index); let src_table_index = TableIndex::from_u32(src_table_index); let dst_table = instance.get_table(dst_table_index); // Lazy-initialize the whole range in the source table first. - let src_range = src..(src.checked_add(len).unwrap_or(u32::MAX)); + let src_range = src..(src.checked_add(len).unwrap_or(u64::MAX)); let src_table = instance.get_table_with_lazy_init(src_table_index, src_range); let gc_store = (*instance.store()).gc_store(); Table::copy(gc_store, dst_table, src_table, dst, src, len) @@ -377,9 +381,9 @@ fn table_init( instance: &mut Instance, table_index: u32, elem_index: u32, - dst: u32, - src: u32, - len: u32, + dst: u64, + src: u64, + len: u64, ) -> Result<(), Trap> { let table_index = TableIndex::from_u32(table_index); let elem_index = ElemIndex::from_u32(elem_index); @@ -415,6 +419,7 @@ fn memory_fill( len: u64, ) -> Result<(), Trap> { let memory_index = MemoryIndex::from_u32(memory_index); + #[allow(clippy::cast_possible_truncation)] instance.memory_fill(memory_index, dst, val as u8, len) } @@ -450,7 +455,7 @@ fn data_drop(instance: &mut Instance, data_index: u32) { unsafe fn table_get_lazy_init_func_ref( instance: &mut Instance, table_index: u32, - index: u32, + index: u64, ) -> *mut u8 { let table_index = TableIndex::from_u32(table_index); let table = instance.get_table_with_lazy_init(table_index, core::iter::once(index)); @@ -500,43 +505,6 @@ unsafe fn gc(instance: &mut Instance, gc_ref: u32) -> Result { } } -/// Perform a Wasm `global.get` for GC reference globals. -#[cfg(feature = "gc")] -unsafe fn gc_ref_global_get(instance: &mut Instance, index: u32) -> Result { - use core::num::NonZeroUsize; - - let index = wasmtime_environ::GlobalIndex::from_u32(index); - let global = instance.defined_or_imported_global_ptr(index); - let gc_store = (*instance.store()).gc_store(); - - if gc_store - .gc_heap - .need_gc_before_entering_wasm(NonZeroUsize::new(1).unwrap()) - { - (*instance.store()).gc(None)?; - } - - match (*global).as_gc_ref() { - None => Ok(0), - Some(gc_ref) => { - let gc_ref = gc_store.clone_gc_ref(gc_ref); - let ret = gc_ref.as_raw_u32(); - gc_store.expose_gc_ref_to_wasm(gc_ref); - Ok(ret) - } - } -} - -/// Perform a Wasm `global.set` for GC reference globals. -#[cfg(feature = "gc")] -unsafe fn gc_ref_global_set(instance: &mut Instance, index: u32, gc_ref: u32) { - let index = wasmtime_environ::GlobalIndex::from_u32(index); - let global = instance.defined_or_imported_global_ptr(index); - let gc_ref = VMGcRef::from_raw_u32(gc_ref); - let gc_store = (*instance.store()).gc_store(); - (*global).write_gc_ref(gc_store, gc_ref.as_ref()); -} - // Implementation of `memory.atomic.notify` for locally defined memories. #[cfg(feature = "threads")] fn memory_atomic_notify( @@ -721,6 +689,60 @@ fn update_mem_size(instance: &mut Instance, num_pages: u32) { } } +fn trap(_instance: &mut Instance, code: u8) -> Result<(), TrapReason> { + Err(TrapReason::Wasm( + wasmtime_environ::Trap::from_u8(code).unwrap(), + )) +} + +fn f64_to_i64(_instance: &mut Instance, val: f64) -> Result { + if val.is_nan() { + return Err(TrapReason::Wasm(Trap::BadConversionToInteger)); + } + let val = relocs::truncf64(val); + if val <= -9223372036854777856.0 || val >= 9223372036854775808.0 { + return Err(TrapReason::Wasm(Trap::IntegerOverflow)); + } + #[allow(clippy::cast_possible_truncation)] + return Ok((val as i64).unsigned()); +} + +fn f64_to_u64(_instance: &mut Instance, val: f64) -> Result { + if val.is_nan() { + return Err(TrapReason::Wasm(Trap::BadConversionToInteger)); + } + let val = relocs::truncf64(val); + if val <= -1.0 || val >= 18446744073709551616.0 { + return Err(TrapReason::Wasm(Trap::IntegerOverflow)); + } + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + return Ok(val as u64); +} + +fn f64_to_i32(_instance: &mut Instance, val: f64) -> Result { + if val.is_nan() { + return Err(TrapReason::Wasm(Trap::BadConversionToInteger)); + } + let val = relocs::truncf64(val); + if val <= -2147483649.0 || val >= 2147483648.0 { + return Err(TrapReason::Wasm(Trap::IntegerOverflow)); + } + #[allow(clippy::cast_possible_truncation)] + return Ok((val as i32).unsigned()); +} + +fn f64_to_u32(_instance: &mut Instance, val: f64) -> Result { + if val.is_nan() { + return Err(TrapReason::Wasm(Trap::BadConversionToInteger)); + } + let val = relocs::truncf64(val); + if val <= -1.0 || val >= 4294967296.0 { + return Err(TrapReason::Wasm(Trap::IntegerOverflow)); + } + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + return Ok(val as u32); +} + /// This module contains functions which are used for resolving relocations at /// runtime if necessary. /// @@ -963,12 +985,16 @@ fn tc_drop_cont_ref(instance: &mut Instance, contref: *mut u8) { fn tc_allocate(_instance: &mut Instance, size: u64, align: u64) -> Result<*mut u8, TrapReason> { debug_assert!(size > 0); - let layout = - std::alloc::Layout::from_size_align(size as usize, align as usize).map_err(|_error| { - TrapReason::user_without_backtrace(anyhow::anyhow!( - "Continuation layout construction failed!" - )) - })?; + let size = usize::try_from(size) + .map_err(|_error| TrapReason::user_without_backtrace(anyhow::anyhow!("size too large!")))?; + let align = usize::try_from(align).map_err(|_error| { + TrapReason::user_without_backtrace(anyhow::anyhow!("align too large!")) + })?; + let layout = std::alloc::Layout::from_size_align(size, align).map_err(|_error| { + TrapReason::user_without_backtrace(anyhow::anyhow!( + "Continuation layout construction failed!" + )) + })?; let ptr = unsafe { alloc::alloc::alloc(layout) }; // TODO(dhil): We can consider making this a debug-build only // check. @@ -988,12 +1014,16 @@ fn tc_deallocate( align: u64, ) -> Result<(), TrapReason> { debug_assert!(size > 0); - let layout = - std::alloc::Layout::from_size_align(size as usize, align as usize).map_err(|_error| { - TrapReason::user_without_backtrace(anyhow::anyhow!( - "Continuation layout construction failed!" - )) - })?; + let size = usize::try_from(size) + .map_err(|_error| TrapReason::user_without_backtrace(anyhow::anyhow!("size too large!")))?; + let align = usize::try_from(align).map_err(|_error| { + TrapReason::user_without_backtrace(anyhow::anyhow!("align too large!")) + })?; + let layout = std::alloc::Layout::from_size_align(size, align).map_err(|_error| { + TrapReason::user_without_backtrace(anyhow::anyhow!( + "Continuation layout construction failed!" + )) + })?; Ok(unsafe { std::alloc::dealloc(ptr, layout) }) } @@ -1014,7 +1044,9 @@ fn tc_reallocate( } fn tc_print_str(_instance: &mut Instance, s: *const u8, len: u64) { - let str = unsafe { std::slice::from_raw_parts(s, len as usize) }; + let len = usize::try_from(len) + .map_err(|_error| TrapReason::user_without_backtrace(anyhow::anyhow!("len too large!"))); + let str = unsafe { std::slice::from_raw_parts(s, len.unwrap()) }; let s = std::str::from_utf8(str).unwrap(); print!("{s}"); } @@ -1036,11 +1068,17 @@ fn tc_baseline_cont_new( param_count: u64, result_count: u64, ) -> Result<*mut u8, TrapReason> { + let param_count = usize::try_from(param_count).map_err(|_error| { + TrapReason::user_without_backtrace(anyhow::anyhow!("param_count too large!")) + })?; + let result_count = usize::try_from(result_count).map_err(|_error| { + TrapReason::user_without_backtrace(anyhow::anyhow!("result_count too large!")) + })?; let ans = crate::runtime::vm::continuation::baseline::cont_new( instance, func, - param_count as usize, - result_count as usize, + param_count, + result_count, )?; let ans_ptr = ans.cast::(); assert!(ans as usize == ans_ptr as usize); @@ -1079,12 +1117,14 @@ fn tc_baseline_continuation_arguments_ptr( contref: *mut u8, nargs: u64, ) -> *mut u8 { + let nargs = usize::try_from(nargs) + .map_err(|_error| TrapReason::user_without_backtrace(anyhow::anyhow!("nargs too large!"))); let contref_ptr = contref.cast::(); assert!(contref_ptr as usize == contref as usize); let ans = crate::runtime::vm::continuation::baseline::get_arguments_ptr( instance, unsafe { &mut *(contref_ptr) }, - nargs as usize, + nargs.unwrap(), ); return ans.cast::(); } @@ -1109,8 +1149,10 @@ fn tc_baseline_clear_arguments(instance: &mut Instance, contref: *mut u8) { } fn tc_baseline_get_payloads_ptr(instance: &mut Instance, nargs: u64) -> *mut u8 { + let nargs = usize::try_from(nargs) + .map_err(|_error| TrapReason::user_without_backtrace(anyhow::anyhow!("nargs too large!"))); let ans = - crate::runtime::vm::continuation::baseline::get_payloads_ptr(instance, nargs as usize); + crate::runtime::vm::continuation::baseline::get_payloads_ptr(instance, nargs.unwrap()); let ans_ptr = ans.cast::(); assert!(ans as usize == ans_ptr as usize); return ans_ptr; diff --git a/crates/wasmtime/src/runtime/vm/memory.rs b/crates/wasmtime/src/runtime/vm/memory.rs index d36ea1dc6eed..09972c2a91e1 100644 --- a/crates/wasmtime/src/runtime/vm/memory.rs +++ b/crates/wasmtime/src/runtime/vm/memory.rs @@ -49,9 +49,7 @@ impl RuntimeMemoryCreator for DefaultMemoryCreator { } } -/// A linear memory's backing storage. -/// -/// This does not a full Wasm linear memory, as it may +/// A linear memory and its backing storage. pub trait RuntimeLinearMemory: Send + Sync { /// Returns the log2 of this memory's page size, in bytes. fn page_size_log2(&self) -> u8; @@ -653,7 +651,7 @@ impl Memory { if !store.memory_growing(0, minimum.unwrap_or(absolute_max), maximum)? { bail!( "memory minimum size of {} pages exceeds memory limits", - plan.memory.minimum + plan.memory.limits.min ); } } @@ -664,7 +662,7 @@ impl Memory { let minimum = minimum.ok_or_else(|| { format_err!( "memory minimum size of {} pages exceeds memory limits", - plan.memory.minimum + plan.memory.limits.min ) })?; @@ -811,5 +809,6 @@ pub fn validate_atomic_addr( return Err(Trap::MemoryOutOfBounds); } - Ok(def.base.wrapping_add(addr as usize)) + let addr = usize::try_from(addr).unwrap(); + Ok(def.base.wrapping_add(addr)) } diff --git a/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs b/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs index 5b8d2b44543b..0736c52e02bf 100644 --- a/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs +++ b/crates/wasmtime/src/runtime/vm/sys/unix/signals.rs @@ -248,6 +248,8 @@ unsafe extern "C" fn trap_handler( } } +#[allow(clippy::cast_possible_truncation)] // too fiddly to handle and wouldn't + // help much anyway unsafe fn get_trap_registers(cx: *mut libc::c_void, _signum: libc::c_int) -> TrapRegisters { cfg_if::cfg_if! { if #[cfg(all(any(target_os = "linux", target_os = "android"), target_arch = "x86_64"))] { diff --git a/crates/wasmtime/src/runtime/vm/table.rs b/crates/wasmtime/src/runtime/vm/table.rs index 8febce78a9b6..33da5ad6ca91 100644 --- a/crates/wasmtime/src/runtime/vm/table.rs +++ b/crates/wasmtime/src/runtime/vm/table.rs @@ -8,13 +8,14 @@ use crate::prelude::*; use crate::runtime::vm::continuation::VMContObj; use crate::runtime::vm::vmcontext::{VMFuncRef, VMTableDefinition}; use crate::runtime::vm::{GcStore, SendSyncPtr, Store, VMGcRef}; -use core::cmp; use core::ops::Range; use core::ptr::{self, NonNull}; use core::slice; +use core::{cmp, usize}; use sptr::Strict; use wasmtime_environ::{ - TablePlan, TableStyle, Trap, WasmHeapTopType, WasmRefType, FUNCREF_INIT_BIT, FUNCREF_MASK, + IndexType, TablePlan, TableStyle, Trap, WasmHeapTopType, WasmRefType, FUNCREF_INIT_BIT, + FUNCREF_MASK, }; /// An element going into or coming out of a table. @@ -223,7 +224,7 @@ pub struct StaticFuncTable { /// maximum size of the table. data: SendSyncPtr<[FuncTableElem]>, /// The current size of the table. - size: u32, + size: usize, /// Whether elements of this table are initialized lazily. lazy_init: bool, } @@ -233,7 +234,7 @@ pub struct StaticGcRefTable { /// maximum size of the table. data: SendSyncPtr<[Option]>, /// The current size of the table. - size: u32, + size: usize, } pub struct StaticContTable { @@ -241,7 +242,7 @@ pub struct StaticContTable { /// maximum size of the table. data: SendSyncPtr<[ContTableElem]>, /// The current size of the table. - size: u32, + size: usize, } pub enum DynamicTable { @@ -273,7 +274,7 @@ pub struct DynamicFuncTable { /// vector is the current size of the table. elements: Vec, /// Maximum size that `elements` can grow to. - maximum: Option, + maximum: Option, /// Whether elements of this table are initialized lazily. lazy_init: bool, } @@ -283,7 +284,7 @@ pub struct DynamicGcRefTable { /// vector is the current size of the table. elements: Vec>, /// Maximum size that `elements` can grow to. - maximum: Option, + maximum: Option, } pub struct DynamicContTable { @@ -291,7 +292,7 @@ pub struct DynamicContTable { /// vector is the current size of the table. elements: Vec, /// Maximum size that `elements` can grow to. - maximum: Option, + maximum: Option, } /// Represents an instance's table. @@ -369,23 +370,23 @@ pub(crate) fn wasm_to_table_type(ty: WasmRefType) -> TableElementType { impl Table { /// Create a new dynamic (movable) table instance for the specified table plan. pub fn new_dynamic(plan: &TablePlan, store: &mut dyn Store) -> Result { - Self::limit_new(plan, store)?; - let TableStyle::CallerChecksSignature { lazy_init } = plan.style; - match wasm_to_table_type(plan.table.wasm_ty) { - TableElementType::Func => Ok(Self::from(DynamicFuncTable { - elements: vec![None; usize::try_from(plan.table.minimum).unwrap()], - maximum: plan.table.maximum, - lazy_init, - })), + let (minimum, maximum) = Self::limit_new(plan, store)?; + match wasm_to_table_type(plan.table.ref_type) { + TableElementType::Func => { + let TableStyle::CallerChecksSignature { lazy_init } = plan.style; + Ok(Self::from(DynamicFuncTable { + elements: vec![None; minimum], + maximum, + lazy_init, + })) + } TableElementType::GcRef => Ok(Self::from(DynamicGcRefTable { - elements: (0..usize::try_from(plan.table.minimum).unwrap()) - .map(|_| None) - .collect(), - maximum: plan.table.maximum, + elements: (0..minimum).map(|_| None).collect(), + maximum, })), TableElementType::Cont => Ok(Self::from(DynamicContTable { - elements: vec![None; usize::try_from(plan.table.minimum).unwrap()], - maximum: plan.table.maximum, + elements: vec![None; minimum], + maximum: maximum, })), } } @@ -396,15 +397,11 @@ impl Table { data: SendSyncPtr<[u8]>, store: &mut dyn Store, ) -> Result { - Self::limit_new(plan, store)?; - - let size = plan.table.minimum; - let max = plan - .table - .maximum - .map_or(usize::MAX, |x| usize::try_from(x).unwrap()); + let (minimum, maximum) = Self::limit_new(plan, store)?; + let size = minimum; + let max = maximum.unwrap_or(usize::MAX); - match wasm_to_table_type(plan.table.wasm_ty) { + match wasm_to_table_type(plan.table.ref_type) { TableElementType::Func => { let len = { let data = data.as_non_null().as_ref(); @@ -414,10 +411,10 @@ impl Table { data.len() }; ensure!( - usize::try_from(plan.table.minimum).unwrap() <= len, + usize::try_from(plan.table.limits.min).unwrap() <= len, "initial table size of {} exceeds the pooling allocator's \ configured maximum table size of {len} elements", - plan.table.minimum, + plan.table.limits.min, ); let data = SendSyncPtr::new(NonNull::slice_from_raw_parts( data.as_non_null().cast::(), @@ -439,10 +436,10 @@ impl Table { data.len() }; ensure!( - usize::try_from(plan.table.minimum).unwrap() <= len, + usize::try_from(plan.table.limits.min).unwrap() <= len, "initial table size of {} exceeds the pooling allocator's \ configured maximum table size of {len} elements", - plan.table.minimum, + plan.table.limits.min, ); let data = SendSyncPtr::new(NonNull::slice_from_raw_parts( data.as_non_null().cast::>(), @@ -459,10 +456,10 @@ impl Table { data.len() }; ensure!( - usize::try_from(plan.table.minimum).unwrap() <= len, + usize::try_from(plan.table.limits.min).unwrap() <= len, "initial table size of {} exceeds the pooling allocator's \ configured maximum table size of {len} elements", - plan.table.minimum, + plan.table.limits.min, ); let data = SendSyncPtr::new(NonNull::slice_from_raw_parts( data.as_non_null().cast::(), @@ -474,14 +471,45 @@ impl Table { } } - fn limit_new(plan: &TablePlan, store: &mut dyn Store) -> Result<()> { - if !store.table_growing(0, plan.table.minimum, plan.table.maximum)? { + // Calls the `store`'s limiter to optionally prevent the table from being created. + // + // Returns the minimum and maximum size of the table if the table can be created. + fn limit_new(plan: &TablePlan, store: &mut dyn Store) -> Result<(usize, Option)> { + // No matter how the table limits are specified + // The table size is limited by the host's pointer size + let absolute_max = usize::MAX; + + // If the minimum overflows the host's pointer size, then we can't satisfy this request. + // We defer the error to later so the `store` can be informed. + let minimum = usize::try_from(plan.table.limits.min).ok(); + + // The maximum size of the table is limited by: + // * the host's pointer size. + // * the table's maximum size if defined. + // * if the table is 64-bit. + let maximum = match (plan.table.limits.max, plan.table.idx_type) { + (Some(max), _) => usize::try_from(max).ok(), + (None, IndexType::I64) => usize::try_from(u64::MAX).ok(), + (None, IndexType::I32) => usize::try_from(u32::MAX).ok(), + }; + + // Inform the store's limiter what's about to happen. + if !store.table_growing(0, minimum.unwrap_or(absolute_max), maximum)? { bail!( "table minimum size of {} elements exceeds table limits", - plan.table.minimum + plan.table.limits.min ); } - Ok(()) + + // At this point we need to actually handle overflows, so bail out with + // an error if we made it this far. + let minimum = minimum.ok_or_else(|| { + format_err!( + "table minimum size of {} elements exceeds table limits", + plan.table.limits.min + ) + })?; + Ok((minimum, maximum)) } /// Returns the type of the elements in this table. @@ -506,20 +534,16 @@ impl Table { } /// Returns the number of allocated elements. - pub fn size(&self) -> u32 { + pub fn size(&self) -> usize { match self { Table::Static(StaticTable::Func(StaticFuncTable { size, .. })) => *size, Table::Static(StaticTable::GcRef(StaticGcRefTable { size, .. })) => *size, Table::Static(StaticTable::Cont(StaticContTable { size, .. })) => *size, - Table::Dynamic(DynamicTable::Func(DynamicFuncTable { elements, .. })) => { - elements.len().try_into().unwrap() - } + Table::Dynamic(DynamicTable::Func(DynamicFuncTable { elements, .. })) => elements.len(), Table::Dynamic(DynamicTable::GcRef(DynamicGcRefTable { elements, .. })) => { - elements.len().try_into().unwrap() - } - Table::Dynamic(DynamicTable::Cont(DynamicContTable { elements, .. })) => { - elements.len().try_into().unwrap() + elements.len() } + Table::Dynamic(DynamicTable::Cont(DynamicContTable { elements, .. })) => elements.len(), } } @@ -529,17 +553,11 @@ impl Table { /// /// The runtime maximum may not be equal to the maximum from the table's Wasm type /// when it is being constrained by an instance allocator. - pub fn maximum(&self) -> Option { + pub fn maximum(&self) -> Option { match self { - Table::Static(StaticTable::Func(StaticFuncTable { data, .. })) => { - Some(u32::try_from(data.len()).unwrap()) - } - Table::Static(StaticTable::GcRef(StaticGcRefTable { data, .. })) => { - Some(u32::try_from(data.len()).unwrap()) - } - Table::Static(StaticTable::Cont(StaticContTable { data, .. })) => { - Some(u32::try_from(data.len()).unwrap()) - } + Table::Static(StaticTable::Cont(StaticContTable { data, .. })) => Some(data.len()), + Table::Static(StaticTable::Func(StaticFuncTable { data, .. })) => Some(data.len()), + Table::Static(StaticTable::GcRef(StaticGcRefTable { data, .. })) => Some(data.len()), Table::Dynamic(DynamicTable::Func(DynamicFuncTable { maximum, .. })) => *maximum, Table::Dynamic(DynamicTable::GcRef(DynamicGcRefTable { maximum, .. })) => *maximum, Table::Dynamic(DynamicTable::Cont(DynamicContTable { maximum, .. })) => *maximum, @@ -553,7 +571,7 @@ impl Table { /// Panics if the table is not a function table. pub fn init_func( &mut self, - dst: u32, + dst: u64, items: impl ExactSizeIterator, ) -> Result<(), Trap> { let dst = usize::try_from(dst).map_err(|_| Trap::TableOutOfBounds)?; @@ -575,7 +593,7 @@ impl Table { /// Returns a trap error on out-of-bounds accesses. pub fn init_gc_refs( &mut self, - dst: u32, + dst: u64, items: impl ExactSizeIterator>, ) -> Result<(), Trap> { let dst = usize::try_from(dst).map_err(|_| Trap::TableOutOfBounds)?; @@ -602,16 +620,17 @@ impl Table { pub fn fill( &mut self, gc_store: &mut GcStore, - dst: u32, + dst: u64, val: TableElement, - len: u32, + len: u64, ) -> Result<(), Trap> { - let start = dst as usize; + let start = usize::try_from(dst).map_err(|_| Trap::TableOutOfBounds)?; + let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds)?; let end = start - .checked_add(len as usize) + .checked_add(len) .ok_or_else(|| Trap::TableOutOfBounds)?; - if end > self.size() as usize { + if end > self.size() { return Err(Trap::TableOutOfBounds); } @@ -667,10 +686,10 @@ impl Table { /// this unsafety. pub unsafe fn grow( &mut self, - delta: u32, + delta: u64, init_value: TableElement, store: &mut dyn Store, - ) -> Result, Error> { + ) -> Result, Error> { let old_size = self.size(); // Don't try to resize the table if its size isn't changing, just return @@ -678,6 +697,9 @@ impl Table { if delta == 0 { return Ok(Some(old_size)); } + // Cannot return `Trap::TableOutOfBounds` here becase `impl std::error::Error for Trap` is not available in no-std. + let delta = + usize::try_from(delta).map_err(|_| format_err!("delta exceeds host pointer size"))?; let new_size = match old_size.checked_add(delta) { Some(s) => s, @@ -707,25 +729,19 @@ impl Table { match self { Table::Static(StaticTable::Func(StaticFuncTable { data, size, .. })) => { unsafe { - debug_assert!(data.as_ref()[*size as usize..new_size as usize] - .iter() - .all(|x| x.is_none())); + debug_assert!(data.as_ref()[*size..new_size].iter().all(|x| x.is_none())); } *size = new_size; } Table::Static(StaticTable::GcRef(StaticGcRefTable { data, size })) => { unsafe { - debug_assert!(data.as_ref()[*size as usize..new_size as usize] - .iter() - .all(|x| x.is_none())); + debug_assert!(data.as_ref()[*size..new_size].iter().all(|x| x.is_none())); } *size = new_size; } Table::Static(StaticTable::Cont(StaticContTable { data, size })) => { unsafe { - debug_assert!(data.as_ref()[*size as usize..new_size as usize] - .iter() - .all(|x| x.is_none())); + debug_assert!(data.as_ref()[*size..new_size].iter().all(|x| x.is_none())); } *size = new_size; } @@ -748,8 +764,14 @@ impl Table { } } - self.fill(store.gc_store(), old_size, init_value, delta) - .expect("table should not be out of bounds"); + // casting to u64 is ok to unwrap + self.fill( + store.gc_store(), + u64::try_from(old_size).unwrap(), + init_value, + u64::try_from(delta).unwrap(), + ) + .expect("table should not be out of bounds"); Ok(Some(old_size)) } @@ -757,7 +779,7 @@ impl Table { /// Get reference to the specified element. /// /// Returns `None` if the index is out of bounds. - pub fn get(&self, gc_store: &mut GcStore, index: u32) -> Option { + pub fn get(&self, gc_store: &mut GcStore, index: u64) -> Option { let index = usize::try_from(index).ok()?; match self.element_type() { TableElementType::Func => { @@ -789,8 +811,8 @@ impl Table { /// # Panics /// /// Panics if `elem` is not of the right type for this table. - pub fn set(&mut self, index: u32, elem: TableElement) -> Result<(), ()> { - let index = usize::try_from(index).map_err(|_| ())?; + pub fn set(&mut self, index: u64, elem: TableElement) -> Result<(), ()> { + let index: usize = index.try_into().map_err(|_| ())?; match elem { TableElement::FuncRef(f) => { let (funcrefs, lazy_init) = self.funcrefs_mut(); @@ -820,12 +842,16 @@ impl Table { gc_store: &mut GcStore, dst_table: *mut Self, src_table: *mut Self, - dst_index: u32, - src_index: u32, - len: u32, + dst_index: u64, + src_index: u64, + len: u64, ) -> Result<(), Trap> { // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-copy + let src_index = usize::try_from(src_index).map_err(|_| Trap::TableOutOfBounds)?; + let dst_index = usize::try_from(dst_index).map_err(|_| Trap::TableOutOfBounds)?; + let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds)?; + if src_index .checked_add(len) .map_or(true, |n| n > (*src_table).size()) @@ -841,8 +867,8 @@ impl Table { "table element type mismatch" ); - let src_range = src_index as usize..src_index as usize + len as usize; - let dst_range = dst_index as usize..dst_index as usize + len as usize; + let src_range = src_index..src_index + len; + let dst_range = dst_index..dst_index + len; // Check if the tables are the same as we cannot mutably borrow and also borrow the same `RefCell` if ptr::eq(dst_table, src_table) { @@ -876,13 +902,13 @@ impl Table { Table::Dynamic(DynamicTable::Func(DynamicFuncTable { elements, .. })) => { VMTableDefinition { base: elements.as_mut_ptr().cast(), - current_elements: elements.len().try_into().unwrap(), + current_elements: elements.len(), } } Table::Dynamic(DynamicTable::GcRef(DynamicGcRefTable { elements, .. })) => { VMTableDefinition { base: elements.as_mut_ptr().cast(), - current_elements: elements.len().try_into().unwrap(), + current_elements: elements.len(), } } Table::Dynamic(DynamicTable::Cont(DynamicContTable { elements, .. })) => { diff --git a/crates/wasmtime/src/runtime/vm/traphandlers.rs b/crates/wasmtime/src/runtime/vm/traphandlers.rs index 2fa9197b8efe..835d9d922dd3 100644 --- a/crates/wasmtime/src/runtime/vm/traphandlers.rs +++ b/crates/wasmtime/src/runtime/vm/traphandlers.rs @@ -581,7 +581,7 @@ impl CallThreadState { Some(unsafe { Backtrace::new_with_trap_state(limits, self, trap_pc_and_fp) }) } - pub(crate) fn iter<'a>(&'a self) -> impl Iterator + 'a { + pub(crate) fn iter<'a>(&'a self) -> impl Iterator + 'a { let mut state = Some(self); core::iter::from_fn(move || { let this = state?; diff --git a/crates/wasmtime/src/runtime/vm/vmcontext.rs b/crates/wasmtime/src/runtime/vm/vmcontext.rs index b7d0035eee70..cd2b3658745c 100644 --- a/crates/wasmtime/src/runtime/vm/vmcontext.rs +++ b/crates/wasmtime/src/runtime/vm/vmcontext.rs @@ -79,12 +79,12 @@ mod test_vmfunction_import { use super::VMFunctionImport; use core::mem::offset_of; use std::mem::size_of; - use wasmtime_environ::{Module, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, VMOffsets}; #[test] fn check_vmfunction_import_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.size_of_vmfunction_import()) @@ -144,12 +144,12 @@ mod test_vmtable_import { use super::VMTableImport; use core::mem::offset_of; use std::mem::size_of; - use wasmtime_environ::{Module, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, VMOffsets}; #[test] fn check_vmtable_import_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.size_of_vmtable_import()) @@ -190,12 +190,12 @@ mod test_vmmemory_import { use super::VMMemoryImport; use core::mem::offset_of; use std::mem::size_of; - use wasmtime_environ::{Module, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, VMOffsets}; #[test] fn check_vmmemory_import_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.size_of_vmmemory_import()) @@ -234,12 +234,12 @@ mod test_vmglobal_import { use super::VMGlobalImport; use core::mem::offset_of; use std::mem::size_of; - use wasmtime_environ::{Module, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, VMOffsets}; #[test] fn check_vmglobal_import_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.size_of_vmglobal_import()) @@ -276,7 +276,7 @@ mod test_vmtag_import { #[test] fn check_vmtag_import_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(u8::try_from(size_of::<*mut u8>()).unwrap(), &module); assert_eq!( size_of::(), usize::from(offsets.size_of_vmtag_import()) @@ -334,12 +334,12 @@ mod test_vmmemory_definition { use super::VMMemoryDefinition; use core::mem::offset_of; use std::mem::size_of; - use wasmtime_environ::{Module, PtrSize, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, PtrSize, VMOffsets}; #[test] fn check_vmmemory_definition_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.ptr.size_of_vmmemory_definition()) @@ -370,7 +370,7 @@ pub struct VMTableDefinition { pub base: *mut u8, /// The current number of elements in the table. - pub current_elements: u32, + pub current_elements: usize, } #[cfg(test)] @@ -378,12 +378,12 @@ mod test_vmtable_definition { use super::VMTableDefinition; use core::mem::offset_of; use std::mem::size_of; - use wasmtime_environ::{Module, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, VMOffsets}; #[test] fn check_vmtable_definition_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.size_of_vmtable_definition()) @@ -414,7 +414,7 @@ pub struct VMGlobalDefinition { mod test_vmglobal_definition { use super::VMGlobalDefinition; use std::mem::{align_of, size_of}; - use wasmtime_environ::{Module, PtrSize, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, PtrSize, VMOffsets}; #[test] fn check_vmglobal_definition_alignment() { @@ -428,7 +428,7 @@ mod test_vmglobal_definition { #[test] fn check_vmglobal_definition_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.ptr.size_of_vmglobal_definition()) @@ -438,7 +438,7 @@ mod test_vmglobal_definition { #[test] fn check_vmglobal_begins_aligned() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!(offsets.vmctx_globals_begin() % 16, 0); } @@ -647,12 +647,12 @@ impl VMGlobalDefinition { mod test_vmshared_type_index { use super::VMSharedTypeIndex; use std::mem::size_of; - use wasmtime_environ::{Module, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, VMOffsets}; #[test] fn check_vmshared_type_index() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.size_of_vmshared_type_index()) @@ -684,7 +684,7 @@ mod test_vmtag_definition { #[test] fn check_vmtag_definition_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(u8::try_from(size_of::<*mut u8>()).unwrap(), &module); assert_eq!( size_of::(), usize::from(offsets.ptr.size_of_vmtag_definition()) @@ -694,7 +694,7 @@ mod test_vmtag_definition { #[test] fn check_vmtag_begins_aligned() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(u8::try_from(size_of::<*mut u8>()).unwrap(), &module); assert_eq!(offsets.vmctx_tags_begin() % 16, 0); } } @@ -751,12 +751,12 @@ mod test_vm_func_ref { use super::VMFuncRef; use core::mem::offset_of; use std::mem::size_of; - use wasmtime_environ::{Module, PtrSize, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, PtrSize, VMOffsets}; #[test] fn check_vm_func_ref_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( size_of::(), usize::from(offsets.ptr.size_of_vm_func_ref()) @@ -810,6 +810,8 @@ macro_rules! define_builtin_array { (@ty i32) => (u32); (@ty i64) => (u64); + (@ty f64) => (f64); + (@ty u8) => (u8); (@ty reference) => (u32); (@ty pointer) => (*mut u8); (@ty vmctx) => (*mut VMContext); @@ -915,13 +917,12 @@ impl Default for VMRuntimeLimits { mod test_vmruntime_limits { use super::VMRuntimeLimits; use core::mem::offset_of; - use std::mem::size_of; - use wasmtime_environ::{Module, PtrSize, VMOffsets}; + use wasmtime_environ::{HostPtr, Module, PtrSize, VMOffsets}; #[test] fn field_offsets() { let module = Module::new(); - let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module); + let offsets = VMOffsets::new(HostPtr, &module); assert_eq!( offset_of!(VMRuntimeLimits, stack_limit), usize::from(offsets.ptr.vmruntime_limits_stack_limit()) diff --git a/crates/wast/src/spectest.rs b/crates/wast/src/spectest.rs index f69213af978a..924bf66d1c40 100644 --- a/crates/wast/src/spectest.rs +++ b/crates/wast/src/spectest.rs @@ -70,6 +70,10 @@ pub fn link_spectest( let table = Table::new(&mut *store, ty, Ref::Func(None))?; linker.define(&mut *store, "spectest", "table", table)?; + let ty = TableType::new64(RefType::FUNCREF, 10, Some(20)); + let table = Table::new(&mut *store, ty, Ref::Func(None))?; + linker.define(&mut *store, "spectest", "table64", table)?; + let ty = MemoryType::new(1, Some(2)); let memory = Memory::new(&mut *store, ty)?; linker.define(&mut *store, "spectest", "memory", memory)?; diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 983a7dbe36fa..d97eb87c7106 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -19,6 +19,7 @@ pub struct WastContext { /// recently defined. current: Option, core_linker: Linker, + modules: HashMap, #[cfg(feature = "component-model")] component_linker: component::Linker, store: Store, @@ -52,6 +53,13 @@ enum Results { Component(Vec), } +#[derive(Clone)] +enum ModuleKind { + Core(Module), + #[cfg(feature = "component-model")] + Component(component::Component), +} + enum InstanceKind { Core(Instance), #[cfg(feature = "component-model")] @@ -85,6 +93,7 @@ where linker }, store, + modules: Default::default(), } } @@ -114,8 +123,7 @@ where }) } - fn instantiate_module(&mut self, module: &[u8]) -> Result> { - let module = Module::new(self.store.engine(), module)?; + fn instantiate_module(&mut self, module: &Module) -> Result> { Ok( match self.core_linker.instantiate(&mut self.store, &module) { Ok(i) => Outcome::Ok(i), @@ -127,16 +135,14 @@ where #[cfg(feature = "component-model")] fn instantiate_component( &mut self, - component: &[u8], + component: &component::Component, ) -> Result> { - let engine = self.store.engine(); - let component = component::Component::new(engine, component)?; Ok( match self .component_linker .instantiate(&mut self.store, &component) { - Ok(i) => Outcome::Ok((component, i)), + Ok(i) => Outcome::Ok((component.clone(), i)), Err(e) => Outcome::Trap(e), }, ) @@ -154,17 +160,17 @@ where fn perform_execute(&mut self, exec: WastExecute<'_>) -> Result { match exec { WastExecute::Invoke(invoke) => self.perform_invoke(invoke), - WastExecute::Wat(mut module) => Ok(match &mut module { - Wat::Module(m) => self - .instantiate_module(&m.encode()?)? - .map(|_| Results::Core(Vec::new())), - #[cfg(feature = "component-model")] - Wat::Component(m) => self - .instantiate_component(&m.encode()?)? - .map(|_| Results::Component(Vec::new())), - #[cfg(not(feature = "component-model"))] - Wat::Component(_) => bail!("component-model support not enabled"), - }), + WastExecute::Wat(module) => { + Ok(match self.module_definition(QuoteWat::Wat(module))? { + (_, ModuleKind::Core(module)) => self + .instantiate_module(&module)? + .map(|_| Results::Core(Vec::new())), + #[cfg(feature = "component-model")] + (_, ModuleKind::Component(component)) => self + .instantiate_component(&component)? + .map(|_| Results::Component(Vec::new())), + }) + } WastExecute::Get { module, global, .. } => self.get(module.map(|s| s.name()), global), } } @@ -214,35 +220,29 @@ where } } - /// Define a module and register it. - fn wat(&mut self, mut wat: QuoteWat<'_>) -> Result<()> { - let (is_module, name) = match &wat { - QuoteWat::Wat(Wat::Module(m)) => (true, m.id), - QuoteWat::QuoteModule(..) => (true, None), - QuoteWat::Wat(Wat::Component(m)) => (false, m.id), - QuoteWat::QuoteComponent(..) => (false, None), - }; - let bytes = wat.encode()?; - if is_module { - let instance = match self.instantiate_module(&bytes)? { - Outcome::Ok(i) => i, - Outcome::Trap(e) => return Err(e).context("instantiation failed"), - }; - if let Some(name) = name { - self.core_linker - .instance(&mut self.store, name.name(), instance)?; + /// Instantiates the `module` provided and registers the instance under the + /// `name` provided if successful. + fn module(&mut self, name: Option<&str>, module: &ModuleKind) -> Result<()> { + match module { + ModuleKind::Core(module) => { + let instance = match self.instantiate_module(&module)? { + Outcome::Ok(i) => i, + Outcome::Trap(e) => return Err(e).context("instantiation failed"), + }; + if let Some(name) = name { + self.core_linker.instance(&mut self.store, name, instance)?; + } + self.current = Some(InstanceKind::Core(instance)); } - self.current = Some(InstanceKind::Core(instance)); - } else { #[cfg(feature = "component-model")] - { - let (component, instance) = match self.instantiate_component(&bytes)? { + ModuleKind::Component(module) => { + let (component, instance) = match self.instantiate_component(&module)? { Outcome::Ok(i) => i, Outcome::Trap(e) => return Err(e).context("instantiation failed"), }; if let Some(name) = name { let ty = component.component_type(); - let mut linker = self.component_linker.instance(name.name())?; + let mut linker = self.component_linker.instance(name)?; let engine = self.store.engine().clone(); for (name, item) in ty.exports(&engine) { match item { @@ -250,22 +250,54 @@ where let module = instance.get_module(&mut self.store, name).unwrap(); linker.module(name, &module)?; } + component::types::ComponentItem::Resource(_) => { + let resource = + instance.get_resource(&mut self.store, name).unwrap(); + linker.resource(name, resource, |_, _| Ok(()))?; + } // TODO: should ideally reflect more than just - // modules into the linker's namespace but that's - // not easily supported today for host functions due - // to the inability to take a function from one - // instance and put it into the linker (must go - // through the host right now). + // modules/resources into the linker's namespace + // but that's not easily supported today for host + // functions due to the inability to take a + // function from one instance and put it into the + // linker (must go through the host right now). _ => {} } } } self.current = Some(InstanceKind::Component(instance)); } + } + Ok(()) + } + + /// Compiles the module `wat` into binary and returns the name found within + /// it, if any. + /// + /// This will not register the name within `self.modules`. + fn module_definition<'a>( + &mut self, + mut wat: QuoteWat<'a>, + ) -> Result<(Option<&'a str>, ModuleKind)> { + let (is_module, name) = match &wat { + QuoteWat::Wat(Wat::Module(m)) => (true, m.id), + QuoteWat::QuoteModule(..) => (true, None), + QuoteWat::Wat(Wat::Component(m)) => (false, m.id), + QuoteWat::QuoteComponent(..) => (false, None), + }; + let bytes = wat.encode()?; + if is_module { + let module = Module::new(self.store.engine(), &bytes)?; + Ok((name.map(|n| n.name()), ModuleKind::Core(module))) + } else { + #[cfg(feature = "component-model")] + { + let component = component::Component::new(self.store.engine(), &bytes)?; + Ok((name.map(|n| n.name()), ModuleKind::Component(component))) + } #[cfg(not(feature = "component-model"))] bail!("component-model support not enabled"); } - Ok(()) } /// Register an instance to make it available for performing actions. @@ -448,7 +480,27 @@ where use wast::WastDirective::*; match directive { - Wat(module) => self.wat(module)?, + Module(module) => { + let (name, module) = self.module_definition(module)?; + self.module(name, &module)?; + } + ModuleDefinition(module) => { + let (name, module) = self.module_definition(module)?; + if let Some(name) = name { + self.modules.insert(name.to_string(), module.clone()); + } + } + ModuleInstance { + instance, + module, + span: _, + } => { + let module = module + .and_then(|n| self.modules.get(n.name())) + .cloned() + .ok_or_else(|| anyhow!("no module named {module:?}"))?; + self.module(instance.map(|n| n.name()), &module)?; + } Register { span: _, name, @@ -488,8 +540,8 @@ where module, message, } => { - let err = match self.wat(module) { - Ok(()) => bail!("expected module to fail to build"), + let err = match self.module_definition(module) { + Ok(_) => bail!("expected module to fail to build"), Err(e) => e, }; let error_message = format!("{err:?}"); @@ -506,7 +558,7 @@ where span: _, message: _, } => { - if let Ok(_) = self.wat(module) { + if let Ok(_) = self.module_definition(module) { bail!("expected malformed module to fail to instantiate"); } } @@ -515,8 +567,9 @@ where module, message, } => { - let err = match self.wat(QuoteWat::Wat(module)) { - Ok(()) => bail!("expected module to fail to link"), + let (name, module) = self.module_definition(QuoteWat::Wat(module))?; + let err = match self.module(name, &module) { + Ok(_) => bail!("expected module to fail to link"), Err(e) => e, }; let error_message = format!("{err:?}"); @@ -556,6 +609,7 @@ where #[cfg(feature = "component-model")] component_linker: component::Linker::new(self.store.engine()), store: Store::new(self.store.engine(), self.store.data().clone()), + modules: self.modules.clone(), }; let name = thread.name.name(); let child = @@ -597,4 +651,5 @@ fn is_matching_assert_invalid_error_message(expected: &str, actual: &str) -> boo // for this scenario || (expected == "unknown global" && actual.contains("global.get of locally defined global")) || (expected == "immutable global" && actual.contains("global is immutable: cannot modify it with `global.set`")) + || (expected == "table size must be at most 2^32-1" && actual.contains("invalid u32 number: constant out of range")) } diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index e82e9e090a81..aa630827e5a2 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -2534,16 +2534,13 @@ impl<'a> InterfaceGenerator<'a> { self.src.push_str(", "); } self.src.push_str(") |"); - if self.gen.opts.async_.is_import_async(&func.name) { - uwriteln!( - self.src, - " {wt}::component::__internal::Box::new(async move {{ " - ); - } else { - self.src.push_str(" { \n"); - } + self.src.push_str(" {\n"); if self.gen.opts.tracing { + if self.gen.opts.async_.is_import_async(&func.name) { + self.src.push_str("use tracing::Instrument;\n"); + } + uwrite!( self.src, " @@ -2553,7 +2550,6 @@ impl<'a> InterfaceGenerator<'a> { module = \"{}\", function = \"{}\", ); - let _enter = span.enter(); ", match owner { TypeOwner::Interface(id) => self.resolve.interfaces[id] @@ -2565,6 +2561,23 @@ impl<'a> InterfaceGenerator<'a> { }, func.name, ); + } + + if self.gen.opts.async_.is_import_async(&func.name) { + uwriteln!( + self.src, + " {wt}::component::__internal::Box::new(async move {{ " + ); + } else { + // Only directly enter the span if the function is sync. Otherwise + // we use tracing::Instrument to ensure that the span is not entered + // across an await point. + if self.gen.opts.tracing { + self.push_str("let _enter = span.enter();\n"); + } + } + + if self.gen.opts.tracing { let mut event_fields = func .params .iter() @@ -2653,10 +2666,15 @@ impl<'a> InterfaceGenerator<'a> { if self.gen.opts.async_.is_import_async(&func.name) { // Need to close Box::new and async block - self.src.push_str("})"); - } else { - self.src.push_str("}"); + + if self.gen.opts.tracing { + self.src.push_str("}.instrument(span))\n"); + } else { + self.src.push_str("})\n"); + } } + + self.src.push_str("}\n"); } fn generate_function_trait_sig(&mut self, func: &Function) { diff --git a/docs/contributing-testing.md b/docs/contributing-testing.md index c8cff4347561..558c62d63c0d 100644 --- a/docs/contributing-testing.md +++ b/docs/contributing-testing.md @@ -17,27 +17,28 @@ follows: rustup target add wasm32-wasip1 wasm32-unknown-unknown ``` -## Running All Tests - -To run all of Wasmtime's tests, execute this command: - -```shell -cargo test --workspace -``` - -You can also exclude a particular crate from testing with `--exclude`. For -example, if you want to avoid testing the `wastime-fuzzing` crate — which -requires that `libclang` is installed on your system, and for some reason maybe -you don't have it — you can run: +## Running Tests + +Depending on what you're modifying there's a few commands you may be the most +interested: + +* `cargo test` - used to run the `tests/*` folder at the top-level. This tests + the CLI and contains most tests for the `wasmtime` crate itself. This will + also run all spec tests. Note that this does not run all tests in the + repository, but it's generally a good starting point. +* `cargo test -p cranelift-tools` - used if you're working on Cranelift and this + will run all the tests at `cranelift/filetests/filetests`. You can also, + within the `cranelift` folder, run `cargo run test ./filetests` to run these + tests. +* `cargo test -p wasmtime-wasi` - this will run all WASI tests for the + `wasmtime-wasi` crate. + +At this time not all of the crates in the Wasmtime workspace can be tested, so +running all tests is a little non-standard. To match what CI does and run all +tests you'll need to execute ```shell -cargo test --workspace --exclude wasmtime-fuzzing -``` - -Similarly, to skip WASI integration tests, run: - -```shell -cargo test --workspace --exclude test-programs +./ci/run-tests.sh ``` ## Testing a Specific Crate @@ -68,22 +69,44 @@ git submodule update --init ``` When the submodule is checked out, Wasmtime runs the Wasm spec testsuite as part -of testing the `wasmtime-cli` crate: +of testing the `wasmtime-cli` crate at the crate root, meaning in the root of +the repository you can execute: ```shell -cargo test -p wasmtime-cli +cargo test --test wast ``` -## Running WASI Integration Tests Only +You can pass an additional CLI argument to act as a filter on which tests to +run. For example to only run the spec tests themselves (excluding handwritten +Wasmtime-specific tests) and only in Cranelift you can run: + +```shell +cargo test --test wast Cranelift/tests/spec +``` + +Note that in general spec tests are executed regardless of whether they pass +or not. In `tests/wast.rs` there's a `should_fail` function which indicates the +expected result of the test. When adding new spec tests or implementing features +this function will need to be updated as tests change from failing to passing. + +## Running WASI Integration Tests WASI integration tests can be run separately from all other tests which -can be useful when working on the `wasi-common` crate. This can be done by +can be useful when working on the `wasmtime-wasi` crate. This can be done by executing this command: ```shell -cargo test -p test-programs +cargo test -p wasmtime-wasi ``` +Similarly if you're testing HTTP-related functionality you can execute: + +```shell +cargo test -p wasmtime-wasi-http +``` + +Note that these tests will compile programs in `crates/test-programs` to run. + ## Adding New Tests ### Adding Rust's `#[test]`-Style Tests @@ -109,42 +132,71 @@ mod tests { If you're writing a unit test and a `test` module doesn't already exist, you can create one. -For more "integration-y" tests, we create a `tests` directory within the crate, -and put the tests inside there. For example, there are various code -cache-related tests at `crates/environ/tests/cache_*.rs`. Always feel free to -add a `tests` directory to a crate, if you want to add a new test and there -aren't any existing tests. +For more "integration-y" tests, each crate supports a separate `tests` directory +within the crate, and put the tests inside there. Most integration tests in +Wasmtime are located in the root `tests/*.rs` location, notably +`tests/all/*.rs`. This tests much of the `wasmtime` crate for example and +facilitates `cargo test` at the repository root running most tests. + +Some tests make more sense to live per-crate, though. For example, many WASI +tests are at `crates/wasi/tests/*.rs`. For adding a test feel free to add it +wherever feels best, there's not really a strong reason to put it in one place +over another. While it's easiest to add to existing tests it's ok to add a new +`tests` directory with tests too. ### Adding Specification-Style Wast Tests We use the spec testsuite as-is and without custom patches or a forked -version. This probably isn't what you want to modify when adding a new Wasmtime -test! +version via a submodule at `tests/spec_testsuite`. This probably isn't what you +want to modify when adding a new Wasmtime test! When you have a Wasmtime-specific test that you'd like to write in Wast and use the Wast-style assertions, you can add it to our "misc testsuite". The misc testsuite uses the same syntax and assertions as the spec testsuite, but lives in `tests/misc_testsuite`. Feel free to add new tests to existing `tests/misc_testsuite/*.wast` files or create new ones as needed. These tests -are run as part of the `wasmtime-cli` crate's tests. +are run from the crate root: + +```shell +cargo test --test wast +``` If you have a new test that you think really belongs in the spec testsuite, make sure it makes sense for every Wasm implementation to run your test (i.e. it isn't Wasmtime-specific) and send a pull request -[upstream](https://github.com/WebAssembly/testsuite/). Once it is accepted in -the upstream repo, we can update our git submodule and we'll start running the -new tests. +[upstream](https://github.com/WebAssembly/spec). Once it is accepted in the +upstream repo, it'll make its way to the test-specific mirror at +[WebAssembly/testsuite](https://github.com/WebAssembly/testsuite) and then we +can update our git submodule and we'll start running the new tests. ### Adding WASI Integration Tests When you have a WASI-specific test program that you'd like to include as a test case to run against our WASI implementation, you can add it to our `test-programs` crate. In particular, you should drop a main-style Rust source -file into `crates/test-programs/wasi-tests/src/bin/some_new_test.rs` with a -name of your choice. And that's it! The build script included in the -`test-programs` crate will automatically generate the necessary boilerplate -code for your test program so that it's run on all supported hosts. - -If you would like to tweak which host to run the test program against however -(for instance, only on Unix but on Windows), you can tweak that in the build -script located under `crates/test-programs/build.rs`. +file into `crates/test-programs/src/bin/PREFIX_some_new_test.rs`. Here the +`PREFIX` indicates what test suite it's going to run as. For example +`preview2_*` tests are run as part of `wasmtime-wasi` crate tests. The `cli_*` +tests are run as part of `tests/all/cli_tests.rs`. It's probably easiest to use +a preexisting prefix. The `some_new_test` name is arbitrary and is selected as +appropriate by you. + +One a test file is added you'll need to add some code to execute the tests as +well. For example if you added a new test +`crates/test-programs/src/bin/cli_my_test.rs` then you'll need to add a new +function to `tests/all/cli_tests.rs` such as: + +```rust +#[test] +fn my_test() { + // ... +} +``` + +The path to the compiled WebAssembly of your test case will be available in a +Rust-level `const` named `CLI_MY_TEST`. There is also a component version at +`CLI_MY_TEST_COMPONENT`. These are used to pass as arguments to +`wasmtime`-the-CLI for example or you can use `Module::from_file`. + +When in doubt feel free to copy existing tests and then modify them to suit your +needs. diff --git a/pulley/Cargo.toml b/pulley/Cargo.toml index b8c9f3138e1c..0c3677641a1b 100644 --- a/pulley/Cargo.toml +++ b/pulley/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0 WITH LLVM-exception" name = "pulley-interpreter" readme = "./README.md" repository = "https://github.com/bytecodealliance/wasmtime/tree/main/pulley" -version = "0.1.0" +version = "0.2.0" [lints] workspace = true diff --git a/pulley/fuzz/src/interp.rs b/pulley/fuzz/src/interp.rs index 424cfc588026..2777ef1fcc4a 100644 --- a/pulley/fuzz/src/interp.rs +++ b/pulley/fuzz/src/interp.rs @@ -63,6 +63,12 @@ fn op_is_safe_for_fuzzing(op: &Op) -> bool { Op::BrIfXulteq32(_) => false, Op::BrIfXslt32(_) => false, Op::BrIfXslteq32(_) => false, + Op::BrIfXeq64(_) => false, + Op::BrIfXneq64(_) => false, + Op::BrIfXult64(_) => false, + Op::BrIfXulteq64(_) => false, + Op::BrIfXslt64(_) => false, + Op::BrIfXslteq64(_) => false, Op::Xmov(op::Xmov { dst, .. }) => !dst.is_special(), Op::Fmov(_) => true, Op::Vmov(_) => true, diff --git a/pulley/src/disas.rs b/pulley/src/disas.rs index 912b1756d159..fc2ab7dbb3ef 100644 --- a/pulley/src/disas.rs +++ b/pulley/src/disas.rs @@ -19,6 +19,8 @@ pub struct Disassembler<'a> { disas: String, start: usize, temp: String, + offsets: bool, + hexdump: bool, } impl<'a> Disassembler<'a> { @@ -38,9 +40,27 @@ impl<'a> Disassembler<'a> { disas: String::new(), start: 0, temp: String::new(), + offsets: true, + hexdump: true, } } + /// Whether to prefix each instruction's disassembly with its offset. + /// + /// True by default. + pub fn offsets(&mut self, offsets: bool) -> &mut Self { + self.offsets = offsets; + self + } + + /// Whether to include a hexdump of the bytecode in the disassembly. + /// + /// True by default. + pub fn hexdump(&mut self, hexdump: bool) -> &mut Self { + self.hexdump = hexdump; + self + } + /// Get the disassembly thus far. pub fn disas(&self) -> &str { &self.disas @@ -176,18 +196,21 @@ macro_rules! impl_disas { } fn after_visit(&mut self) { - let size = self.bytecode.position() - self.start; - - write!(&mut self.disas, "{:8x}: ", self.start).unwrap(); - let mut need_space = false; - for byte in &self.raw_bytecode[self.start..][..size] { - write!(&mut self.disas, "{}{byte:02x}", if need_space { " " } else { "" }).unwrap(); - need_space = true; + if self.offsets { + write!(&mut self.disas, "{:8x}: ", self.start).unwrap(); } - for _ in 0..11_usize.saturating_sub(size) { - write!(&mut self.disas, " ").unwrap(); + if self.hexdump { + let size = self.bytecode.position() - self.start; + let mut need_space = false; + for byte in &self.raw_bytecode[self.start..][..size] { + let space = if need_space { " " } else { "" }; + write!(&mut self.disas, "{}{byte:02x}", space).unwrap(); + need_space = true; + } + for _ in 0..11_usize.saturating_sub(size) { + write!(&mut self.disas, " ").unwrap(); + } } - self.disas.push_str(&self.temp); self.temp.clear(); diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs index 4eed9bfe592b..664b9cf72bc5 100644 --- a/pulley/src/interp.rs +++ b/pulley/src/interp.rs @@ -718,6 +718,66 @@ impl OpVisitor for InterpreterVisitor<'_> { } } + fn br_if_xeq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { + let a = self.state[a].get_u64(); + let b = self.state[b].get_u64(); + if a == b { + self.pc_rel_jump(offset, 7) + } else { + Continuation::Continue + } + } + + fn br_if_xneq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { + let a = self.state[a].get_u64(); + let b = self.state[b].get_u64(); + if a != b { + self.pc_rel_jump(offset, 7) + } else { + Continuation::Continue + } + } + + fn br_if_xslt64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { + let a = self.state[a].get_i64(); + let b = self.state[b].get_i64(); + if a < b { + self.pc_rel_jump(offset, 7) + } else { + Continuation::Continue + } + } + + fn br_if_xslteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { + let a = self.state[a].get_i64(); + let b = self.state[b].get_i64(); + if a <= b { + self.pc_rel_jump(offset, 7) + } else { + Continuation::Continue + } + } + + fn br_if_xult64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { + let a = self.state[a].get_u64(); + let b = self.state[b].get_u64(); + if a < b { + self.pc_rel_jump(offset, 7) + } else { + Continuation::Continue + } + } + + fn br_if_xulteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return { + let a = self.state[a].get_u64(); + let b = self.state[b].get_u64(); + if a <= b { + self.pc_rel_jump(offset, 7) + } else { + Continuation::Continue + } + } + fn xmov(&mut self, dst: XReg, src: XReg) -> Self::Return { let val = self.state[src]; self.state[dst] = val; diff --git a/pulley/src/lib.rs b/pulley/src/lib.rs index 0b454f5939fe..f792b83df727 100644 --- a/pulley/src/lib.rs +++ b/pulley/src/lib.rs @@ -45,6 +45,18 @@ macro_rules! for_each_op { br_if_xult32 = BrIfXult32 { a: XReg, b: XReg, offset: PcRelOffset }; /// Branch if unsigned `a <= b`. br_if_xulteq32 = BrIfXulteq32 { a: XReg, b: XReg, offset: PcRelOffset }; + /// Branch if `a == b`. + br_if_xeq64 = BrIfXeq64 { a: XReg, b: XReg, offset: PcRelOffset }; + /// Branch if `a != `b. + br_if_xneq64 = BrIfXneq64 { a: XReg, b: XReg, offset: PcRelOffset }; + /// Branch if signed `a < b`. + br_if_xslt64 = BrIfXslt64 { a: XReg, b: XReg, offset: PcRelOffset }; + /// Branch if signed `a <= b`. + br_if_xslteq64 = BrIfXslteq64 { a: XReg, b: XReg, offset: PcRelOffset }; + /// Branch if unsigned `a < b`. + br_if_xult64 = BrIfXult64 { a: XReg, b: XReg, offset: PcRelOffset }; + /// Branch if unsigned `a <= b`. + br_if_xulteq64 = BrIfXulteq64 { a: XReg, b: XReg, offset: PcRelOffset }; /// Move between `x` registers. xmov = Xmov { dst: XReg, src: XReg }; diff --git a/pulley/tests/all/disas.rs b/pulley/tests/all/disas.rs index eb2b49a5687c..d1466b1e134c 100644 --- a/pulley/tests/all/disas.rs +++ b/pulley/tests/all/disas.rs @@ -11,19 +11,25 @@ fn encoded(ops: &[Op]) -> Vec { encoded } -fn assert_disas(ops: &[Op], expected: &str) { +#[track_caller] +fn assert_disas_with_disassembler(dis: &mut disas::Disassembler<'_>, expected: &str) { let expected = expected.trim(); eprintln!("=== expected ===\n{expected}"); - let bytecode = encoded(ops); + decode::Decoder::decode_all(dis).expect("decoding should succeed"); - let actual = disas::Disassembler::disassemble_all(&bytecode).expect("decoding failed"); - let actual = actual.trim(); + let actual = dis.disas().trim(); eprintln!("=== actual ===\n{actual}"); assert_eq!(expected, actual); } +#[track_caller] +fn assert_disas(ops: &[Op], expected: &str) { + let bytecode = encoded(ops); + assert_disas_with_disassembler(&mut disas::Disassembler::new(&bytecode), expected); +} + #[test] fn simple() { assert_disas( @@ -43,9 +49,9 @@ fn simple() { Op::Ret(Ret {}), ], r#" - 0: 2f push_frame - 1: 12 00 04 xadd32 x0, x0, x1 - 4: 30 pop_frame + 0: 35 push_frame + 1: 18 00 04 xadd32 x0, x0, x1 + 4: 36 pop_frame 5: 00 ret "#, ); @@ -76,12 +82,101 @@ fn push_pop_many() { Op::Ret(Ret {}), ], r#" - 0: 2f push_frame - 1: 32 1f 00 00 00 xpush32_many x0, x1, x2, x3, x4 - 6: 12 00 04 xadd32 x0, x0, x1 - 9: 36 1f 00 00 00 xpop32_many x0, x1, x2, x3, x4 - e: 30 pop_frame + 0: 35 push_frame + 1: 38 1f 00 00 00 xpush32_many x0, x1, x2, x3, x4 + 6: 18 00 04 xadd32 x0, x0, x1 + 9: 3c 1f 00 00 00 xpop32_many x0, x1, x2, x3, x4 + e: 36 pop_frame f: 00 ret "#, ); } + +#[test] +fn no_offsets() { + let bytecode = encoded(&[ + // Prologue. + Op::PushFrame(PushFrame {}), + // Function body. + Op::Xadd32(Xadd32 { + operands: BinaryOperands { + dst: XReg::x0, + src1: XReg::x0, + src2: XReg::x1, + }, + }), + // Epilogue. + Op::PopFrame(PopFrame {}), + Op::Ret(Ret {}), + ]); + + assert_disas_with_disassembler( + disas::Disassembler::new(&bytecode).offsets(false), + r#" +35 push_frame +18 00 04 xadd32 x0, x0, x1 +36 pop_frame +00 ret + "#, + ); +} + +#[test] +fn no_hexdump() { + let bytecode = encoded(&[ + // Prologue. + Op::PushFrame(PushFrame {}), + // Function body. + Op::Xadd32(Xadd32 { + operands: BinaryOperands { + dst: XReg::x0, + src1: XReg::x0, + src2: XReg::x1, + }, + }), + // Epilogue. + Op::PopFrame(PopFrame {}), + Op::Ret(Ret {}), + ]); + + assert_disas_with_disassembler( + disas::Disassembler::new(&bytecode).hexdump(false), + r#" + 0: push_frame + 1: xadd32 x0, x0, x1 + 4: pop_frame + 5: ret + "#, + ); +} + +#[test] +fn no_offsets_or_hexdump() { + let bytecode = encoded(&[ + // Prologue. + Op::PushFrame(PushFrame {}), + // Function body. + Op::Xadd32(Xadd32 { + operands: BinaryOperands { + dst: XReg::x0, + src1: XReg::x0, + src2: XReg::x1, + }, + }), + // Epilogue. + Op::PopFrame(PopFrame {}), + Op::Ret(Ret {}), + ]); + + assert_disas_with_disassembler( + disas::Disassembler::new(&bytecode) + .offsets(false) + .hexdump(false), + r#" +push_frame +xadd32 x0, x0, x1 +pop_frame +ret + "#, + ); +} diff --git a/pulley/tests/all/main.rs b/pulley/tests/all/main.rs index 38e113a178b6..bb35ad1c4442 100644 --- a/pulley/tests/all/main.rs +++ b/pulley/tests/all/main.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "disas")] +#[cfg(all(feature = "disas", feature = "encode"))] mod disas; #[cfg(feature = "interp")] diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index 312abdbb9d57..3ec8c45768ca 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -171,7 +171,7 @@ notes = "We (Bytecode Alliance) are the primary authors of regalloc2 and co-deve [[wildcard-audits.regalloc2]] who = "Trevor Elliott " criteria = "safe-to-deploy" -user-id = 187138 +user-id = 187138 # Trevor Elliott (elliottt) start = "2022-11-29" end = "2025-07-30" notes = """ @@ -2394,6 +2394,12 @@ who = "Alex Crichton " criteria = "safe-to-deploy" delta = "0.1.21 -> 0.1.24" +[[audits.rustc-hash]] +who = "Trevor Elliott " +criteria = "safe-to-deploy" +delta = "1.1.0 -> 2.0.0" +notes = "Chris Fallin reviewed this update with me, and we didn't find anything surprising. We did verify that the new constants did originate in the paper referenced." + [[audits.rustix]] who = "Dan Gohman " criteria = "safe-to-deploy" diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index e1f81c500991..7962ab8d332b 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -9,6 +9,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-bforest]] version = "0.111.0" audited_as = "0.110.1" @@ -17,6 +21,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-bforest]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-bitset]] version = "0.111.0" audited_as = "0.110.1" @@ -25,6 +33,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-bitset]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-codegen]] version = "0.111.0" audited_as = "0.110.1" @@ -33,6 +45,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-codegen]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-codegen-meta]] version = "0.111.0" audited_as = "0.110.1" @@ -41,6 +57,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-codegen-meta]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-codegen-shared]] version = "0.111.0" audited_as = "0.110.1" @@ -49,6 +69,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-codegen-shared]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-control]] version = "0.111.0" audited_as = "0.110.1" @@ -57,6 +81,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-control]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-entity]] version = "0.111.0" audited_as = "0.110.1" @@ -65,6 +93,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-entity]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-frontend]] version = "0.111.0" audited_as = "0.110.1" @@ -73,6 +105,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-frontend]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-interpreter]] version = "0.111.0" audited_as = "0.110.1" @@ -81,6 +117,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-interpreter]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-isle]] version = "0.111.0" audited_as = "0.110.1" @@ -89,6 +129,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-isle]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-jit]] version = "0.111.0" audited_as = "0.110.1" @@ -97,6 +141,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-jit]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-module]] version = "0.111.0" audited_as = "0.110.1" @@ -105,6 +153,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-module]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-native]] version = "0.111.0" audited_as = "0.110.1" @@ -113,6 +165,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-native]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-object]] version = "0.111.0" audited_as = "0.110.1" @@ -121,6 +177,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-object]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-reader]] version = "0.111.0" audited_as = "0.110.1" @@ -129,6 +189,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-reader]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-serde]] version = "0.111.0" audited_as = "0.110.1" @@ -137,6 +201,10 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-serde]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.cranelift-wasm]] version = "0.111.0" audited_as = "0.110.1" @@ -145,10 +213,18 @@ audited_as = "0.110.1" version = "0.112.0" audited_as = "0.110.1" +[[unpublished.cranelift-wasm]] +version = "0.113.0" +audited_as = "0.111.0" + [[unpublished.pulley-interpreter]] version = "0.1.0" audited_as = "0.0.0" +[[unpublished.pulley-interpreter]] +version = "0.2.0" +audited_as = "0.0.0" + [[unpublished.wasi-common]] version = "24.0.0" audited_as = "23.0.1" @@ -157,6 +233,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasi-common]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime]] version = "24.0.0" audited_as = "23.0.1" @@ -165,6 +245,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-asm-macros]] version = "24.0.0" audited_as = "23.0.1" @@ -173,6 +257,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-asm-macros]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-cache]] version = "24.0.0" audited_as = "23.0.1" @@ -181,6 +269,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-cache]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-cli]] version = "24.0.0" audited_as = "23.0.1" @@ -189,6 +281,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-cli]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-cli-flags]] version = "24.0.0" audited_as = "23.0.1" @@ -197,6 +293,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-cli-flags]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-component-macro]] version = "24.0.0" audited_as = "23.0.1" @@ -205,6 +305,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-component-macro]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-component-util]] version = "24.0.0" audited_as = "23.0.1" @@ -213,6 +317,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-component-util]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-cranelift]] version = "24.0.0" audited_as = "23.0.1" @@ -221,6 +329,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-cranelift]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-environ]] version = "24.0.0" audited_as = "23.0.1" @@ -229,6 +341,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-environ]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-explorer]] version = "24.0.0" audited_as = "23.0.1" @@ -237,6 +353,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-explorer]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-fiber]] version = "24.0.0" audited_as = "23.0.1" @@ -245,6 +365,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-fiber]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-jit-debug]] version = "24.0.0" audited_as = "23.0.1" @@ -253,6 +377,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-jit-debug]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-jit-icache-coherence]] version = "24.0.0" audited_as = "23.0.1" @@ -261,6 +389,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-jit-icache-coherence]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-slab]] version = "24.0.0" audited_as = "23.0.1" @@ -269,6 +401,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-slab]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-types]] version = "24.0.0" audited_as = "23.0.1" @@ -277,6 +413,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-types]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wasi]] version = "24.0.0" audited_as = "23.0.1" @@ -285,6 +425,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-wasi]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wasi-http]] version = "24.0.0" audited_as = "23.0.1" @@ -293,10 +437,18 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-wasi-http]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wasi-keyvalue]] version = "25.0.0" audited_as = "24.0.0" +[[unpublished.wasmtime-wasi-keyvalue]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wasi-nn]] version = "24.0.0" audited_as = "23.0.1" @@ -305,10 +457,18 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-wasi-nn]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wasi-runtime-config]] version = "25.0.0" audited_as = "24.0.0" +[[unpublished.wasmtime-wasi-runtime-config]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wasi-threads]] version = "24.0.0" audited_as = "23.0.1" @@ -317,6 +477,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-wasi-threads]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wast]] version = "24.0.0" audited_as = "23.0.1" @@ -325,6 +489,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-wast]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-winch]] version = "24.0.0" audited_as = "23.0.1" @@ -333,6 +501,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-winch]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wit-bindgen]] version = "24.0.0" audited_as = "23.0.1" @@ -341,6 +513,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-wit-bindgen]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wasmtime-wmemcheck]] version = "24.0.0" audited_as = "23.0.1" @@ -349,6 +525,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wasmtime-wmemcheck]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wiggle]] version = "24.0.0" audited_as = "23.0.1" @@ -357,6 +537,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wiggle]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wiggle-generate]] version = "24.0.0" audited_as = "23.0.1" @@ -365,6 +549,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wiggle-generate]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wiggle-macro]] version = "24.0.0" audited_as = "23.0.1" @@ -373,6 +561,10 @@ audited_as = "23.0.1" version = "25.0.0" audited_as = "23.0.1" +[[unpublished.wiggle-macro]] +version = "26.0.0" +audited_as = "24.0.0" + [[unpublished.wiggle-test]] version = "0.0.0" audited_as = "0.1.0" @@ -385,6 +577,10 @@ audited_as = "0.21.1" version = "0.23.0" audited_as = "0.21.1" +[[unpublished.winch-codegen]] +version = "0.24.0" +audited_as = "0.22.0" + [[publisher.aho-corasick]] version = "1.0.2" when = "2023-06-04" @@ -566,108 +762,216 @@ when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-bforest]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-bforest]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-bitset]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-bitset]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-codegen]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-codegen]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-codegen-meta]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-codegen-meta]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-codegen-shared]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-codegen-shared]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-control]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-control]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-entity]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-entity]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-frontend]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-frontend]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-interpreter]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-interpreter]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-isle]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-isle]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-jit]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-jit]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-module]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-module]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-native]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-native]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-object]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-object]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-reader]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-reader]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-serde]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-serde]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.cranelift-wasm]] version = "0.110.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.cranelift-wasm]] +version = "0.111.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.derive_arbitrary]] version = "1.3.0" when = "2023-03-13" @@ -857,6 +1161,27 @@ user-id = 3726 user-login = "cfallin" user-name = "Chris Fallin" +[[publisher.regalloc2]] +version = "0.9.4" +when = "2024-08-30" +user-id = 187138 +user-login = "elliottt" +user-name = "Trevor Elliott" + +[[publisher.regalloc2]] +version = "0.10.0" +when = "2024-09-03" +user-id = 187138 +user-login = "elliottt" +user-name = "Trevor Elliott" + +[[publisher.regalloc2]] +version = "0.10.2" +when = "2024-09-11" +user-id = 187138 +user-login = "elliottt" +user-name = "Trevor Elliott" + [[publisher.regex]] version = "1.9.1" when = "2023-07-07" @@ -1072,6 +1397,12 @@ when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasi-common]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasm-bindgen]] version = "0.2.87" when = "2023-06-12" @@ -1125,6 +1456,12 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasm-encoder]] +version = "0.217.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasm-metadata]] version = "0.214.0" when = "2024-07-16" @@ -1143,6 +1480,12 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasm-metadata]] +version = "0.217.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmparser]] version = "0.214.0" when = "2024-07-16" @@ -1161,6 +1504,12 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmparser]] +version = "0.217.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmprinter]] version = "0.214.0" when = "2024-07-16" @@ -1179,108 +1528,216 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmprinter]] +version = "0.217.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-asm-macros]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-asm-macros]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-cache]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-cache]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-cli]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-cli]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-cli-flags]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-cli-flags]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-component-macro]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-component-macro]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-component-util]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-component-util]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-cranelift]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-cranelift]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-environ]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-environ]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-explorer]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-explorer]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-fiber]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-fiber]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-jit-debug]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-jit-debug]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-jit-icache-coherence]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-jit-icache-coherence]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-slab]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-slab]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-types]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-types]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-wasi]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-wasi]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-wasi-http]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-wasi-http]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-wasi-keyvalue]] version = "24.0.0" when = "2024-08-20" @@ -1293,6 +1750,12 @@ when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-wasi-nn]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-wasi-runtime-config]] version = "24.0.0" when = "2024-08-20" @@ -1305,30 +1768,60 @@ when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-wasi-threads]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-wast]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-wast]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-winch]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-winch]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-wit-bindgen]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-wit-bindgen]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wasmtime-wmemcheck]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wasmtime-wmemcheck]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wast]] version = "214.0.0" when = "2024-07-16" @@ -1347,6 +1840,12 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wast]] +version = "217.0.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wat]] version = "1.214.0" when = "2024-07-16" @@ -1365,24 +1864,48 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wat]] +version = "1.217.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wiggle]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wiggle]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wiggle-generate]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wiggle-generate]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wiggle-macro]] version = "23.0.1" when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wiggle-macro]] +version = "24.0.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wiggle-test]] version = "0.1.0" when = "2020-03-12" @@ -1403,6 +1926,12 @@ when = "2024-07-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.winch-codegen]] +version = "0.22.0" +when = "2024-08-20" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.windows]] version = "0.52.0" when = "2023-11-15" @@ -1582,6 +2111,12 @@ when = "2024-08-12" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wit-bindgen]] +version = "0.31.0" +when = "2024-09-09" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wit-bindgen-core]] version = "0.28.0" when = "2024-07-16" @@ -1600,6 +2135,12 @@ when = "2024-08-12" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wit-bindgen-core]] +version = "0.31.0" +when = "2024-09-09" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wit-bindgen-rt]] version = "0.28.0" when = "2024-07-16" @@ -1618,6 +2159,12 @@ when = "2024-08-12" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wit-bindgen-rt]] +version = "0.31.0" +when = "2024-09-09" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wit-bindgen-rust]] version = "0.28.0" when = "2024-07-16" @@ -1636,6 +2183,12 @@ when = "2024-08-12" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wit-bindgen-rust]] +version = "0.31.0" +when = "2024-09-09" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wit-bindgen-rust-macro]] version = "0.28.0" when = "2024-07-16" @@ -1654,6 +2207,12 @@ when = "2024-08-12" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wit-bindgen-rust-macro]] +version = "0.31.0" +when = "2024-09-09" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wit-component]] version = "0.214.0" when = "2024-07-16" @@ -1672,6 +2231,12 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wit-component]] +version = "0.217.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.wit-parser]] version = "0.214.0" when = "2024-07-16" @@ -1690,6 +2255,12 @@ when = "2024-08-22" user-id = 73222 user-login = "wasmtime-publish" +[[publisher.wit-parser]] +version = "0.217.0" +when = "2024-09-10" +user-id = 73222 +user-login = "wasmtime-publish" + [[publisher.witx]] version = "0.9.1" when = "2021-06-22" diff --git a/tests/all/call_hook.rs b/tests/all/call_hook.rs index ef565f6261aa..c4d4bcba463d 100644 --- a/tests/all/call_hook.rs +++ b/tests/all/call_hook.rs @@ -822,23 +822,23 @@ async fn drop_suspended_async_hook() -> Result<(), Error> { } #[derive(Debug, PartialEq, Eq)] -enum Context { +pub enum Context { Host, Wasm, } -struct State { - context: Vec, +pub struct State { + pub context: Vec, - calls_into_host: usize, - returns_from_host: usize, - calls_into_wasm: usize, - returns_from_wasm: usize, + pub calls_into_host: usize, + pub returns_from_host: usize, + pub calls_into_wasm: usize, + pub returns_from_wasm: usize, - trap_next_call_host: bool, - trap_next_return_host: bool, - trap_next_call_wasm: bool, - trap_next_return_wasm: bool, + pub trap_next_call_host: bool, + pub trap_next_return_host: bool, + pub trap_next_call_wasm: bool, + pub trap_next_return_wasm: bool, } impl Default for State { @@ -906,6 +906,6 @@ impl State { } } -fn sync_call_hook(mut ctx: StoreContextMut<'_, State>, transition: CallHook) -> Result<()> { +pub fn sync_call_hook(mut ctx: StoreContextMut<'_, State>, transition: CallHook) -> Result<()> { ctx.data_mut().call_hook(transition) } diff --git a/tests/all/cli_tests.rs b/tests/all/cli_tests.rs index dfb31842a91b..a8743c910785 100644 --- a/tests/all/cli_tests.rs +++ b/tests/all/cli_tests.rs @@ -3,7 +3,7 @@ use anyhow::{bail, Result}; use std::fs::File; use std::io::Write; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{Command, Output, Stdio}; use tempfile::{NamedTempFile, TempDir}; @@ -21,13 +21,10 @@ pub fn run_wasmtime_for_output(args: &[&str], stdin: Option<&Path>) -> Result Result { // Figure out the Wasmtime binary from the current executable. + let bin = get_wasmtime_path()?; let runner = std::env::vars() .filter(|(k, _v)| k.starts_with("CARGO_TARGET") && k.ends_with("RUNNER")) .next(); - let mut me = std::env::current_exe()?; - me.pop(); // chop off the file name - me.pop(); // chop off `deps` - me.push("wasmtime"); // If we're running tests with a "runner" then we might be doing something // like cross-emulation, so spin up the emulator rather than the tests @@ -38,10 +35,10 @@ pub fn get_wasmtime_command() -> Result { for arg in parts { cmd.arg(arg); } - cmd.arg(&me); + cmd.arg(&bin); cmd } else { - Command::new(&me) + Command::new(&bin) }; // Ignore this if it's specified in the environment to allow tests to run in @@ -51,6 +48,14 @@ pub fn get_wasmtime_command() -> Result { Ok(cmd) } +fn get_wasmtime_path() -> Result { + let mut path = std::env::current_exe()?; + path.pop(); // chop off the file name + path.pop(); // chop off `deps` + path.push("wasmtime"); + Ok(path) +} + // Run the wasmtime CLI with the provided args and, if it succeeds, return // the standard output in a `String`. fn run_wasmtime(args: &[&str]) -> Result { @@ -921,7 +926,7 @@ fn table_growth_failure2() -> Result<()> { assert!(!output.status.success()); let stderr = String::from_utf8_lossy(&output.stderr); assert!( - stderr.contains("forcing a table growth failure to be a trap"), + stderr.contains("forcing trap when growing table to 4294967296 elements"), "bad stderr: {stderr}" ); Ok(()) @@ -1947,3 +1952,43 @@ fn settings_command() -> Result<()> { assert!(output.contains("Cranelift settings for target")); Ok(()) } + +#[cfg(target_arch = "x86_64")] +#[test] +fn profile_with_vtune() -> Result<()> { + if !is_vtune_available() { + println!("> `vtune` is not available on the system path; skipping test"); + return Ok(()); + } + + let mut bin = Command::new("vtune"); + bin.args(&[ + // Configure VTune... + "-verbose", + "-collect", + "hotspots", + "-user-data-dir", + &std::env::temp_dir().to_string_lossy(), + // ...then run Wasmtime with profiling enabled: + &get_wasmtime_path()?.to_string_lossy(), + "--profile=vtune", + "tests/all/cli_tests/simple.wat", + ]); + + println!("> executing: {bin:?}"); + let output = bin.output()?; + + assert!(output.status.success()); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + println!("> stdout:\n{stdout}"); + assert!(stdout.contains("CPU Time")); + println!("> stderr:\n{stderr}"); + assert!(!stderr.contains("Error")); + Ok(()) +} + +#[cfg(target_arch = "x86_64")] +fn is_vtune_available() -> bool { + Command::new("vtune").arg("-version").output().is_ok() +} diff --git a/tests/all/component_model.rs b/tests/all/component_model.rs index da4c1abcdf5d..bb6ebc98bc36 100644 --- a/tests/all/component_model.rs +++ b/tests/all/component_model.rs @@ -8,6 +8,7 @@ use wasmtime_component_util::REALLOC_AND_FREE; mod aot; mod r#async; mod bindgen; +mod call_hook; mod dynamic; mod func; mod import; diff --git a/tests/all/component_model/call_hook.rs b/tests/all/component_model/call_hook.rs new file mode 100644 index 000000000000..91f71151aa48 --- /dev/null +++ b/tests/all/component_model/call_hook.rs @@ -0,0 +1,635 @@ +#![cfg(not(miri))] + +use super::REALLOC_AND_FREE; +use crate::call_hook::{sync_call_hook, Context, State}; +use anyhow::{bail, Result}; +use std::future::Future; +use std::pin::Pin; +use std::task::{self, Poll}; +use wasmtime::component::*; +use wasmtime::{CallHook, CallHookHandler, Config, Engine, Store, StoreContextMut}; + +// Crate a synchronous Func, call it directly: +#[test] +fn call_wrapped_func() -> Result<()> { + let wat = r#" + (component + (import "f" (func $f)) + + (core func $f_lower + (canon lower (func $f)) + ) + (core module $m + (import "" "" (func $f)) + + (func $export + (call $f) + ) + + (export "export" (func $export)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "" (func $f_lower)) + )) + )) + (func (export "export") + (canon lift + (core func $i "export") + ) + ) + ) + "#; + + let engine = Engine::default(); + let component = Component::new(&engine, wat)?; + + let mut linker = Linker::::new(&engine); + linker + .root() + .func_wrap("f", |_, _: ()| -> Result<()> { Ok(()) })?; + + let mut store = Store::new(&engine, State::default()); + store.call_hook(sync_call_hook); + let inst = linker + .instantiate(&mut store, &component) + .expect("instantiate"); + + let export = inst + .get_typed_func::<(), ()>(&mut store, "export") + .expect("looking up `export`"); + + export.call(&mut store, ())?; + export.post_return(&mut store)?; + + let s = store.into_data(); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + Ok(()) +} + +// Call a func that turns a `list` into a `string`, to ensure that `realloc` calls are counted. +#[test] +fn call_func_with_realloc() -> Result<()> { + let wat = format!( + r#"(component + (core module $m + (memory (export "memory") 1) + (func (export "roundtrip") (param i32 i32) (result i32) + (local $base i32) + (local.set $base + (call $realloc + (i32.const 0) + (i32.const 0) + (i32.const 4) + (i32.const 8))) + (i32.store offset=0 + (local.get $base) + (local.get 0)) + (i32.store offset=4 + (local.get $base) + (local.get 1)) + (local.get $base) + ) + + {REALLOC_AND_FREE} + ) + (core instance $i (instantiate $m)) + + (func (export "list8-to-str") (param "a" (list u8)) (result string) + (canon lift + (core func $i "roundtrip") + (memory $i "memory") + (realloc (func $i "realloc")) + ) + ) + )"# + ); + + let engine = Engine::default(); + let component = Component::new(&engine, wat)?; + let linker = Linker::::new(&engine); + let mut store = Store::new(&engine, State::default()); + store.call_hook(sync_call_hook); + let inst = linker + .instantiate(&mut store, &component) + .expect("instantiate"); + + let export = inst + .get_typed_func::<(&[u8],), (WasmStr,)>(&mut store, "list8-to-str") + .expect("looking up `list8-to-str`"); + + let message = String::from("hello, world!"); + let res = export.call(&mut store, (message.as_bytes(),))?.0; + let result = res.to_str(&store)?; + assert_eq!(&message, &result); + + export.post_return(&mut store)?; + + // There are two wasm calls for the `list8-to-str` call and the guest realloc call for the list + // argument. + let s = store.into_data(); + assert_eq!(s.calls_into_host, 0); + assert_eq!(s.returns_from_host, 0); + assert_eq!(s.calls_into_wasm, 2); + assert_eq!(s.returns_from_wasm, 2); + + Ok(()) +} + +// Call a guest function that also defines a post-return. +#[test] +fn call_func_with_post_return() -> Result<()> { + let wat = r#" + (component + (core module $m + (func (export "roundtrip")) + (func (export "post-return")) + ) + (core instance $i (instantiate $m)) + + (func (export "export") + (canon lift + (core func $i "roundtrip") + (post-return (func $i "post-return")) + ) + ) + )"#; + + let engine = Engine::default(); + let component = Component::new(&engine, wat)?; + let linker = Linker::::new(&engine); + let mut store = Store::new(&engine, State::default()); + store.call_hook(sync_call_hook); + let inst = linker + .instantiate(&mut store, &component) + .expect("instantiate"); + + let export = inst + .get_typed_func::<(), ()>(&mut store, "export") + .expect("looking up `export`"); + + export.call(&mut store, ())?; + + // Before post-return, there will only have been one call into wasm. + assert_eq!(store.data().calls_into_wasm, 1); + assert_eq!(store.data().returns_from_wasm, 1); + + export.post_return(&mut store)?; + + // There are no host calls in this example, but the post-return does increment the count of + // wasm calls by 1, putting the total number of wasm calls at 2. + let s = store.into_data(); + assert_eq!(s.calls_into_host, 0); + assert_eq!(s.returns_from_host, 0); + assert_eq!(s.calls_into_wasm, 2); + assert_eq!(s.returns_from_wasm, 2); + + Ok(()) +} + +// Create an async Func, call it directly: +#[tokio::test] +async fn call_wrapped_async_func() -> Result<()> { + let wat = r#" + (component + (import "f" (func $f)) + + (core func $f_lower + (canon lower (func $f)) + ) + (core module $m + (import "" "" (func $f)) + + (func $export + (call $f) + ) + + (export "export" (func $export)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "" (func $f_lower)) + )) + )) + (func (export "export") + (canon lift + (core func $i "export") + ) + ) + ) + "#; + + let mut config = Config::new(); + config.async_support(true); + let engine = Engine::new(&config)?; + + let component = Component::new(&engine, wat)?; + + let mut linker = Linker::::new(&engine); + linker + .root() + .func_wrap_async("f", |_, _: ()| Box::new(async { Ok(()) }))?; + + let mut store = Store::new(&engine, State::default()); + store.call_hook(sync_call_hook); + + let inst = linker + .instantiate_async(&mut store, &component) + .await + .expect("instantiate"); + + let export = inst + .get_typed_func::<(), ()>(&mut store, "export") + .expect("looking up `export`"); + + export.call_async(&mut store, ()).await?; + export.post_return_async(&mut store).await?; + + let s = store.into_data(); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + Ok(()) +} + +#[test] +fn trapping() -> Result<()> { + const TRAP_IN_F: i32 = 0; + const TRAP_NEXT_CALL_HOST: i32 = 1; + const TRAP_NEXT_RETURN_HOST: i32 = 2; + const TRAP_NEXT_CALL_WASM: i32 = 3; + const TRAP_NEXT_RETURN_WASM: i32 = 4; + const DO_NOTHING: i32 = 5; + + let engine = Engine::default(); + + let mut linker = Linker::::new(&engine); + + linker + .root() + .func_wrap("f", |mut store: _, (action,): (i32,)| -> Result<()> { + assert_eq!(store.data().context.last(), Some(&Context::Host)); + assert_eq!(store.data().calls_into_host, store.data().calls_into_wasm); + + match action { + TRAP_IN_F => bail!("trapping in f"), + TRAP_NEXT_CALL_HOST => store.data_mut().trap_next_call_host = true, + TRAP_NEXT_RETURN_HOST => store.data_mut().trap_next_return_host = true, + TRAP_NEXT_CALL_WASM => store.data_mut().trap_next_call_wasm = true, + TRAP_NEXT_RETURN_WASM => store.data_mut().trap_next_return_wasm = true, + _ => {} // Do nothing + } + + Ok(()) + })?; + + let wat = r#" + (component + (import "f" (func $f (param "action" s32))) + + (core func $f_lower + (canon lower (func $f)) + ) + (core module $m + (import "" "" (func $f (param i32))) + + (func $export (param i32) + (call $f (local.get 0)) + ) + + (export "export" (func $export)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "" (func $f_lower)) + )) + )) + (func (export "export") (param "action" s32) + (canon lift + (core func $i "export") + ) + ) + ) + "#; + + let component = Component::new(&engine, wat)?; + + let run = |action: i32, again: bool| -> (State, Option) { + let mut store = Store::new(&engine, State::default()); + store.call_hook(sync_call_hook); + let inst = linker + .instantiate(&mut store, &component) + .expect("instantiate"); + + let export = inst + .get_typed_func::<(i32,), ()>(&mut store, "export") + .expect("looking up `export`"); + + let mut r = export.call(&mut store, (action,)); + if r.is_ok() && again { + export.post_return(&mut store).unwrap(); + r = export.call(&mut store, (action,)); + } + (store.into_data(), r.err()) + }; + + let (s, e) = run(DO_NOTHING, false); + assert!(e.is_none()); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + let (s, e) = run(DO_NOTHING, true); + assert!(e.is_none()); + assert_eq!(s.calls_into_host, 2); + assert_eq!(s.returns_from_host, 2); + assert_eq!(s.calls_into_wasm, 2); + assert_eq!(s.returns_from_wasm, 2); + + let (s, e) = run(TRAP_IN_F, false); + assert!(format!("{:?}", e.unwrap()).contains("trapping in f")); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + // // trap in next call to host. No calls after the bit is set, so this trap shouldn't happen + let (s, e) = run(TRAP_NEXT_CALL_HOST, false); + assert!(e.is_none()); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + // trap in next call to host. call again, so the second call into host traps: + let (s, e) = run(TRAP_NEXT_CALL_HOST, true); + println!("{:?}", e.as_ref().unwrap()); + assert!(format!("{:?}", e.unwrap()).contains("call_hook: trapping on CallingHost")); + assert_eq!(s.calls_into_host, 2); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 2); + assert_eq!(s.returns_from_wasm, 2); + + // trap in the return from host. should trap right away, without a second call + let (s, e) = run(TRAP_NEXT_RETURN_HOST, false); + assert!(format!("{:?}", e.unwrap()).contains("call_hook: trapping on ReturningFromHost")); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + // trap in next call to wasm. No calls after the bit is set, so this trap shouldn't happen: + let (s, e) = run(TRAP_NEXT_CALL_WASM, false); + assert!(e.is_none()); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + // trap in next call to wasm. call again, so the second call into wasm traps: + let (s, e) = run(TRAP_NEXT_CALL_WASM, true); + assert!(format!("{:?}", e.unwrap()).contains("call_hook: trapping on CallingWasm")); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 2); + assert_eq!(s.returns_from_wasm, 1); + + // trap in the return from wasm. should trap right away, without a second call + let (s, e) = run(TRAP_NEXT_RETURN_WASM, false); + assert!(format!("{:?}", e.unwrap()).contains("call_hook: trapping on ReturningFromWasm")); + assert_eq!(s.calls_into_host, 1); + assert_eq!(s.returns_from_host, 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 1); + + Ok(()) +} + +#[tokio::test] +async fn timeout_async_hook() -> Result<()> { + struct HandlerR; + + #[async_trait::async_trait] + impl CallHookHandler for HandlerR { + async fn handle_call_event( + &self, + mut ctx: StoreContextMut<'_, State>, + ch: CallHook, + ) -> Result<()> { + let obj = ctx.data_mut(); + if obj.calls_into_host > 200 { + bail!("timeout"); + } + + match ch { + CallHook::CallingHost => obj.calls_into_host += 1, + CallHook::CallingWasm => obj.calls_into_wasm += 1, + CallHook::ReturningFromHost => obj.returns_from_host += 1, + CallHook::ReturningFromWasm => obj.returns_from_wasm += 1, + } + + Ok(()) + } + } + + let wat = r#" + (component + (import "f" (func $f)) + + (core func $f_lower + (canon lower (func $f)) + ) + (core module $m + (import "" "" (func $f)) + + (func $export + (loop $start + (call $f) + (br $start)) + ) + + (export "export" (func $export)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "" (func $f_lower)) + )) + )) + (func (export "export") + (canon lift + (core func $i "export") + ) + ) + ) + "#; + + let mut config = Config::new(); + config.async_support(true); + let engine = Engine::new(&config)?; + + let component = Component::new(&engine, wat)?; + + let mut linker = Linker::::new(&engine); + linker + .root() + .func_wrap_async("f", |_, _: ()| Box::new(async { Ok(()) }))?; + + let mut store = Store::new(&engine, State::default()); + store.call_hook_async(HandlerR {}); + + let inst = linker + .instantiate_async(&mut store, &component) + .await + .expect("instantiate"); + + let export = inst + .get_typed_func::<(), ()>(&mut store, "export") + .expect("looking up `export`"); + + let r = export.call_async(&mut store, ()).await; + assert!(format!("{:?}", r.unwrap_err()).contains("timeout")); + + let s = store.into_data(); + assert!(s.calls_into_host > 1); + assert!(s.returns_from_host > 1); + assert_eq!(s.calls_into_wasm, 1); + assert_eq!(s.returns_from_wasm, 0); + + Ok(()) +} + +#[tokio::test] +async fn drop_suspended_async_hook() -> Result<()> { + struct Handler; + + #[async_trait::async_trait] + impl CallHookHandler for Handler { + async fn handle_call_event( + &self, + mut ctx: StoreContextMut<'_, u32>, + _ch: CallHook, + ) -> Result<()> { + let state = ctx.data_mut(); + assert_eq!(*state, 0); + *state += 1; + let _dec = Decrement(state); + + // Simulate some sort of event which takes a number of yields + for _ in 0..500 { + tokio::task::yield_now().await; + } + Ok(()) + } + } + + let wat = r#" + (component + (import "f" (func $f)) + + (core func $f_lower + (canon lower (func $f)) + ) + (core module $m + (import "" "" (func $f)) + + (func $export + (call $f) + ) + + (export "export" (func $export)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "" (func $f_lower)) + )) + )) + (func (export "export") + (canon lift + (core func $i "export") + ) + ) + ) + "#; + + let mut config = Config::new(); + config.async_support(true); + let engine = Engine::new(&config)?; + + let component = Component::new(&engine, wat)?; + + let mut linker = Linker::::new(&engine); + linker.root().func_wrap_async("f", |mut store, _: ()| { + Box::new(async move { + let state = store.data_mut(); + assert_eq!(*state, 0); + *state += 1; + let _dec = Decrement(state); + for _ in 0.. { + tokio::task::yield_now().await; + } + Ok(()) + }) + })?; + + let mut store = Store::new(&engine, 0); + store.call_hook_async(Handler); + + let inst = linker + .instantiate_async(&mut store, &component) + .await + .expect("instantiate"); + + let export = inst + .get_typed_func::<(), ()>(&mut store, "export") + .expect("looking up `export`"); + + // Test that if we drop in the middle of an async hook that everything + // is alright. + PollNTimes { + future: Box::pin(export.call_async(&mut store, ())), + times: 200, + } + .await; + assert_eq!(*store.data(), 0); // double-check user dtors ran + + return Ok(()); + + // A helper struct to poll an inner `future` N `times` and then resolve. + // This is used above to test that when futures are dropped while they're + // pending everything works and is cleaned up on the Wasmtime side of + // things. + struct PollNTimes { + future: F, + times: u32, + } + + impl Future for PollNTimes { + type Output = (); + fn poll(mut self: Pin<&mut Self>, task: &mut task::Context<'_>) -> Poll<()> { + for i in 0..self.times { + match Pin::new(&mut self.future).poll(task) { + Poll::Ready(_) => panic!("future should not be ready at {i}"), + Poll::Pending => {} + } + } + + Poll::Ready(()) + } + } + + // helper struct to decrement a counter on drop + struct Decrement<'a>(&'a mut u32); + + impl Drop for Decrement<'_> { + fn drop(&mut self) { + *self.0 -= 1; + } + } +} diff --git a/tests/all/externals.rs b/tests/all/externals.rs index 1b36359c1e5b..43365457e0b2 100644 --- a/tests/all/externals.rs +++ b/tests/all/externals.rs @@ -29,7 +29,8 @@ fn bad_tables() { let ty = TableType::new(RefType::FUNCREF, 0, Some(1)); let t = Table::new(&mut store, ty.clone(), Ref::Func(None)).unwrap(); assert!(t.get(&mut store, 0).is_none()); - assert!(t.get(&mut store, u32::max_value()).is_none()); + assert!(t.get(&mut store, u64::from(u32::MAX)).is_none()); + assert!(t.get(&mut store, u64::MAX).is_none()); // set out of bounds or wrong type let ty = TableType::new(RefType::FUNCREF, 1, Some(1)); diff --git a/tests/all/limits.rs b/tests/all/limits.rs index 9150ce20de78..684d76de35dc 100644 --- a/tests/all/limits.rs +++ b/tests/all/limits.rs @@ -103,7 +103,7 @@ async fn test_limits_async() -> Result<()> { struct LimitsAsync { memory_size: usize, - table_elements: u32, + table_elements: usize, } #[async_trait::async_trait] impl ResourceLimiterAsync for LimitsAsync { @@ -117,9 +117,9 @@ async fn test_limits_async() -> Result<()> { } async fn table_growing( &mut self, - _current: u32, - desired: u32, - _maximum: Option, + _current: usize, + desired: usize, + _maximum: Option, ) -> Result { Ok(desired <= self.table_elements) } @@ -419,9 +419,9 @@ impl ResourceLimiter for MemoryContext { } fn table_growing( &mut self, - _current: u32, - _desired: u32, - _maximum: Option, + _current: usize, + _desired: usize, + _maximum: Option, ) -> Result { Ok(true) } @@ -533,9 +533,9 @@ impl ResourceLimiterAsync for MemoryContext { } async fn table_growing( &mut self, - _current: u32, - _desired: u32, - _maximum: Option, + _current: usize, + _desired: usize, + _maximum: Option, ) -> Result { Ok(true) } @@ -626,8 +626,8 @@ async fn test_custom_memory_limiter_async() -> Result<()> { } struct TableContext { - elements_used: u32, - element_limit: u32, + elements_used: usize, + element_limit: usize, limit_exceeded: bool, } @@ -640,9 +640,14 @@ impl ResourceLimiter for TableContext { ) -> Result { Ok(true) } - fn table_growing(&mut self, current: u32, desired: u32, maximum: Option) -> Result { + fn table_growing( + &mut self, + current: usize, + desired: usize, + maximum: Option, + ) -> Result { // Check if the desired exceeds a maximum (either from Wasm or from the host) - assert!(desired < maximum.unwrap_or(u32::MAX)); + assert!(desired < maximum.unwrap_or(usize::MAX)); assert_eq!(current, self.elements_used); Ok(if desired > self.element_limit { self.limit_exceeded = true; @@ -704,8 +709,8 @@ struct FailureDetector { /// Display impl of most recent call to memory_grow_failed memory_error: Option, /// Arguments of most recent call to table_growing - table_current: u32, - table_desired: u32, + table_current: usize, + table_desired: usize, /// Display impl of most recent call to table_grow_failed table_error: Option, } @@ -725,7 +730,12 @@ impl ResourceLimiter for FailureDetector { self.memory_error = Some(err.to_string()); Ok(()) } - fn table_growing(&mut self, current: u32, desired: u32, _maximum: Option) -> Result { + fn table_growing( + &mut self, + current: usize, + desired: usize, + _maximum: Option, + ) -> Result { self.table_current = current; self.table_desired = desired; Ok(true) @@ -832,9 +842,9 @@ impl ResourceLimiterAsync for FailureDetector { async fn table_growing( &mut self, - current: u32, - desired: u32, - _maximum: Option, + current: usize, + desired: usize, + _maximum: Option, ) -> Result { self.table_current = current; self.table_desired = desired; @@ -941,9 +951,9 @@ impl ResourceLimiter for Panic { } fn table_growing( &mut self, - _current: u32, - _desired: u32, - _maximum: Option, + _current: usize, + _desired: usize, + _maximum: Option, ) -> Result { panic!("resource limiter table growing"); } @@ -960,9 +970,9 @@ impl ResourceLimiterAsync for Panic { } async fn table_growing( &mut self, - _current: u32, - _desired: u32, - _maximum: Option, + _current: usize, + _desired: usize, + _maximum: Option, ) -> Result { panic!("async resource limiter table growing"); } diff --git a/tests/all/memory.rs b/tests/all/memory.rs index 24746f204faf..91865bfdb5b2 100644 --- a/tests/all/memory.rs +++ b/tests/all/memory.rs @@ -375,9 +375,9 @@ fn massive_64_bit_still_limited() -> Result<()> { } fn table_growing( &mut self, - _current: u32, - _request: u32, - _max: Option, + _current: usize, + _request: usize, + _max: Option, ) -> Result { unreachable!() } diff --git a/tests/all/pooling_allocator.rs b/tests/all/pooling_allocator.rs index 0d37fd784cca..1e5b30175095 100644 --- a/tests/all/pooling_allocator.rs +++ b/tests/all/pooling_allocator.rs @@ -234,7 +234,7 @@ fn memory_zeroed() -> Result<()> { #[test] #[cfg_attr(miri, ignore)] fn table_limit() -> Result<()> { - const TABLE_ELEMENTS: u32 = 10; + const TABLE_ELEMENTS: usize = 10; let mut pool = crate::small_pool_config(); pool.table_elements(TABLE_ELEMENTS); let mut config = Config::new(); @@ -299,16 +299,16 @@ fn table_limit() -> Result<()> { let table = instance.get_table(&mut store, "t").unwrap(); for i in 0..TABLE_ELEMENTS { - assert_eq!(table.size(&store), i); + assert_eq!(table.size(&store), i as u64); assert_eq!( table .grow(&mut store, 1, Ref::Func(None)) .expect("table should grow"), - i + i as u64 ); } - assert_eq!(table.size(&store), TABLE_ELEMENTS); + assert_eq!(table.size(&store), TABLE_ELEMENTS as u64); assert!(table.grow(&mut store, 1, Ref::Func(None)).is_err()); Ok(()) @@ -527,7 +527,7 @@ fn drop_externref_global_during_module_init() -> Result<()> { Ok(false) } - fn table_growing(&mut self, _: u32, _: u32, _: Option) -> Result { + fn table_growing(&mut self, _: usize, _: usize, _: Option) -> Result { Ok(false) } } diff --git a/tests/all/typed_continuations.rs b/tests/all/typed_continuations.rs index c20e92179413..38baef4ec239 100644 --- a/tests/all/typed_continuations.rs +++ b/tests/all/typed_continuations.rs @@ -123,7 +123,7 @@ mod test_utils { } pub fn make_panicking_host_func(store: &mut Store<()>, msg: &'static str) -> Func { - Func::wrap(store, move || std::panic::panic_any(msg)) + Func::wrap(store, move || -> () { std::panic::panic_any(msg) }) } } @@ -347,7 +347,11 @@ fn inter_instance_suspend() -> Result<()> { let entry_func = main_instance.get_func(&mut store, "entry").unwrap(); let result = entry_func.call(&mut store, &[], &mut []); - assert!(result.is_err()); + if cfg!(feature = "wasmfx_baseline") { + assert!(result.is_ok()); // NOTE(dhil): Tag linking is broken on the baseline implementation. + } else { + assert!(result.is_err()); + } Ok(()) } diff --git a/tests/disable_host_trap_handlers.rs b/tests/disable_host_trap_handlers.rs new file mode 100644 index 000000000000..da2830d80a2c --- /dev/null +++ b/tests/disable_host_trap_handlers.rs @@ -0,0 +1,92 @@ +//! A standalone test to assert that Wasmtime can operate in "no signal handlers +//! mode" +//! +//! This is a test for `Config::signals_based_traps(false)` which resides in its +//! own binary to assert properties about signal handlers that Wasmtime uses. +//! Due to the global nature of signals no other tests can be in this binary. +//! This will ensure that various trapping scenarios all work and additionally +//! signal handlers are not registered. + +use anyhow::Result; +use wasmtime::{Config, Engine, Instance, Module, Store, Trap}; + +#[test] +#[cfg_attr(miri, ignore)] +fn no_host_trap_handlers() -> Result<()> { + let mut config = Config::new(); + config.signals_based_traps(false); + let engine = Engine::new(&config)?; + let module = Module::new( + &engine, + r#" + (module + (memory 1) + + (func (export "load") (param i32) (result i32) + (i32.load (local.get 0))) + + (func (export "div") (param i32 i32) (result i32) + (i32.div_s (local.get 0) (local.get 1))) + + (func (export "unreachable") unreachable) + (func $oflow (export "overflow") call $oflow) + ) + "#, + )?; + + let mut store = Store::new(&engine, ()); + let instance = Instance::new(&mut store, &module, &[])?; + let load = instance.get_typed_func::(&mut store, "load")?; + let div = instance.get_typed_func::<(i32, i32), i32>(&mut store, "div")?; + let unreachable = instance.get_typed_func::<(), ()>(&mut store, "unreachable")?; + let overflow = instance.get_typed_func::<(), ()>(&mut store, "overflow")?; + + let trap = load + .call(&mut store, 1 << 20) + .unwrap_err() + .downcast::()?; + assert_eq!(trap, Trap::MemoryOutOfBounds); + + let trap = div + .call(&mut store, (1, 0)) + .unwrap_err() + .downcast::()?; + assert_eq!(trap, Trap::IntegerDivisionByZero); + + let trap = unreachable + .call(&mut store, ()) + .unwrap_err() + .downcast::()?; + assert_eq!(trap, Trap::UnreachableCodeReached); + + let trap = overflow + .call(&mut store, ()) + .unwrap_err() + .downcast::()?; + assert_eq!(trap, Trap::StackOverflow); + + assert_host_signal_handlers_are_unset(); + + Ok(()) +} + +fn assert_host_signal_handlers_are_unset() { + #[cfg(unix)] + unsafe { + let mut prev = std::mem::zeroed::(); + let rc = libc::sigaction(libc::SIGILL, std::ptr::null(), &mut prev); + assert_eq!(rc, 0); + assert_eq!( + prev.sa_sigaction, + libc::SIG_DFL, + "fault handler was installed when it shouldn't have been" + ); + } + #[cfg(windows)] + { + // Note that this can't be checked on Windows because vectored exception + // handlers work a bit differently and aren't as "global" as a signal + // handler. For now rely on the check above on unix to also guarantee + // that on Windows we don't register any vectored exception handlers. + } +} diff --git a/tests/disas.rs b/tests/disas.rs index 1a07e8d698e5..70f4acbe79f7 100644 --- a/tests/disas.rs +++ b/tests/disas.rs @@ -45,6 +45,7 @@ use cranelift_codegen::ir::{Function, UserExternalName, UserFuncName}; use cranelift_codegen::isa::{lookup_by_name, TargetIsa}; use cranelift_codegen::settings::{Configurable, Flags, SetError}; use libtest_mimic::{Arguments, Trial}; +use pulley_interpreter::decode::OpVisitor; use serde::de::DeserializeOwned; use serde_derive::Deserialize; use similar::TextDiff; @@ -60,6 +61,8 @@ fn main() -> Result<()> { return Ok(()); } + let _ = env_logger::try_init(); + let mut tests = Vec::new(); find_tests("./tests/disas".as_ref(), &mut tests)?; @@ -311,17 +314,130 @@ fn assert_output( } } } - CompileOutput::Elf(bytes) => { - let disas = isa.to_capstone()?; - disas_elf(&disas, &mut actual, &bytes)?; - } + CompileOutput::Elf(bytes) => match isa.to_capstone() { + Ok(disas) => disas_insts(&mut actual, &bytes, |bytes, addr| { + Ok(disas + .disasm_all(bytes, addr)? + .into_iter() + .map(|inst| { + use capstone::InsnGroupType::{CS_GRP_JUMP, CS_GRP_RET}; + + let detail = disas.insn_detail(&inst).ok(); + let detail = detail.as_ref(); + let is_jump = detail + .map(|d| { + d.groups() + .iter() + .find(|g| g.0 as u32 == CS_GRP_JUMP) + .is_some() + }) + .unwrap_or(false); + + let is_return = detail + .map(|d| { + d.groups() + .iter() + .find(|g| g.0 as u32 == CS_GRP_RET) + .is_some() + }) + .unwrap_or(false); + + let disassembly = match (inst.mnemonic(), inst.op_str()) { + (Some(i), Some(o)) => { + if o.is_empty() { + format!("{i}") + } else { + format!("{i:7} {o}") + } + } + (Some(i), None) => format!("{i}"), + _ => unreachable!(), + }; + + let address = inst.address(); + DisasInst { + address, + is_jump, + is_return, + disassembly, + } + }) + .collect::>()) + })?, + Err(_) => { + assert!(matches!( + isa.triple().architecture, + target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 + )); + disas_insts(&mut actual, &bytes, |bytes, _addr| { + let mut result = vec![]; + + let mut disas = pulley_interpreter::disas::Disassembler::new(bytes); + disas.offsets(false); + disas.hexdump(false); + let mut decoder = pulley_interpreter::decode::Decoder::new(); + + loop { + let addr = disas.bytecode().position(); + + match decoder.decode_one(&mut disas) { + // If we got EOF at the initial position, then we're done disassembling. + Err(pulley_interpreter::decode::DecodingError::UnexpectedEof { + position, + }) if position == addr => break, + + // Otherwise, propagate the error. + Err(e) => { + return Err(anyhow::Error::from(e)) + .context("failed to disassembly pulley bytecode"); + } + + Ok(()) => { + let disassembly = disas + .disas() + .lines() + .map(|l| l.trim().to_string()) + .filter(|l| !l.is_empty()) + .next_back() + .unwrap(); + let address = u64::try_from(addr).unwrap(); + let is_jump = + disassembly.contains("jump") || disassembly.contains("br_if"); + let is_return = disassembly == "ret"; + result.push(DisasInst { + address, + is_jump, + is_return, + disassembly, + }); + } + } + } + + Ok(result) + })? + } + }, } let actual = actual.trim(); assert_or_bless_output(path, wat, actual) } -fn disas_elf(disas: &capstone::Capstone, result: &mut String, elf: &[u8]) -> Result<()> { - use capstone::InsnGroupType::{CS_GRP_JUMP, CS_GRP_RET}; +struct DisasInst { + address: u64, + is_jump: bool, + is_return: bool, + disassembly: String, +} + +fn disas_insts( + result: &mut String, + elf: &[u8], + disas: impl Fn(&[u8], u64) -> Result, +) -> Result<()> +where + I: IntoIterator, +{ use object::{Endianness, Object, ObjectSection, ObjectSymbol}; let elf = object::read::elf::ElfFile64::::parse(elf)?; @@ -354,50 +470,27 @@ fn disas_elf(disas: &capstone::Capstone, result: &mut String, elf: &[u8]) -> Res let mut prev_jump = false; let mut write_offsets = false; - for inst in disas.disasm_all(bytes, sym.address())?.iter() { - let detail = disas.insn_detail(&inst).ok(); - let detail = detail.as_ref(); - let is_jump = detail - .map(|d| { - d.groups() - .iter() - .find(|g| g.0 as u32 == CS_GRP_JUMP) - .is_some() - }) - .unwrap_or(false); - + for DisasInst { + address, + is_jump, + is_return, + disassembly: disas, + } in disas(bytes, sym.address())?.into_iter() + { if write_offsets || (prev_jump && !is_jump) { - write!(result, "{:>4x}: ", inst.address())?; + write!(result, "{address:>4x}: ")?; } else { write!(result, " ")?; } - match (inst.mnemonic(), inst.op_str()) { - (Some(i), Some(o)) => { - if o.is_empty() { - writeln!(result, "{i}")?; - } else { - writeln!(result, "{i:7} {o}")?; - } - } - (Some(i), None) => writeln!(result, "{i}")?, - _ => unreachable!(), - } + writeln!(result, "{disas}")?; prev_jump = is_jump; // Flip write_offsets to true once we've seen a `ret`, as // instructions that follow the return are often related to trap // tables. - write_offsets = write_offsets - || detail - .map(|d| { - d.groups() - .iter() - .find(|g| g.0 as u32 == CS_GRP_RET) - .is_some() - }) - .unwrap_or(false); + write_offsets |= is_return; } } Ok(()) diff --git a/tests/disas/gc/externref-globals.wat b/tests/disas/gc/externref-globals.wat new file mode 100644 index 000000000000..95ce3ce51a58 --- /dev/null +++ b/tests/disas/gc/externref-globals.wat @@ -0,0 +1,186 @@ +;;! target = "x86_64" +;;! flags = "-W function-references,gc" +;;! test = "optimize" + +(module + (global $x (mut externref) (ref.null extern)) + (func (export "get") (result externref) + (global.get $x) + ) + (func (export "set") (param externref) + (global.set $x (local.get 0)) + ) +) + +;; function u0:0(i64 vmctx, i64) -> i32 tail { +;; ss0 = explicit_slot 4, align = 4 +;; gv0 = vmctx +;; gv1 = load.i64 notrap aligned readonly gv0+8 +;; gv2 = load.i64 notrap aligned gv1 +;; gv3 = vmctx +;; sig0 = (i64 vmctx, i32) -> i32 system_v +;; fn0 = colocated u1:26 sig0 +;; stack_limit = gv2 +;; +;; block0(v0: i64, v1: i64): +;; v43 = iconst.i64 96 +;; @0034 v4 = iadd v0, v43 ; v43 = 96 +;; @0034 v5 = load.i32 notrap aligned v4 +;; v44 = stack_addr.i64 ss0 +;; store notrap v5, v44 +;; v46 = iconst.i32 0 +;; @0034 v6 = icmp eq v5, v46 ; v46 = 0 +;; @0034 brif v6, block5, block2 +;; +;; block2: +;; @0034 v8 = load.i64 notrap aligned v0+56 +;; @0034 v9 = load.i64 notrap aligned v8 +;; @0034 v10 = load.i64 notrap aligned v8+8 +;; @0034 v11 = icmp eq v9, v10 +;; @0034 brif v11, block3, block4 +;; +;; block4: +;; @0034 v15 = uextend.i64 v5 +;; @0034 v16 = iconst.i64 8 +;; @0034 v17 = uadd_overflow_trap v15, v16, user65535 ; v16 = 8 +;; @0034 v19 = uadd_overflow_trap v17, v16, user65535 ; v16 = 8 +;; @0034 v14 = load.i64 notrap aligned readonly v0+48 +;; @0034 v20 = icmp ult v19, v14 +;; @0034 brif v20, block7, block6 +;; +;; block6 cold: +;; @0034 trap user65535 +;; +;; block7: +;; @0034 v13 = load.i64 notrap aligned readonly v0+40 +;; @0034 v21 = iadd v13, v17 +;; @0034 v22 = load.i64 notrap aligned v21 +;; v40 = load.i32 notrap v44 +;; @0034 v27 = uextend.i64 v40 +;; v54 = iconst.i64 8 +;; @0034 v29 = uadd_overflow_trap v27, v54, user65535 ; v54 = 8 +;; @0034 v31 = uadd_overflow_trap v29, v54, user65535 ; v54 = 8 +;; @0034 v32 = icmp ult v31, v14 +;; @0034 brif v32, block9, block8 +;; +;; block8 cold: +;; @0034 trap user65535 +;; +;; block9: +;; v48 = iconst.i64 1 +;; @0034 v23 = iadd.i64 v22, v48 ; v48 = 1 +;; @0034 v33 = iadd.i64 v13, v29 +;; @0034 store notrap aligned v23, v33 +;; v39 = load.i32 notrap v44 +;; @0034 store notrap aligned v39, v9 +;; v51 = iconst.i64 4 +;; @0034 v34 = iadd.i64 v9, v51 ; v51 = 4 +;; @0034 store notrap aligned v34, v8 +;; @0034 jump block5 +;; +;; block3 cold: +;; @0034 v36 = call fn0(v0, v5), stack_map=[i32 @ ss0+0] +;; @0034 jump block5 +;; +;; block5: +;; v37 = load.i32 notrap v44 +;; @0036 jump block1 +;; +;; block1: +;; @0036 return v37 +;; } +;; +;; function u0:1(i64 vmctx, i64, i32) tail { +;; gv0 = vmctx +;; gv1 = load.i64 notrap aligned readonly gv0+8 +;; gv2 = load.i64 notrap aligned gv1 +;; gv3 = vmctx +;; sig0 = (i64 vmctx, i32 uext) system_v +;; fn0 = colocated u1:25 sig0 +;; stack_limit = gv2 +;; +;; block0(v0: i64, v1: i64, v2: i32): +;; v54 = iconst.i64 96 +;; @003b v4 = iadd v0, v54 ; v54 = 96 +;; @003b v5 = load.i32 notrap aligned v4 +;; v55 = iconst.i32 0 +;; @003b v6 = icmp eq v2, v55 ; v55 = 0 +;; @003b brif v6, block3, block2 +;; +;; block2: +;; @003b v10 = uextend.i64 v2 +;; @003b v34 = iconst.i64 8 +;; @003b v12 = uadd_overflow_trap v10, v34, user65535 ; v34 = 8 +;; @003b v14 = uadd_overflow_trap v12, v34, user65535 ; v34 = 8 +;; @003b v32 = load.i64 notrap aligned readonly v0+48 +;; @003b v15 = icmp ult v14, v32 +;; @003b brif v15, block9, block8 +;; +;; block8 cold: +;; @003b trap user65535 +;; +;; block9: +;; @003b v31 = load.i64 notrap aligned readonly v0+40 +;; @003b v16 = iadd v31, v12 +;; @003b v17 = load.i64 notrap aligned v16 +;; @003b brif.i8 v15, block11, block10 +;; +;; block10 cold: +;; @003b trap user65535 +;; +;; block11: +;; v56 = iconst.i64 1 +;; @003b v18 = iadd.i64 v17, v56 ; v56 = 1 +;; @003b store notrap aligned v18, v16 +;; @003b jump block3 +;; +;; block3: +;; v60 = iadd.i64 v0, v54 ; v54 = 96 +;; @003b store.i32 notrap aligned v2, v60 +;; v61 = iconst.i32 0 +;; v62 = icmp.i32 eq v5, v61 ; v61 = 0 +;; @003b brif v62, block7, block4 +;; +;; block4: +;; @003b v33 = uextend.i64 v5 +;; v63 = iconst.i64 8 +;; @003b v35 = uadd_overflow_trap v33, v63, user65535 ; v63 = 8 +;; @003b v37 = uadd_overflow_trap v35, v63, user65535 ; v63 = 8 +;; v64 = load.i64 notrap aligned readonly v0+48 +;; @003b v38 = icmp ult v37, v64 +;; @003b brif v38, block13, block12 +;; +;; block12 cold: +;; @003b trap user65535 +;; +;; block13: +;; v65 = load.i64 notrap aligned readonly v0+40 +;; @003b v39 = iadd v65, v35 +;; @003b v40 = load.i64 notrap aligned v39 +;; v58 = iconst.i64 -1 +;; @003b v41 = iadd v40, v58 ; v58 = -1 +;; v59 = iconst.i64 0 +;; @003b v42 = icmp eq v41, v59 ; v59 = 0 +;; @003b brif v42, block5, block6 +;; +;; block5 cold: +;; @003b call fn0(v0, v5) +;; @003b jump block7 +;; +;; block6: +;; @003b brif.i8 v38, block15, block14 +;; +;; block14 cold: +;; @003b trap user65535 +;; +;; block15: +;; v66 = iadd.i64 v40, v58 ; v58 = -1 +;; @003b store notrap aligned v66, v39 +;; @003b jump block7 +;; +;; block7: +;; @003d jump block1 +;; +;; block1: +;; @003d return +;; } diff --git a/tests/disas/gc/i31ref-globals.wat b/tests/disas/gc/i31ref-globals.wat new file mode 100644 index 000000000000..b172c6f35dfb --- /dev/null +++ b/tests/disas/gc/i31ref-globals.wat @@ -0,0 +1,47 @@ +;;! target = "x86_64" +;;! flags = "-W function-references,gc" +;;! test = "optimize" + +(module + (global $x (mut i31ref) (ref.i31 (i32.const 42))) + (func (export "get") (result i31ref) + (global.get $x) + ) + (func (export "set") (param i31ref) + (global.set $x (local.get 0)) + ) +) + +;; function u0:0(i64 vmctx, i64) -> i32 tail { +;; gv0 = vmctx +;; gv1 = load.i64 notrap aligned readonly gv0+8 +;; gv2 = load.i64 notrap aligned gv1 +;; gv3 = vmctx +;; stack_limit = gv2 +;; +;; block0(v0: i64, v1: i64): +;; v6 = iconst.i64 96 +;; @0036 v4 = iadd v0, v6 ; v6 = 96 +;; @0036 v5 = load.i32 notrap aligned v4 +;; @0038 jump block1 +;; +;; block1: +;; @0038 return v5 +;; } +;; +;; function u0:1(i64 vmctx, i64, i32) tail { +;; gv0 = vmctx +;; gv1 = load.i64 notrap aligned readonly gv0+8 +;; gv2 = load.i64 notrap aligned gv1 +;; gv3 = vmctx +;; stack_limit = gv2 +;; +;; block0(v0: i64, v1: i64, v2: i32): +;; v5 = iconst.i64 96 +;; @003d v4 = iadd v0, v5 ; v5 = 96 +;; @003d store notrap aligned v2, v4 +;; @003f jump block1 +;; +;; block1: +;; @003f return +;; } diff --git a/tests/disas/icall-loop.wat b/tests/disas/icall-loop.wat index 80d55efdb302..38689687810d 100644 --- a/tests/disas/icall-loop.wat +++ b/tests/disas/icall-loop.wat @@ -29,7 +29,7 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 ;; sig0 = (i64 vmctx, i64) -> i32 tail -;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig1 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; fn0 = colocated u1:9 sig1 ;; stack_limit = gv2 ;; @@ -39,39 +39,39 @@ ;; @002b v10 = iconst.i64 0 ;; @002b v7 = load.i64 notrap aligned readonly v0+88 ;; @002b v6 = uextend.i64 v2 -;; v28 = iconst.i64 3 -;; @002b v8 = ishl v6, v28 ; v28 = 3 +;; v29 = iconst.i64 3 +;; @002b v8 = ishl v6, v29 ; v29 = 3 ;; @002b v9 = iadd v7, v8 ;; @002b v11 = select_spectre_guard v5, v10, v9 ; v10 = 0 -;; v29 = iconst.i64 -2 +;; v30 = iconst.i64 -2 ;; @002b v15 = iconst.i32 0 -;; @002b v19 = load.i64 notrap aligned readonly v0+80 -;; @002b v20 = load.i32 notrap aligned readonly v19 +;; @002b v20 = load.i64 notrap aligned readonly v0+80 +;; @002b v21 = load.i32 notrap aligned readonly v20 ;; @0027 jump block2 ;; ;; block2: ;; @002b v12 = load.i64 table_oob aligned table v11 -;; v30 = iconst.i64 -2 -;; v31 = band v12, v30 ; v30 = -2 -;; @002b brif v12, block5(v31), block4 +;; v31 = iconst.i64 -2 +;; v32 = band v12, v31 ; v31 = -2 +;; @002b brif v12, block5(v32), block4 ;; ;; block4 cold: -;; v32 = iconst.i32 0 -;; @002b v17 = call fn0(v0, v32, v2) ; v32 = 0 -;; @002b jump block5(v17) +;; v33 = iconst.i32 0 +;; @002b v18 = call fn0(v0, v33, v6) ; v33 = 0 +;; @002b jump block5(v18) ;; ;; block5(v14: i64): -;; @002b v21 = load.i32 icall_null aligned readonly v14+16 -;; @002b v22 = icmp eq v21, v20 -;; @002b brif v22, block7, block6 +;; @002b v22 = load.i32 icall_null aligned readonly v14+16 +;; @002b v23 = icmp eq v22, v21 +;; @002b brif v23, block7, block6 ;; ;; block6 cold: ;; @002b trap bad_sig ;; ;; block7: -;; @002b v23 = load.i64 notrap aligned readonly v14+8 -;; @002b v24 = load.i64 notrap aligned readonly v14+24 -;; @002b v25 = call_indirect sig0, v23(v24, v0) +;; @002b v24 = load.i64 notrap aligned readonly v14+8 +;; @002b v25 = load.i64 notrap aligned readonly v14+24 +;; @002b v26 = call_indirect sig0, v24(v25, v0) ;; @002e jump block2 ;; } ;; @@ -82,45 +82,45 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 ;; sig0 = (i64 vmctx, i64) -> i32 tail -;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig1 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; fn0 = colocated u1:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): ;; @0038 v6 = load.i64 notrap aligned readonly v0+88 -;; v36 = iconst.i64 8 -;; @0038 v8 = iadd v6, v36 ; v36 = 8 -;; v27 = iconst.i64 -2 +;; v37 = iconst.i64 8 +;; @0038 v8 = iadd v6, v37 ; v37 = 8 +;; v28 = iconst.i64 -2 ;; @0038 v14 = iconst.i32 0 -;; @0036 v2 = iconst.i32 1 -;; @0038 v18 = load.i64 notrap aligned readonly v0+80 -;; @0038 v19 = load.i32 notrap aligned readonly v18 +;; v36 = iconst.i64 1 +;; @0038 v19 = load.i64 notrap aligned readonly v0+80 +;; @0038 v20 = load.i32 notrap aligned readonly v19 ;; @0034 jump block2 ;; ;; block2: -;; v37 = iadd.i64 v6, v36 ; v36 = 8 -;; @0038 v11 = load.i64 table_oob aligned table v37 -;; v38 = iconst.i64 -2 -;; v39 = band v11, v38 ; v38 = -2 -;; @0038 brif v11, block5(v39), block4 +;; v38 = iadd.i64 v6, v37 ; v37 = 8 +;; @0038 v11 = load.i64 table_oob aligned table v38 +;; v39 = iconst.i64 -2 +;; v40 = band v11, v39 ; v39 = -2 +;; @0038 brif v11, block5(v40), block4 ;; ;; block4 cold: -;; v40 = iconst.i32 0 -;; v41 = iconst.i32 1 -;; @0038 v16 = call fn0(v0, v40, v41) ; v40 = 0, v41 = 1 -;; @0038 jump block5(v16) +;; v41 = iconst.i32 0 +;; v42 = iconst.i64 1 +;; @0038 v17 = call fn0(v0, v41, v42) ; v41 = 0, v42 = 1 +;; @0038 jump block5(v17) ;; ;; block5(v13: i64): -;; @0038 v20 = load.i32 icall_null aligned readonly v13+16 -;; @0038 v21 = icmp eq v20, v19 -;; @0038 brif v21, block7, block6 +;; @0038 v21 = load.i32 icall_null aligned readonly v13+16 +;; @0038 v22 = icmp eq v21, v20 +;; @0038 brif v22, block7, block6 ;; ;; block6 cold: ;; @0038 trap bad_sig ;; ;; block7: -;; @0038 v22 = load.i64 notrap aligned readonly v13+8 -;; @0038 v23 = load.i64 notrap aligned readonly v13+24 -;; @0038 v24 = call_indirect sig0, v22(v23, v0) +;; @0038 v23 = load.i64 notrap aligned readonly v13+8 +;; @0038 v24 = load.i64 notrap aligned readonly v13+24 +;; @0038 v25 = call_indirect sig0, v23(v24, v0) ;; @003b jump block2 ;; } diff --git a/tests/disas/icall-simd.wat b/tests/disas/icall-simd.wat index 523948634e7e..17b4bcc1e272 100644 --- a/tests/disas/icall-simd.wat +++ b/tests/disas/icall-simd.wat @@ -15,7 +15,7 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 ;; sig0 = (i64 vmctx, i64, i8x16) -> i8x16 tail -;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig1 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; fn0 = colocated u1:9 sig1 ;; stack_limit = gv2 ;; @@ -35,20 +35,21 @@ ;; block2 cold: ;; @0033 v16 = iconst.i32 0 ;; @0033 v17 = global_value.i64 gv3 -;; @0033 v18 = call fn0(v17, v16, v2) ; v16 = 0 -;; @0033 jump block3(v18) +;; @0033 v18 = uextend.i64 v2 +;; @0033 v19 = call fn0(v17, v16, v18) ; v16 = 0 +;; @0033 jump block3(v19) ;; ;; block3(v15: i64): -;; @0033 v19 = global_value.i64 gv3 -;; @0033 v20 = load.i64 notrap aligned readonly v19+80 -;; @0033 v21 = load.i32 notrap aligned readonly v20 -;; @0033 v22 = load.i32 icall_null aligned readonly v15+16 -;; @0033 v23 = icmp eq v22, v21 -;; @0033 trapz v23, bad_sig -;; @0033 v24 = load.i64 notrap aligned readonly v15+8 -;; @0033 v25 = load.i64 notrap aligned readonly v15+24 -;; @0033 v26 = call_indirect sig0, v24(v25, v0, v3) -;; @0036 jump block1(v26) +;; @0033 v20 = global_value.i64 gv3 +;; @0033 v21 = load.i64 notrap aligned readonly v20+80 +;; @0033 v22 = load.i32 notrap aligned readonly v21 +;; @0033 v23 = load.i32 icall_null aligned readonly v15+16 +;; @0033 v24 = icmp eq v23, v22 +;; @0033 trapz v24, bad_sig +;; @0033 v25 = load.i64 notrap aligned readonly v15+8 +;; @0033 v26 = load.i64 notrap aligned readonly v15+24 +;; @0033 v27 = call_indirect sig0, v25(v26, v0, v3) +;; @0036 jump block1(v27) ;; ;; block1(v4: i8x16): ;; @0036 return v4 diff --git a/tests/disas/icall.wat b/tests/disas/icall.wat index bdf6d722e9bc..83675583f1ed 100644 --- a/tests/disas/icall.wat +++ b/tests/disas/icall.wat @@ -15,7 +15,7 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 ;; sig0 = (i64 vmctx, i64, f32) -> i32 tail -;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig1 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; fn0 = colocated u1:9 sig1 ;; stack_limit = gv2 ;; @@ -35,20 +35,21 @@ ;; block2 cold: ;; @0033 v16 = iconst.i32 0 ;; @0033 v17 = global_value.i64 gv3 -;; @0033 v18 = call fn0(v17, v16, v2) ; v16 = 0 -;; @0033 jump block3(v18) +;; @0033 v18 = uextend.i64 v2 +;; @0033 v19 = call fn0(v17, v16, v18) ; v16 = 0 +;; @0033 jump block3(v19) ;; ;; block3(v15: i64): -;; @0033 v19 = global_value.i64 gv3 -;; @0033 v20 = load.i64 notrap aligned readonly v19+80 -;; @0033 v21 = load.i32 notrap aligned readonly v20 -;; @0033 v22 = load.i32 icall_null aligned readonly v15+16 -;; @0033 v23 = icmp eq v22, v21 -;; @0033 trapz v23, bad_sig -;; @0033 v24 = load.i64 notrap aligned readonly v15+8 -;; @0033 v25 = load.i64 notrap aligned readonly v15+24 -;; @0033 v26 = call_indirect sig0, v24(v25, v0, v3) -;; @0036 jump block1(v26) +;; @0033 v20 = global_value.i64 gv3 +;; @0033 v21 = load.i64 notrap aligned readonly v20+80 +;; @0033 v22 = load.i32 notrap aligned readonly v21 +;; @0033 v23 = load.i32 icall_null aligned readonly v15+16 +;; @0033 v24 = icmp eq v23, v22 +;; @0033 trapz v24, bad_sig +;; @0033 v25 = load.i64 notrap aligned readonly v15+8 +;; @0033 v26 = load.i64 notrap aligned readonly v15+24 +;; @0033 v27 = call_indirect sig0, v25(v26, v0, v3) +;; @0036 jump block1(v27) ;; ;; block1(v4: i32): ;; @0036 return v4 diff --git a/tests/disas/indirect-call-no-caching.wat b/tests/disas/indirect-call-no-caching.wat index bb9e7e4fce76..7d63d0bc3fc4 100644 --- a/tests/disas/indirect-call-no-caching.wat +++ b/tests/disas/indirect-call-no-caching.wat @@ -69,7 +69,7 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 ;; sig0 = (i64 vmctx, i64) -> i32 tail -;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig1 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; fn0 = colocated u1:9 sig1 ;; stack_limit = gv2 ;; @@ -89,20 +89,21 @@ ;; block2 cold: ;; @0050 v15 = iconst.i32 0 ;; @0050 v16 = global_value.i64 gv3 -;; @0050 v17 = call fn0(v16, v15, v2) ; v15 = 0 -;; @0050 jump block3(v17) +;; @0050 v17 = uextend.i64 v2 +;; @0050 v18 = call fn0(v16, v15, v17) ; v15 = 0 +;; @0050 jump block3(v18) ;; ;; block3(v14: i64): -;; @0050 v18 = global_value.i64 gv3 -;; @0050 v19 = load.i64 notrap aligned readonly v18+80 -;; @0050 v20 = load.i32 notrap aligned readonly v19 -;; @0050 v21 = load.i32 icall_null aligned readonly v14+16 -;; @0050 v22 = icmp eq v21, v20 -;; @0050 trapz v22, bad_sig -;; @0050 v23 = load.i64 notrap aligned readonly v14+8 -;; @0050 v24 = load.i64 notrap aligned readonly v14+24 -;; @0050 v25 = call_indirect sig0, v23(v24, v0) -;; @0053 jump block1(v25) +;; @0050 v19 = global_value.i64 gv3 +;; @0050 v20 = load.i64 notrap aligned readonly v19+80 +;; @0050 v21 = load.i32 notrap aligned readonly v20 +;; @0050 v22 = load.i32 icall_null aligned readonly v14+16 +;; @0050 v23 = icmp eq v22, v21 +;; @0050 trapz v23, bad_sig +;; @0050 v24 = load.i64 notrap aligned readonly v14+8 +;; @0050 v25 = load.i64 notrap aligned readonly v14+24 +;; @0050 v26 = call_indirect sig0, v24(v25, v0) +;; @0053 jump block1(v26) ;; ;; block1(v3: i32): ;; @0053 return v3 diff --git a/tests/disas/pulley/i32_add/const.wat b/tests/disas/pulley/i32_add/const.wat new file mode 100644 index 000000000000..f0e23cd22d0f --- /dev/null +++ b/tests/disas/pulley/i32_add/const.wat @@ -0,0 +1,23 @@ +;;! target = "pulley64" +;;! test = "compile" + +(module + (func (result i32) + i32.const 10 + i32.const 20 + i32.add + ) +) + +;; wasm[0]::function[0]: +;; xconst8 spilltmp0, -16 +;; xadd32 sp, sp, spilltmp0 +;; store64_offset8 sp, 8, lr +;; store64 sp, fp +;; xmov fp, sp +;; xconst8 x0, 30 +;; load64_offset8 lr, sp, 8 +;; load64 fp, sp +;; xconst8 spilltmp0, 16 +;; xadd32 sp, sp, spilltmp0 +;; ret diff --git a/tests/disas/readonly-funcrefs.wat b/tests/disas/readonly-funcrefs.wat index 2346abfbfed5..c11f8e15eeb5 100644 --- a/tests/disas/readonly-funcrefs.wat +++ b/tests/disas/readonly-funcrefs.wat @@ -38,7 +38,7 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 ;; sig0 = (i64 vmctx, i64) tail -;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig1 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; fn0 = colocated u1:9 sig1 ;; stack_limit = gv2 ;; @@ -48,34 +48,34 @@ ;; @0031 v9 = iconst.i64 0 ;; @0031 v6 = load.i64 notrap aligned readonly v0+88 ;; @0031 v5 = uextend.i64 v2 -;; v25 = iconst.i64 3 -;; @0031 v7 = ishl v5, v25 ; v25 = 3 +;; v26 = iconst.i64 3 +;; @0031 v7 = ishl v5, v26 ; v26 = 3 ;; @0031 v8 = iadd v6, v7 ;; @0031 v10 = select_spectre_guard v4, v9, v8 ; v9 = 0 ;; @0031 v11 = load.i64 table_oob aligned table v10 -;; v26 = iconst.i64 -2 -;; @0031 v12 = band v11, v26 ; v26 = -2 +;; v27 = iconst.i64 -2 +;; @0031 v12 = band v11, v27 ; v27 = -2 ;; @0031 brif v11, block3(v12), block2 ;; ;; block2 cold: ;; @0031 v14 = iconst.i32 0 -;; @0031 v16 = call fn0(v0, v14, v2) ; v14 = 0 -;; @0031 jump block3(v16) +;; @0031 v17 = call fn0(v0, v14, v5) ; v14 = 0 +;; @0031 jump block3(v17) ;; ;; block3(v13: i64): -;; @0031 v20 = load.i32 icall_null aligned readonly v13+16 -;; @0031 v18 = load.i64 notrap aligned readonly v0+80 -;; @0031 v19 = load.i32 notrap aligned readonly v18 -;; @0031 v21 = icmp eq v20, v19 -;; @0031 brif v21, block5, block4 +;; @0031 v21 = load.i32 icall_null aligned readonly v13+16 +;; @0031 v19 = load.i64 notrap aligned readonly v0+80 +;; @0031 v20 = load.i32 notrap aligned readonly v19 +;; @0031 v22 = icmp eq v21, v20 +;; @0031 brif v22, block5, block4 ;; ;; block4 cold: ;; @0031 trap bad_sig ;; ;; block5: -;; @0031 v22 = load.i64 notrap aligned readonly v13+8 -;; @0031 v23 = load.i64 notrap aligned readonly v13+24 -;; @0031 call_indirect sig0, v22(v23, v0) +;; @0031 v23 = load.i64 notrap aligned readonly v13+8 +;; @0031 v24 = load.i64 notrap aligned readonly v13+24 +;; @0031 call_indirect sig0, v23(v24, v0) ;; @0034 jump block1 ;; ;; block1: diff --git a/tests/disas/ref-func-0.wat b/tests/disas/ref-func-0.wat index d0dcc9d94e0b..9b527227cee8 100644 --- a/tests/disas/ref-func-0.wat +++ b/tests/disas/ref-func-0.wat @@ -15,28 +15,137 @@ ;; function u0:1(i64 vmctx, i64) -> i32, i32, i64, i64 tail { ;; ss0 = explicit_slot 4, align = 4 +;; ss1 = explicit_slot 4, align = 4 ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx -;; sig0 = (i64 vmctx, i32 uext) -> i32 system_v -;; fn0 = colocated u1:27 sig0 +;; sig0 = (i64 vmctx, i32) -> i32 system_v +;; fn0 = colocated u1:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): ;; @008f v6 = global_value.i64 gv3 -;; @008f v7 = iconst.i32 0 -;; @008f v8 = call fn0(v6, v7) ; v7 = 0 +;; @008f v7 = iadd_imm v6, 112 +;; @008f v8 = load.i32 notrap aligned v7 ;; stack_store v8, ss0 -;; @0091 v9 = global_value.i64 gv3 -;; @0091 v10 = iconst.i32 1 -;; @0091 v11 = call fn0(v9, v10), stack_map=[i32 @ ss0+0] ; v10 = 1 -;; @0093 v12 = global_value.i64 gv3 -;; @0093 v13 = load.i64 notrap aligned table v12+144 -;; @0095 v14 = global_value.i64 gv3 -;; @0095 v15 = load.i64 notrap aligned table v14+160 -;; v16 = stack_load.i32 ss0 -;; @0097 jump block1(v16, v11, v13, v15) +;; v89 = stack_load.i32 ss0 +;; @008f v9 = icmp_imm eq v89, 0 +;; @008f brif v9, block5, block2 +;; +;; block2: +;; @008f v10 = global_value.i64 gv3 +;; @008f v11 = load.i64 notrap aligned v10+56 +;; @008f v12 = load.i64 notrap aligned v11 +;; @008f v13 = load.i64 notrap aligned v11+8 +;; @008f v14 = icmp eq v12, v13 +;; @008f brif v14, block3, block4 +;; +;; block4: +;; @008f v15 = global_value.i64 gv3 +;; @008f v16 = load.i64 notrap aligned readonly v15+40 +;; @008f v17 = load.i64 notrap aligned readonly v15+48 +;; v88 = stack_load.i32 ss0 +;; @008f v18 = uextend.i64 v88 +;; @008f v19 = iconst.i64 8 +;; @008f v20 = uadd_overflow_trap v18, v19, user65535 ; v19 = 8 +;; @008f v21 = iconst.i64 8 +;; @008f v22 = uadd_overflow_trap v20, v21, user65535 ; v21 = 8 +;; @008f v23 = icmp ult v22, v17 +;; @008f trapz v23, user65535 +;; @008f v24 = iadd v16, v20 +;; @008f v25 = load.i64 notrap aligned v24 +;; @008f v26 = iadd_imm v25, 1 +;; @008f v27 = global_value.i64 gv3 +;; @008f v28 = load.i64 notrap aligned readonly v27+40 +;; @008f v29 = load.i64 notrap aligned readonly v27+48 +;; v87 = stack_load.i32 ss0 +;; @008f v30 = uextend.i64 v87 +;; @008f v31 = iconst.i64 8 +;; @008f v32 = uadd_overflow_trap v30, v31, user65535 ; v31 = 8 +;; @008f v33 = iconst.i64 8 +;; @008f v34 = uadd_overflow_trap v32, v33, user65535 ; v33 = 8 +;; @008f v35 = icmp ult v34, v29 +;; @008f trapz v35, user65535 +;; @008f v36 = iadd v28, v32 +;; @008f store notrap aligned v26, v36 +;; v86 = stack_load.i32 ss0 +;; @008f store notrap aligned v86, v12 +;; @008f v37 = iadd_imm.i64 v12, 4 +;; @008f store notrap aligned v37, v11 +;; @008f jump block5 +;; +;; block3 cold: +;; @008f v38 = global_value.i64 gv3 +;; v85 = stack_load.i32 ss0 +;; @008f v39 = call fn0(v38, v85), stack_map=[i32 @ ss0+0] +;; @008f jump block5 +;; +;; block5: +;; @0091 v40 = global_value.i64 gv3 +;; @0091 v41 = iadd_imm v40, 128 +;; @0091 v42 = load.i32 notrap aligned v41 +;; stack_store v42, ss1 +;; v84 = stack_load.i32 ss1 +;; @0091 v43 = icmp_imm eq v84, 0 +;; @0091 brif v43, block9, block6 +;; +;; block6: +;; @0091 v44 = global_value.i64 gv3 +;; @0091 v45 = load.i64 notrap aligned v44+56 +;; @0091 v46 = load.i64 notrap aligned v45 +;; @0091 v47 = load.i64 notrap aligned v45+8 +;; @0091 v48 = icmp eq v46, v47 +;; @0091 brif v48, block7, block8 +;; +;; block8: +;; @0091 v49 = global_value.i64 gv3 +;; @0091 v50 = load.i64 notrap aligned readonly v49+40 +;; @0091 v51 = load.i64 notrap aligned readonly v49+48 +;; v83 = stack_load.i32 ss1 +;; @0091 v52 = uextend.i64 v83 +;; @0091 v53 = iconst.i64 8 +;; @0091 v54 = uadd_overflow_trap v52, v53, user65535 ; v53 = 8 +;; @0091 v55 = iconst.i64 8 +;; @0091 v56 = uadd_overflow_trap v54, v55, user65535 ; v55 = 8 +;; @0091 v57 = icmp ult v56, v51 +;; @0091 trapz v57, user65535 +;; @0091 v58 = iadd v50, v54 +;; @0091 v59 = load.i64 notrap aligned v58 +;; @0091 v60 = iadd_imm v59, 1 +;; @0091 v61 = global_value.i64 gv3 +;; @0091 v62 = load.i64 notrap aligned readonly v61+40 +;; @0091 v63 = load.i64 notrap aligned readonly v61+48 +;; v82 = stack_load.i32 ss1 +;; @0091 v64 = uextend.i64 v82 +;; @0091 v65 = iconst.i64 8 +;; @0091 v66 = uadd_overflow_trap v64, v65, user65535 ; v65 = 8 +;; @0091 v67 = iconst.i64 8 +;; @0091 v68 = uadd_overflow_trap v66, v67, user65535 ; v67 = 8 +;; @0091 v69 = icmp ult v68, v63 +;; @0091 trapz v69, user65535 +;; @0091 v70 = iadd v62, v66 +;; @0091 store notrap aligned v60, v70 +;; v81 = stack_load.i32 ss1 +;; @0091 store notrap aligned v81, v46 +;; @0091 v71 = iadd_imm.i64 v46, 4 +;; @0091 store notrap aligned v71, v45 +;; @0091 jump block9 +;; +;; block7 cold: +;; @0091 v72 = global_value.i64 gv3 +;; v80 = stack_load.i32 ss1 +;; @0091 v73 = call fn0(v72, v80), stack_map=[i32 @ ss0+0, i32 @ ss1+0] +;; @0091 jump block9 +;; +;; block9: +;; @0093 v74 = global_value.i64 gv3 +;; @0093 v75 = load.i64 notrap aligned table v74+144 +;; @0095 v76 = global_value.i64 gv3 +;; @0095 v77 = load.i64 notrap aligned table v76+160 +;; v78 = stack_load.i32 ss0 +;; v79 = stack_load.i32 ss1 +;; @0097 jump block1(v78, v79, v75, v77) ;; ;; block1(v2: i32, v3: i32, v4: i64, v5: i64): ;; @0097 return v2, v3, v4, v5 diff --git a/tests/disas/table-copy.wat b/tests/disas/table-copy.wat index c596de21a3ff..14c2d5b0a0a9 100644 --- a/tests/disas/table-copy.wat +++ b/tests/disas/table-copy.wat @@ -67,15 +67,18 @@ ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx -;; sig0 = (i64 vmctx, i32 uext, i32 uext, i32 uext, i32 uext, i32 uext) system_v +;; sig0 = (i64 vmctx, i32 uext, i32 uext, i64, i64, i64) system_v ;; fn0 = colocated u1:1 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): -;; @0090 v7 = iconst.i32 0 -;; @0090 v8 = iconst.i32 1 -;; @0090 v9 = global_value.i64 gv3 -;; @0090 call fn0(v9, v7, v8, v3, v4, v5) ; v7 = 0, v8 = 1 +;; @0090 v7 = uextend.i64 v3 +;; @0090 v8 = uextend.i64 v4 +;; @0090 v9 = uextend.i64 v5 +;; @0090 v10 = iconst.i32 0 +;; @0090 v11 = iconst.i32 1 +;; @0090 v12 = global_value.i64 gv3 +;; @0090 call fn0(v12, v10, v11, v7, v8, v9) ; v10 = 0, v11 = 1 ;; @0094 jump block1(v2) ;; ;; block1(v6: i32): @@ -87,15 +90,18 @@ ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx -;; sig0 = (i64 vmctx, i32 uext, i32 uext, i32 uext, i32 uext, i32 uext) system_v +;; sig0 = (i64 vmctx, i32 uext, i32 uext, i64, i64, i64) system_v ;; fn0 = colocated u1:1 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): -;; @009f v7 = iconst.i32 1 -;; @009f v8 = iconst.i32 0 -;; @009f v9 = global_value.i64 gv3 -;; @009f call fn0(v9, v7, v8, v3, v4, v5) ; v7 = 1, v8 = 0 +;; @009f v7 = uextend.i64 v3 +;; @009f v8 = uextend.i64 v4 +;; @009f v9 = uextend.i64 v5 +;; @009f v10 = iconst.i32 1 +;; @009f v11 = iconst.i32 0 +;; @009f v12 = global_value.i64 gv3 +;; @009f call fn0(v12, v10, v11, v7, v8, v9) ; v10 = 1, v11 = 0 ;; @00a3 jump block1(v2) ;; ;; block1(v6: i32): diff --git a/tests/disas/table-get.wat b/tests/disas/table-get.wat index 2a2207b1a7f3..c12ffdeeb427 100644 --- a/tests/disas/table-get.wat +++ b/tests/disas/table-get.wat @@ -21,98 +21,99 @@ ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned gv3+88 -;; gv5 = load.i32 notrap aligned gv3+96 +;; gv5 = load.i64 notrap aligned gv3+96 ;; sig0 = (i64 vmctx, i32) -> i32 system_v ;; fn0 = colocated u1:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): ;; @0051 v3 = iconst.i32 0 -;; @0053 v4 = load.i32 notrap aligned v0+96 -;; @0053 v5 = icmp uge v3, v4 ; v3 = 0 -;; @0053 v6 = uextend.i64 v3 ; v3 = 0 -;; @0053 v7 = load.i64 notrap aligned v0+88 -;; v52 = iconst.i64 2 -;; @0053 v8 = ishl v6, v52 ; v52 = 2 -;; @0053 v9 = iadd v7, v8 -;; @0053 v10 = iconst.i64 0 -;; @0053 v11 = select_spectre_guard v5, v10, v9 ; v10 = 0 -;; @0053 v12 = load.i32 table_oob aligned table v11 -;; v53 = stack_addr.i64 ss0 -;; store notrap v12, v53 +;; @0053 v4 = load.i64 notrap aligned v0+96 +;; @0053 v5 = ireduce.i32 v4 +;; @0053 v6 = icmp uge v3, v5 ; v3 = 0 +;; @0053 v7 = uextend.i64 v3 ; v3 = 0 +;; @0053 v8 = load.i64 notrap aligned v0+88 +;; v53 = iconst.i64 2 +;; @0053 v9 = ishl v7, v53 ; v53 = 2 +;; @0053 v10 = iadd v8, v9 +;; @0053 v11 = iconst.i64 0 +;; @0053 v12 = select_spectre_guard v6, v11, v10 ; v11 = 0 +;; @0053 v13 = load.i32 table_oob aligned table v12 ;; v54 = stack_addr.i64 ss0 -;; v49 = load.i32 notrap v54 -;; v55 = iconst.i32 0 -;; @0053 v13 = icmp eq v49, v55 ; v55 = 0 -;; @0053 brif v13, block5, block2 +;; store notrap v13, v54 +;; v55 = stack_addr.i64 ss0 +;; v50 = load.i32 notrap v55 +;; v56 = iconst.i32 0 +;; @0053 v14 = icmp eq v50, v56 ; v56 = 0 +;; @0053 brif v14, block5, block2 ;; ;; block2: -;; @0053 v15 = load.i64 notrap aligned v0+56 -;; @0053 v16 = load.i64 notrap aligned v15 -;; @0053 v17 = load.i64 notrap aligned v15+8 -;; @0053 v18 = icmp eq v16, v17 -;; @0053 brif v18, block3, block4 +;; @0053 v16 = load.i64 notrap aligned v0+56 +;; @0053 v17 = load.i64 notrap aligned v16 +;; @0053 v18 = load.i64 notrap aligned v16+8 +;; @0053 v19 = icmp eq v17, v18 +;; @0053 brif v19, block3, block4 ;; ;; block4: -;; @0053 v20 = load.i64 notrap aligned readonly v0+40 -;; @0053 v21 = load.i64 notrap aligned readonly v0+48 -;; v56 = stack_addr.i64 ss0 -;; v48 = load.i32 notrap v56 -;; @0053 v22 = uextend.i64 v48 -;; @0053 v23 = iconst.i64 8 -;; @0053 v24 = uadd_overflow_trap v22, v23, user65535 ; v23 = 8 -;; @0053 v25 = iconst.i64 8 -;; @0053 v26 = uadd_overflow_trap v24, v25, user65535 ; v25 = 8 -;; @0053 v27 = icmp ult v26, v21 -;; @0053 brif v27, block7, block6 +;; @0053 v21 = load.i64 notrap aligned readonly v0+40 +;; @0053 v22 = load.i64 notrap aligned readonly v0+48 +;; v57 = stack_addr.i64 ss0 +;; v49 = load.i32 notrap v57 +;; @0053 v23 = uextend.i64 v49 +;; @0053 v24 = iconst.i64 8 +;; @0053 v25 = uadd_overflow_trap v23, v24, user65535 ; v24 = 8 +;; @0053 v26 = iconst.i64 8 +;; @0053 v27 = uadd_overflow_trap v25, v26, user65535 ; v26 = 8 +;; @0053 v28 = icmp ult v27, v22 +;; @0053 brif v28, block7, block6 ;; ;; block6 cold: ;; @0053 trap user65535 ;; ;; block7: -;; @0053 v28 = iadd.i64 v20, v24 -;; @0053 v29 = load.i64 notrap aligned v28 -;; v57 = iconst.i64 1 -;; @0053 v30 = iadd v29, v57 ; v57 = 1 -;; @0053 v32 = load.i64 notrap aligned readonly v0+40 -;; @0053 v33 = load.i64 notrap aligned readonly v0+48 -;; v58 = stack_addr.i64 ss0 -;; v47 = load.i32 notrap v58 -;; @0053 v34 = uextend.i64 v47 -;; @0053 v35 = iconst.i64 8 -;; @0053 v36 = uadd_overflow_trap v34, v35, user65535 ; v35 = 8 -;; @0053 v37 = iconst.i64 8 -;; @0053 v38 = uadd_overflow_trap v36, v37, user65535 ; v37 = 8 -;; @0053 v39 = icmp ult v38, v33 -;; @0053 brif v39, block9, block8 +;; @0053 v29 = iadd.i64 v21, v25 +;; @0053 v30 = load.i64 notrap aligned v29 +;; v58 = iconst.i64 1 +;; @0053 v31 = iadd v30, v58 ; v58 = 1 +;; @0053 v33 = load.i64 notrap aligned readonly v0+40 +;; @0053 v34 = load.i64 notrap aligned readonly v0+48 +;; v59 = stack_addr.i64 ss0 +;; v48 = load.i32 notrap v59 +;; @0053 v35 = uextend.i64 v48 +;; @0053 v36 = iconst.i64 8 +;; @0053 v37 = uadd_overflow_trap v35, v36, user65535 ; v36 = 8 +;; @0053 v38 = iconst.i64 8 +;; @0053 v39 = uadd_overflow_trap v37, v38, user65535 ; v38 = 8 +;; @0053 v40 = icmp ult v39, v34 +;; @0053 brif v40, block9, block8 ;; ;; block8 cold: ;; @0053 trap user65535 ;; ;; block9: -;; @0053 v40 = iadd.i64 v32, v36 -;; @0053 store.i64 notrap aligned v30, v40 -;; v59 = stack_addr.i64 ss0 -;; v46 = load.i32 notrap v59 -;; @0053 store notrap aligned v46, v16 -;; v60 = iconst.i64 4 -;; @0053 v41 = iadd.i64 v16, v60 ; v60 = 4 -;; @0053 store notrap aligned v41, v15 +;; @0053 v41 = iadd.i64 v33, v37 +;; @0053 store.i64 notrap aligned v31, v41 +;; v60 = stack_addr.i64 ss0 +;; v47 = load.i32 notrap v60 +;; @0053 store notrap aligned v47, v17 +;; v61 = iconst.i64 4 +;; @0053 v42 = iadd.i64 v17, v61 ; v61 = 4 +;; @0053 store notrap aligned v42, v16 ;; @0053 jump block5 ;; ;; block3 cold: -;; v61 = stack_addr.i64 ss0 -;; v45 = load.i32 notrap v61 -;; @0053 v43 = call fn0(v0, v45), stack_map=[i32 @ ss0+0] +;; v62 = stack_addr.i64 ss0 +;; v46 = load.i32 notrap v62 +;; @0053 v44 = call fn0(v0, v46), stack_map=[i32 @ ss0+0] ;; @0053 jump block5 ;; ;; block5: -;; v62 = stack_addr.i64 ss0 -;; v44 = load.i32 notrap v62 +;; v63 = stack_addr.i64 ss0 +;; v45 = load.i32 notrap v63 ;; @0055 jump block1 ;; ;; block1: -;; @0055 return v44 +;; @0055 return v45 ;; } ;; ;; function u0:1(i64 vmctx, i64, i32) -> i32 tail { @@ -122,95 +123,96 @@ ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned gv3+88 -;; gv5 = load.i32 notrap aligned gv3+96 +;; gv5 = load.i64 notrap aligned gv3+96 ;; sig0 = (i64 vmctx, i32) -> i32 system_v ;; fn0 = colocated u1:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): -;; @005a v4 = load.i32 notrap aligned v0+96 -;; @005a v5 = icmp uge v2, v4 -;; @005a v6 = uextend.i64 v2 -;; @005a v7 = load.i64 notrap aligned v0+88 -;; v52 = iconst.i64 2 -;; @005a v8 = ishl v6, v52 ; v52 = 2 -;; @005a v9 = iadd v7, v8 -;; @005a v10 = iconst.i64 0 -;; @005a v11 = select_spectre_guard v5, v10, v9 ; v10 = 0 -;; @005a v12 = load.i32 table_oob aligned table v11 -;; v53 = stack_addr.i64 ss0 -;; store notrap v12, v53 +;; @005a v4 = load.i64 notrap aligned v0+96 +;; @005a v5 = ireduce.i32 v4 +;; @005a v6 = icmp uge v2, v5 +;; @005a v7 = uextend.i64 v2 +;; @005a v8 = load.i64 notrap aligned v0+88 +;; v53 = iconst.i64 2 +;; @005a v9 = ishl v7, v53 ; v53 = 2 +;; @005a v10 = iadd v8, v9 +;; @005a v11 = iconst.i64 0 +;; @005a v12 = select_spectre_guard v6, v11, v10 ; v11 = 0 +;; @005a v13 = load.i32 table_oob aligned table v12 ;; v54 = stack_addr.i64 ss0 -;; v49 = load.i32 notrap v54 -;; v55 = iconst.i32 0 -;; @005a v13 = icmp eq v49, v55 ; v55 = 0 -;; @005a brif v13, block5, block2 +;; store notrap v13, v54 +;; v55 = stack_addr.i64 ss0 +;; v50 = load.i32 notrap v55 +;; v56 = iconst.i32 0 +;; @005a v14 = icmp eq v50, v56 ; v56 = 0 +;; @005a brif v14, block5, block2 ;; ;; block2: -;; @005a v15 = load.i64 notrap aligned v0+56 -;; @005a v16 = load.i64 notrap aligned v15 -;; @005a v17 = load.i64 notrap aligned v15+8 -;; @005a v18 = icmp eq v16, v17 -;; @005a brif v18, block3, block4 +;; @005a v16 = load.i64 notrap aligned v0+56 +;; @005a v17 = load.i64 notrap aligned v16 +;; @005a v18 = load.i64 notrap aligned v16+8 +;; @005a v19 = icmp eq v17, v18 +;; @005a brif v19, block3, block4 ;; ;; block4: -;; @005a v20 = load.i64 notrap aligned readonly v0+40 -;; @005a v21 = load.i64 notrap aligned readonly v0+48 -;; v56 = stack_addr.i64 ss0 -;; v48 = load.i32 notrap v56 -;; @005a v22 = uextend.i64 v48 -;; @005a v23 = iconst.i64 8 -;; @005a v24 = uadd_overflow_trap v22, v23, user65535 ; v23 = 8 -;; @005a v25 = iconst.i64 8 -;; @005a v26 = uadd_overflow_trap v24, v25, user65535 ; v25 = 8 -;; @005a v27 = icmp ult v26, v21 -;; @005a brif v27, block7, block6 +;; @005a v21 = load.i64 notrap aligned readonly v0+40 +;; @005a v22 = load.i64 notrap aligned readonly v0+48 +;; v57 = stack_addr.i64 ss0 +;; v49 = load.i32 notrap v57 +;; @005a v23 = uextend.i64 v49 +;; @005a v24 = iconst.i64 8 +;; @005a v25 = uadd_overflow_trap v23, v24, user65535 ; v24 = 8 +;; @005a v26 = iconst.i64 8 +;; @005a v27 = uadd_overflow_trap v25, v26, user65535 ; v26 = 8 +;; @005a v28 = icmp ult v27, v22 +;; @005a brif v28, block7, block6 ;; ;; block6 cold: ;; @005a trap user65535 ;; ;; block7: -;; @005a v28 = iadd.i64 v20, v24 -;; @005a v29 = load.i64 notrap aligned v28 -;; v57 = iconst.i64 1 -;; @005a v30 = iadd v29, v57 ; v57 = 1 -;; @005a v32 = load.i64 notrap aligned readonly v0+40 -;; @005a v33 = load.i64 notrap aligned readonly v0+48 -;; v58 = stack_addr.i64 ss0 -;; v47 = load.i32 notrap v58 -;; @005a v34 = uextend.i64 v47 -;; @005a v35 = iconst.i64 8 -;; @005a v36 = uadd_overflow_trap v34, v35, user65535 ; v35 = 8 -;; @005a v37 = iconst.i64 8 -;; @005a v38 = uadd_overflow_trap v36, v37, user65535 ; v37 = 8 -;; @005a v39 = icmp ult v38, v33 -;; @005a brif v39, block9, block8 +;; @005a v29 = iadd.i64 v21, v25 +;; @005a v30 = load.i64 notrap aligned v29 +;; v58 = iconst.i64 1 +;; @005a v31 = iadd v30, v58 ; v58 = 1 +;; @005a v33 = load.i64 notrap aligned readonly v0+40 +;; @005a v34 = load.i64 notrap aligned readonly v0+48 +;; v59 = stack_addr.i64 ss0 +;; v48 = load.i32 notrap v59 +;; @005a v35 = uextend.i64 v48 +;; @005a v36 = iconst.i64 8 +;; @005a v37 = uadd_overflow_trap v35, v36, user65535 ; v36 = 8 +;; @005a v38 = iconst.i64 8 +;; @005a v39 = uadd_overflow_trap v37, v38, user65535 ; v38 = 8 +;; @005a v40 = icmp ult v39, v34 +;; @005a brif v40, block9, block8 ;; ;; block8 cold: ;; @005a trap user65535 ;; ;; block9: -;; @005a v40 = iadd.i64 v32, v36 -;; @005a store.i64 notrap aligned v30, v40 -;; v59 = stack_addr.i64 ss0 -;; v46 = load.i32 notrap v59 -;; @005a store notrap aligned v46, v16 -;; v60 = iconst.i64 4 -;; @005a v41 = iadd.i64 v16, v60 ; v60 = 4 -;; @005a store notrap aligned v41, v15 +;; @005a v41 = iadd.i64 v33, v37 +;; @005a store.i64 notrap aligned v31, v41 +;; v60 = stack_addr.i64 ss0 +;; v47 = load.i32 notrap v60 +;; @005a store notrap aligned v47, v17 +;; v61 = iconst.i64 4 +;; @005a v42 = iadd.i64 v17, v61 ; v61 = 4 +;; @005a store notrap aligned v42, v16 ;; @005a jump block5 ;; ;; block3 cold: -;; v61 = stack_addr.i64 ss0 -;; v45 = load.i32 notrap v61 -;; @005a v43 = call fn0(v0, v45), stack_map=[i32 @ ss0+0] +;; v62 = stack_addr.i64 ss0 +;; v46 = load.i32 notrap v62 +;; @005a v44 = call fn0(v0, v46), stack_map=[i32 @ ss0+0] ;; @005a jump block5 ;; ;; block5: -;; v62 = stack_addr.i64 ss0 -;; v44 = load.i32 notrap v62 +;; v63 = stack_addr.i64 ss0 +;; v45 = load.i32 notrap v63 ;; @005c jump block1 ;; ;; block1: -;; @005c return v44 +;; @005c return v45 ;; } diff --git a/tests/disas/table-set.wat b/tests/disas/table-set.wat index 54029fe7ceee..1aeb42ff1da7 100644 --- a/tests/disas/table-set.wat +++ b/tests/disas/table-set.wat @@ -22,114 +22,115 @@ ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned gv3+88 -;; gv5 = load.i32 notrap aligned gv3+96 +;; gv5 = load.i64 notrap aligned gv3+96 ;; sig0 = (i64 vmctx, i32 uext) system_v ;; fn0 = colocated u1:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): ;; @0051 v3 = iconst.i32 0 -;; @0055 v4 = load.i32 notrap aligned v0+96 -;; @0055 v5 = icmp uge v3, v4 ; v3 = 0 -;; @0055 v6 = uextend.i64 v3 ; v3 = 0 -;; @0055 v7 = load.i64 notrap aligned v0+88 -;; v63 = iconst.i64 2 -;; @0055 v8 = ishl v6, v63 ; v63 = 2 -;; @0055 v9 = iadd v7, v8 -;; @0055 v10 = iconst.i64 0 -;; @0055 v11 = select_spectre_guard v5, v10, v9 ; v10 = 0 -;; @0055 v12 = load.i32 table_oob aligned table v11 -;; v64 = iconst.i32 0 -;; @0055 v13 = icmp eq v2, v64 ; v64 = 0 -;; @0055 brif v13, block3, block2 +;; @0055 v4 = load.i64 notrap aligned v0+96 +;; @0055 v5 = ireduce.i32 v4 +;; @0055 v6 = icmp uge v3, v5 ; v3 = 0 +;; @0055 v7 = uextend.i64 v3 ; v3 = 0 +;; @0055 v8 = load.i64 notrap aligned v0+88 +;; v64 = iconst.i64 2 +;; @0055 v9 = ishl v7, v64 ; v64 = 2 +;; @0055 v10 = iadd v8, v9 +;; @0055 v11 = iconst.i64 0 +;; @0055 v12 = select_spectre_guard v6, v11, v10 ; v11 = 0 +;; @0055 v13 = load.i32 table_oob aligned table v12 +;; v65 = iconst.i32 0 +;; @0055 v14 = icmp eq v2, v65 ; v65 = 0 +;; @0055 brif v14, block3, block2 ;; ;; block2: -;; @0055 v15 = load.i64 notrap aligned readonly v0+40 -;; @0055 v16 = load.i64 notrap aligned readonly v0+48 -;; @0055 v17 = uextend.i64 v2 -;; @0055 v18 = iconst.i64 8 -;; @0055 v19 = uadd_overflow_trap v17, v18, user65535 ; v18 = 8 -;; @0055 v20 = iconst.i64 8 -;; @0055 v21 = uadd_overflow_trap v19, v20, user65535 ; v20 = 8 -;; @0055 v22 = icmp ult v21, v16 -;; @0055 brif v22, block9, block8 +;; @0055 v16 = load.i64 notrap aligned readonly v0+40 +;; @0055 v17 = load.i64 notrap aligned readonly v0+48 +;; @0055 v18 = uextend.i64 v2 +;; @0055 v19 = iconst.i64 8 +;; @0055 v20 = uadd_overflow_trap v18, v19, user65535 ; v19 = 8 +;; @0055 v21 = iconst.i64 8 +;; @0055 v22 = uadd_overflow_trap v20, v21, user65535 ; v21 = 8 +;; @0055 v23 = icmp ult v22, v17 +;; @0055 brif v23, block9, block8 ;; ;; block8 cold: ;; @0055 trap user65535 ;; ;; block9: -;; @0055 v23 = iadd.i64 v15, v19 -;; @0055 v24 = load.i64 notrap aligned v23 -;; v65 = iconst.i64 1 -;; @0055 v25 = iadd v24, v65 ; v65 = 1 -;; @0055 v27 = load.i64 notrap aligned readonly v0+40 -;; @0055 v28 = load.i64 notrap aligned readonly v0+48 -;; @0055 v29 = uextend.i64 v2 -;; @0055 v30 = iconst.i64 8 -;; @0055 v31 = uadd_overflow_trap v29, v30, user65535 ; v30 = 8 -;; @0055 v32 = iconst.i64 8 -;; @0055 v33 = uadd_overflow_trap v31, v32, user65535 ; v32 = 8 -;; @0055 v34 = icmp ult v33, v28 -;; @0055 brif v34, block11, block10 +;; @0055 v24 = iadd.i64 v16, v20 +;; @0055 v25 = load.i64 notrap aligned v24 +;; v66 = iconst.i64 1 +;; @0055 v26 = iadd v25, v66 ; v66 = 1 +;; @0055 v28 = load.i64 notrap aligned readonly v0+40 +;; @0055 v29 = load.i64 notrap aligned readonly v0+48 +;; @0055 v30 = uextend.i64 v2 +;; @0055 v31 = iconst.i64 8 +;; @0055 v32 = uadd_overflow_trap v30, v31, user65535 ; v31 = 8 +;; @0055 v33 = iconst.i64 8 +;; @0055 v34 = uadd_overflow_trap v32, v33, user65535 ; v33 = 8 +;; @0055 v35 = icmp ult v34, v29 +;; @0055 brif v35, block11, block10 ;; ;; block10 cold: ;; @0055 trap user65535 ;; ;; block11: -;; @0055 v35 = iadd.i64 v27, v31 -;; @0055 store.i64 notrap aligned v25, v35 +;; @0055 v36 = iadd.i64 v28, v32 +;; @0055 store.i64 notrap aligned v26, v36 ;; @0055 jump block3 ;; ;; block3: -;; @0055 store.i32 table_oob aligned table v2, v11 -;; v66 = iconst.i32 0 -;; @0055 v36 = icmp.i32 eq v12, v66 ; v66 = 0 -;; @0055 brif v36, block7, block4 +;; @0055 store.i32 table_oob aligned table v2, v12 +;; v67 = iconst.i32 0 +;; @0055 v37 = icmp.i32 eq v13, v67 ; v67 = 0 +;; @0055 brif v37, block7, block4 ;; ;; block4: -;; @0055 v38 = load.i64 notrap aligned readonly v0+40 -;; @0055 v39 = load.i64 notrap aligned readonly v0+48 -;; @0055 v40 = uextend.i64 v12 -;; @0055 v41 = iconst.i64 8 -;; @0055 v42 = uadd_overflow_trap v40, v41, user65535 ; v41 = 8 -;; @0055 v43 = iconst.i64 8 -;; @0055 v44 = uadd_overflow_trap v42, v43, user65535 ; v43 = 8 -;; @0055 v45 = icmp ult v44, v39 -;; @0055 brif v45, block13, block12 +;; @0055 v39 = load.i64 notrap aligned readonly v0+40 +;; @0055 v40 = load.i64 notrap aligned readonly v0+48 +;; @0055 v41 = uextend.i64 v13 +;; @0055 v42 = iconst.i64 8 +;; @0055 v43 = uadd_overflow_trap v41, v42, user65535 ; v42 = 8 +;; @0055 v44 = iconst.i64 8 +;; @0055 v45 = uadd_overflow_trap v43, v44, user65535 ; v44 = 8 +;; @0055 v46 = icmp ult v45, v40 +;; @0055 brif v46, block13, block12 ;; ;; block12 cold: ;; @0055 trap user65535 ;; ;; block13: -;; @0055 v46 = iadd.i64 v38, v42 -;; @0055 v47 = load.i64 notrap aligned v46 -;; v67 = iconst.i64 -1 -;; @0055 v48 = iadd v47, v67 ; v67 = -1 -;; v68 = iconst.i64 0 -;; @0055 v49 = icmp eq v48, v68 ; v68 = 0 -;; @0055 brif v49, block5, block6 +;; @0055 v47 = iadd.i64 v39, v43 +;; @0055 v48 = load.i64 notrap aligned v47 +;; v68 = iconst.i64 -1 +;; @0055 v49 = iadd v48, v68 ; v68 = -1 +;; v69 = iconst.i64 0 +;; @0055 v50 = icmp eq v49, v69 ; v69 = 0 +;; @0055 brif v50, block5, block6 ;; ;; block5 cold: -;; @0055 call fn0(v0, v12) +;; @0055 call fn0(v0, v13) ;; @0055 jump block7 ;; ;; block6: -;; @0055 v52 = load.i64 notrap aligned readonly v0+40 -;; @0055 v53 = load.i64 notrap aligned readonly v0+48 -;; @0055 v54 = uextend.i64 v12 -;; @0055 v55 = iconst.i64 8 -;; @0055 v56 = uadd_overflow_trap v54, v55, user65535 ; v55 = 8 -;; @0055 v57 = iconst.i64 8 -;; @0055 v58 = uadd_overflow_trap v56, v57, user65535 ; v57 = 8 -;; @0055 v59 = icmp ult v58, v53 -;; @0055 brif v59, block15, block14 +;; @0055 v53 = load.i64 notrap aligned readonly v0+40 +;; @0055 v54 = load.i64 notrap aligned readonly v0+48 +;; @0055 v55 = uextend.i64 v13 +;; @0055 v56 = iconst.i64 8 +;; @0055 v57 = uadd_overflow_trap v55, v56, user65535 ; v56 = 8 +;; @0055 v58 = iconst.i64 8 +;; @0055 v59 = uadd_overflow_trap v57, v58, user65535 ; v58 = 8 +;; @0055 v60 = icmp ult v59, v54 +;; @0055 brif v60, block15, block14 ;; ;; block14 cold: ;; @0055 trap user65535 ;; ;; block15: -;; @0055 v60 = iadd.i64 v52, v56 -;; @0055 store.i64 notrap aligned v48, v60 +;; @0055 v61 = iadd.i64 v53, v57 +;; @0055 store.i64 notrap aligned v49, v61 ;; @0055 jump block7 ;; ;; block7: @@ -145,113 +146,114 @@ ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned gv3+88 -;; gv5 = load.i32 notrap aligned gv3+96 +;; gv5 = load.i64 notrap aligned gv3+96 ;; sig0 = (i64 vmctx, i32 uext) system_v ;; fn0 = colocated u1:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): -;; @005e v4 = load.i32 notrap aligned v0+96 -;; @005e v5 = icmp uge v2, v4 -;; @005e v6 = uextend.i64 v2 -;; @005e v7 = load.i64 notrap aligned v0+88 -;; v63 = iconst.i64 2 -;; @005e v8 = ishl v6, v63 ; v63 = 2 -;; @005e v9 = iadd v7, v8 -;; @005e v10 = iconst.i64 0 -;; @005e v11 = select_spectre_guard v5, v10, v9 ; v10 = 0 -;; @005e v12 = load.i32 table_oob aligned table v11 -;; v64 = iconst.i32 0 -;; @005e v13 = icmp eq v3, v64 ; v64 = 0 -;; @005e brif v13, block3, block2 +;; @005e v4 = load.i64 notrap aligned v0+96 +;; @005e v5 = ireduce.i32 v4 +;; @005e v6 = icmp uge v2, v5 +;; @005e v7 = uextend.i64 v2 +;; @005e v8 = load.i64 notrap aligned v0+88 +;; v64 = iconst.i64 2 +;; @005e v9 = ishl v7, v64 ; v64 = 2 +;; @005e v10 = iadd v8, v9 +;; @005e v11 = iconst.i64 0 +;; @005e v12 = select_spectre_guard v6, v11, v10 ; v11 = 0 +;; @005e v13 = load.i32 table_oob aligned table v12 +;; v65 = iconst.i32 0 +;; @005e v14 = icmp eq v3, v65 ; v65 = 0 +;; @005e brif v14, block3, block2 ;; ;; block2: -;; @005e v15 = load.i64 notrap aligned readonly v0+40 -;; @005e v16 = load.i64 notrap aligned readonly v0+48 -;; @005e v17 = uextend.i64 v3 -;; @005e v18 = iconst.i64 8 -;; @005e v19 = uadd_overflow_trap v17, v18, user65535 ; v18 = 8 -;; @005e v20 = iconst.i64 8 -;; @005e v21 = uadd_overflow_trap v19, v20, user65535 ; v20 = 8 -;; @005e v22 = icmp ult v21, v16 -;; @005e brif v22, block9, block8 +;; @005e v16 = load.i64 notrap aligned readonly v0+40 +;; @005e v17 = load.i64 notrap aligned readonly v0+48 +;; @005e v18 = uextend.i64 v3 +;; @005e v19 = iconst.i64 8 +;; @005e v20 = uadd_overflow_trap v18, v19, user65535 ; v19 = 8 +;; @005e v21 = iconst.i64 8 +;; @005e v22 = uadd_overflow_trap v20, v21, user65535 ; v21 = 8 +;; @005e v23 = icmp ult v22, v17 +;; @005e brif v23, block9, block8 ;; ;; block8 cold: ;; @005e trap user65535 ;; ;; block9: -;; @005e v23 = iadd.i64 v15, v19 -;; @005e v24 = load.i64 notrap aligned v23 -;; v65 = iconst.i64 1 -;; @005e v25 = iadd v24, v65 ; v65 = 1 -;; @005e v27 = load.i64 notrap aligned readonly v0+40 -;; @005e v28 = load.i64 notrap aligned readonly v0+48 -;; @005e v29 = uextend.i64 v3 -;; @005e v30 = iconst.i64 8 -;; @005e v31 = uadd_overflow_trap v29, v30, user65535 ; v30 = 8 -;; @005e v32 = iconst.i64 8 -;; @005e v33 = uadd_overflow_trap v31, v32, user65535 ; v32 = 8 -;; @005e v34 = icmp ult v33, v28 -;; @005e brif v34, block11, block10 +;; @005e v24 = iadd.i64 v16, v20 +;; @005e v25 = load.i64 notrap aligned v24 +;; v66 = iconst.i64 1 +;; @005e v26 = iadd v25, v66 ; v66 = 1 +;; @005e v28 = load.i64 notrap aligned readonly v0+40 +;; @005e v29 = load.i64 notrap aligned readonly v0+48 +;; @005e v30 = uextend.i64 v3 +;; @005e v31 = iconst.i64 8 +;; @005e v32 = uadd_overflow_trap v30, v31, user65535 ; v31 = 8 +;; @005e v33 = iconst.i64 8 +;; @005e v34 = uadd_overflow_trap v32, v33, user65535 ; v33 = 8 +;; @005e v35 = icmp ult v34, v29 +;; @005e brif v35, block11, block10 ;; ;; block10 cold: ;; @005e trap user65535 ;; ;; block11: -;; @005e v35 = iadd.i64 v27, v31 -;; @005e store.i64 notrap aligned v25, v35 +;; @005e v36 = iadd.i64 v28, v32 +;; @005e store.i64 notrap aligned v26, v36 ;; @005e jump block3 ;; ;; block3: -;; @005e store.i32 table_oob aligned table v3, v11 -;; v66 = iconst.i32 0 -;; @005e v36 = icmp.i32 eq v12, v66 ; v66 = 0 -;; @005e brif v36, block7, block4 +;; @005e store.i32 table_oob aligned table v3, v12 +;; v67 = iconst.i32 0 +;; @005e v37 = icmp.i32 eq v13, v67 ; v67 = 0 +;; @005e brif v37, block7, block4 ;; ;; block4: -;; @005e v38 = load.i64 notrap aligned readonly v0+40 -;; @005e v39 = load.i64 notrap aligned readonly v0+48 -;; @005e v40 = uextend.i64 v12 -;; @005e v41 = iconst.i64 8 -;; @005e v42 = uadd_overflow_trap v40, v41, user65535 ; v41 = 8 -;; @005e v43 = iconst.i64 8 -;; @005e v44 = uadd_overflow_trap v42, v43, user65535 ; v43 = 8 -;; @005e v45 = icmp ult v44, v39 -;; @005e brif v45, block13, block12 +;; @005e v39 = load.i64 notrap aligned readonly v0+40 +;; @005e v40 = load.i64 notrap aligned readonly v0+48 +;; @005e v41 = uextend.i64 v13 +;; @005e v42 = iconst.i64 8 +;; @005e v43 = uadd_overflow_trap v41, v42, user65535 ; v42 = 8 +;; @005e v44 = iconst.i64 8 +;; @005e v45 = uadd_overflow_trap v43, v44, user65535 ; v44 = 8 +;; @005e v46 = icmp ult v45, v40 +;; @005e brif v46, block13, block12 ;; ;; block12 cold: ;; @005e trap user65535 ;; ;; block13: -;; @005e v46 = iadd.i64 v38, v42 -;; @005e v47 = load.i64 notrap aligned v46 -;; v67 = iconst.i64 -1 -;; @005e v48 = iadd v47, v67 ; v67 = -1 -;; v68 = iconst.i64 0 -;; @005e v49 = icmp eq v48, v68 ; v68 = 0 -;; @005e brif v49, block5, block6 +;; @005e v47 = iadd.i64 v39, v43 +;; @005e v48 = load.i64 notrap aligned v47 +;; v68 = iconst.i64 -1 +;; @005e v49 = iadd v48, v68 ; v68 = -1 +;; v69 = iconst.i64 0 +;; @005e v50 = icmp eq v49, v69 ; v69 = 0 +;; @005e brif v50, block5, block6 ;; ;; block5 cold: -;; @005e call fn0(v0, v12) +;; @005e call fn0(v0, v13) ;; @005e jump block7 ;; ;; block6: -;; @005e v52 = load.i64 notrap aligned readonly v0+40 -;; @005e v53 = load.i64 notrap aligned readonly v0+48 -;; @005e v54 = uextend.i64 v12 -;; @005e v55 = iconst.i64 8 -;; @005e v56 = uadd_overflow_trap v54, v55, user65535 ; v55 = 8 -;; @005e v57 = iconst.i64 8 -;; @005e v58 = uadd_overflow_trap v56, v57, user65535 ; v57 = 8 -;; @005e v59 = icmp ult v58, v53 -;; @005e brif v59, block15, block14 +;; @005e v53 = load.i64 notrap aligned readonly v0+40 +;; @005e v54 = load.i64 notrap aligned readonly v0+48 +;; @005e v55 = uextend.i64 v13 +;; @005e v56 = iconst.i64 8 +;; @005e v57 = uadd_overflow_trap v55, v56, user65535 ; v56 = 8 +;; @005e v58 = iconst.i64 8 +;; @005e v59 = uadd_overflow_trap v57, v58, user65535 ; v58 = 8 +;; @005e v60 = icmp ult v59, v54 +;; @005e brif v60, block15, block14 ;; ;; block14 cold: ;; @005e trap user65535 ;; ;; block15: -;; @005e v60 = iadd.i64 v52, v56 -;; @005e store.i64 notrap aligned v48, v60 +;; @005e v61 = iadd.i64 v53, v57 +;; @005e store.i64 notrap aligned v49, v61 ;; @005e jump block7 ;; ;; block7: diff --git a/tests/disas/typed-funcrefs.wat b/tests/disas/typed-funcrefs.wat index da55d039dfd7..9c5fb0fd5dfa 100644 --- a/tests/disas/typed-funcrefs.wat +++ b/tests/disas/typed-funcrefs.wat @@ -132,52 +132,52 @@ ;; gv2 = load.i64 notrap aligned gv1 ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 -;; sig0 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig0 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; sig1 = (i64 vmctx, i64, i32, i32, i32, i32) -> i32 tail ;; fn0 = colocated u1:9 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): ;; @0048 v12 = load.i64 notrap aligned readonly v0+88 -;; v66 = iconst.i64 8 -;; @0048 v14 = iadd v12, v66 ; v66 = 8 +;; v68 = iconst.i64 8 +;; @0048 v14 = iadd v12, v68 ; v68 = 8 ;; @0048 v17 = load.i64 table_oob aligned table v14 -;; v54 = iconst.i64 -2 -;; @0048 v18 = band v17, v54 ; v54 = -2 +;; v56 = iconst.i64 -2 +;; @0048 v18 = band v17, v56 ; v56 = -2 ;; @0048 brif v17, block3(v18), block2 ;; ;; block2 cold: ;; @003c v7 = iconst.i32 0 -;; @0046 v8 = iconst.i32 1 -;; @0048 v22 = call fn0(v0, v7, v8) ; v7 = 0, v8 = 1 -;; @0048 jump block3(v22) +;; v67 = iconst.i64 1 +;; @0048 v23 = call fn0(v0, v7, v67) ; v7 = 0, v67 = 1 +;; @0048 jump block3(v23) ;; ;; block3(v19: i64): -;; @004a v23 = load.i64 null_reference aligned readonly v19+8 -;; @004a v24 = load.i64 notrap aligned readonly v19+24 -;; @004a v25 = call_indirect sig1, v23(v24, v0, v2, v3, v4, v5) -;; v74 = iconst.i64 16 -;; @005b v38 = iadd.i64 v12, v74 ; v74 = 16 -;; @005b v41 = load.i64 table_oob aligned table v38 -;; v75 = iconst.i64 -2 -;; v76 = band v41, v75 ; v75 = -2 -;; @005b brif v41, block5(v76), block4 +;; @004a v24 = load.i64 null_reference aligned readonly v19+8 +;; @004a v25 = load.i64 notrap aligned readonly v19+24 +;; @004a v26 = call_indirect sig1, v24(v25, v0, v2, v3, v4, v5) +;; v76 = iconst.i64 16 +;; @005b v39 = iadd.i64 v12, v76 ; v76 = 16 +;; @005b v42 = load.i64 table_oob aligned table v39 +;; v77 = iconst.i64 -2 +;; v78 = band v42, v77 ; v77 = -2 +;; @005b brif v42, block5(v78), block4 ;; ;; block4 cold: -;; v77 = iconst.i32 0 -;; @0059 v32 = iconst.i32 2 -;; @005b v46 = call fn0(v0, v77, v32) ; v77 = 0, v32 = 2 -;; @005b jump block5(v46) +;; v79 = iconst.i32 0 +;; v75 = iconst.i64 2 +;; @005b v48 = call fn0(v0, v79, v75) ; v79 = 0, v75 = 2 +;; @005b jump block5(v48) ;; -;; block5(v43: i64): -;; @005d v47 = load.i64 null_reference aligned readonly v43+8 -;; @005d v48 = load.i64 notrap aligned readonly v43+24 -;; @005d v49 = call_indirect sig1, v47(v48, v0, v2, v3, v4, v5) +;; block5(v44: i64): +;; @005d v49 = load.i64 null_reference aligned readonly v44+8 +;; @005d v50 = load.i64 notrap aligned readonly v44+24 +;; @005d v51 = call_indirect sig1, v49(v50, v0, v2, v3, v4, v5) ;; @0066 jump block1 ;; ;; block1: -;; @0061 v51 = iadd.i32 v49, v25 -;; @0066 return v51 +;; @0061 v53 = iadd.i32 v51, v26 +;; @0066 return v53 ;; } ;; ;; function u0:2(i64 vmctx, i64, i32, i32, i32, i32) -> i32 tail { @@ -187,51 +187,51 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly gv3+88 ;; sig0 = (i64 vmctx, i64, i32, i32, i32, i32) -> i32 tail -;; sig1 = (i64 vmctx, i32 uext, i32 uext) -> i64 system_v +;; sig1 = (i64 vmctx, i32 uext, i64) -> i64 system_v ;; fn0 = colocated u1:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): ;; @0075 v12 = load.i64 notrap aligned readonly v0+88 -;; v66 = iconst.i64 8 -;; @0075 v14 = iadd v12, v66 ; v66 = 8 +;; v68 = iconst.i64 8 +;; @0075 v14 = iadd v12, v68 ; v68 = 8 ;; @0075 v17 = load.i64 table_oob aligned table v14 -;; v54 = iconst.i64 -2 -;; @0075 v18 = band v17, v54 ; v54 = -2 +;; v56 = iconst.i64 -2 +;; @0075 v18 = band v17, v56 ; v56 = -2 ;; @0075 brif v17, block3(v18), block2 ;; ;; block2 cold: ;; @0069 v7 = iconst.i32 0 -;; @0073 v8 = iconst.i32 1 -;; @0075 v22 = call fn0(v0, v7, v8) ; v7 = 0, v8 = 1 -;; @0075 jump block3(v22) +;; v67 = iconst.i64 1 +;; @0075 v23 = call fn0(v0, v7, v67) ; v7 = 0, v67 = 1 +;; @0075 jump block3(v23) ;; ;; block3(v19: i64): -;; @0075 v23 = load.i64 icall_null aligned readonly v19+8 -;; @0075 v24 = load.i64 notrap aligned readonly v19+24 -;; @0075 v25 = call_indirect sig0, v23(v24, v0, v2, v3, v4, v5) -;; v74 = iconst.i64 16 -;; @0087 v38 = iadd.i64 v12, v74 ; v74 = 16 -;; @0087 v41 = load.i64 table_oob aligned table v38 -;; v75 = iconst.i64 -2 -;; v76 = band v41, v75 ; v75 = -2 -;; @0087 brif v41, block5(v76), block4 +;; @0075 v24 = load.i64 icall_null aligned readonly v19+8 +;; @0075 v25 = load.i64 notrap aligned readonly v19+24 +;; @0075 v26 = call_indirect sig0, v24(v25, v0, v2, v3, v4, v5) +;; v76 = iconst.i64 16 +;; @0087 v39 = iadd.i64 v12, v76 ; v76 = 16 +;; @0087 v42 = load.i64 table_oob aligned table v39 +;; v77 = iconst.i64 -2 +;; v78 = band v42, v77 ; v77 = -2 +;; @0087 brif v42, block5(v78), block4 ;; ;; block4 cold: -;; v77 = iconst.i32 0 -;; @0085 v32 = iconst.i32 2 -;; @0087 v46 = call fn0(v0, v77, v32) ; v77 = 0, v32 = 2 -;; @0087 jump block5(v46) +;; v79 = iconst.i32 0 +;; v75 = iconst.i64 2 +;; @0087 v48 = call fn0(v0, v79, v75) ; v79 = 0, v75 = 2 +;; @0087 jump block5(v48) ;; -;; block5(v43: i64): -;; @0087 v47 = load.i64 icall_null aligned readonly v43+8 -;; @0087 v48 = load.i64 notrap aligned readonly v43+24 -;; @0087 v49 = call_indirect sig0, v47(v48, v0, v2, v3, v4, v5) +;; block5(v44: i64): +;; @0087 v49 = load.i64 icall_null aligned readonly v44+8 +;; @0087 v50 = load.i64 notrap aligned readonly v44+24 +;; @0087 v51 = call_indirect sig0, v49(v50, v0, v2, v3, v4, v5) ;; @0091 jump block1 ;; ;; block1: -;; @008c v51 = iadd.i32 v49, v25 -;; @0091 return v51 +;; @008c v53 = iadd.i32 v51, v26 +;; @0091 return v53 ;; } ;; ;; function u0:3(i64 vmctx, i64, i32, i32, i32, i32) -> i32 tail { diff --git a/tests/disas/winch/aarch64/br/br_jump.wat b/tests/disas/winch/aarch64/br/br_jump.wat index 6f70315187fa..88ef3483fec6 100644 --- a/tests/disas/winch/aarch64/br/br_jump.wat +++ b/tests/disas/winch/aarch64/br/br_jump.wat @@ -25,14 +25,14 @@ ;; mov x16, #0 ;; stur x16, [x28] ;; ldur w16, [x28, #4] -;; sub sp, sp, #8 +;; sub sp, sp, #4 ;; mov x28, sp -;; stur x16, [x28, #8] -;; ldur w16, [x28, #0xc] -;; sub sp, sp, #8 +;; stur w16, [x28] +;; ldur w16, [x28, #8] +;; sub sp, sp, #4 ;; mov x28, sp -;; stur x16, [x28, #8] -;; add sp, sp, #8 +;; stur w16, [x28] +;; add sp, sp, #4 ;; mov x28, sp ;; b #0x38 ;; 54: add sp, sp, #0x18 diff --git a/tests/disas/winch/aarch64/params/multi_values.wat b/tests/disas/winch/aarch64/params/multi_values.wat new file mode 100644 index 000000000000..bb059c6daa18 --- /dev/null +++ b/tests/disas/winch/aarch64/params/multi_values.wat @@ -0,0 +1,55 @@ +;;! target = "aarch64" +;;! test = "winch" + +(module + (func (export "run") (param i32 i32 f32 f32) (result i32 i32 f32 f32) + local.get 0 + local.get 1 + local.get 2 + local.get 3 + ) +) +;; wasm[0]::function[0]: +;; stp x29, x30, [sp, #-0x10]! +;; mov x29, sp +;; mov x28, sp +;; mov x9, x0 +;; sub sp, sp, #0x28 +;; mov x28, sp +;; stur x0, [x28, #0x20] +;; stur x1, [x28, #0x18] +;; stur w2, [x28, #0x14] +;; stur w3, [x28, #0x10] +;; stur s0, [x28, #0xc] +;; stur s1, [x28, #8] +;; stur x4, [x28] +;; ldur s0, [x28, #8] +;; ldur w16, [x28, #0x14] +;; sub sp, sp, #4 +;; mov x28, sp +;; stur w16, [x28] +;; ldur w16, [x28, #0x14] +;; sub sp, sp, #4 +;; mov x28, sp +;; stur w16, [x28] +;; ldur s31, [x28, #0x14] +;; sub sp, sp, #4 +;; mov x28, sp +;; stur s31, [x28] +;; ldur x0, [x28, #0xc] +;; ldur s31, [x28] +;; add sp, sp, #4 +;; mov x28, sp +;; stur s31, [x0] +;; ldur w16, [x28] +;; add sp, sp, #4 +;; mov x28, sp +;; stur w16, [x0, #4] +;; ldur w16, [x28] +;; add sp, sp, #4 +;; mov x28, sp +;; stur w16, [x0, #8] +;; add sp, sp, #0x28 +;; mov x28, sp +;; ldp x29, x30, [sp], #0x10 +;; ret diff --git a/tests/disas/winch/x64/call_indirect/call_indirect.wat b/tests/disas/winch/x64/call_indirect/call_indirect.wat index 56dd4208cd1d..b5e7b9919d6a 100644 --- a/tests/disas/winch/x64/call_indirect/call_indirect.wat +++ b/tests/disas/winch/x64/call_indirect/call_indirect.wat @@ -37,7 +37,7 @@ ;; movq (%r11), %r11 ;; addq $0x30, %r11 ;; cmpq %rsp, %r11 -;; ja 0x1da +;; ja 0x1de ;; 1b: movq %rdi, %r14 ;; subq $0x20, %rsp ;; movq %rdi, 0x18(%rsp) @@ -50,17 +50,17 @@ ;; testl %eax, %eax ;; je 0x52 ;; 48: movl $1, %eax -;; jmp 0x1d4 +;; jmp 0x1d8 ;; 52: movl 0xc(%rsp), %eax ;; subl $2, %eax ;; subq $4, %rsp ;; movl %eax, (%rsp) ;; movl $0, %ecx ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0x1dc -;; 73: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0x1e0 +;; 75: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -69,27 +69,27 @@ ;; cmovaeq %rsi, %rdx ;; movq (%rdx), %rax ;; testq %rax, %rax -;; jne 0xc4 -;; 96: subq $4, %rsp +;; jne 0xc6 +;; 98: subq $4, %rsp ;; movl %ecx, (%rsp) ;; subq $8, %rsp ;; movq %r14, %rdi ;; movl $0, %esi ;; movl 8(%rsp), %edx -;; callq 0x2ef +;; callq 0x2f3 ;; addq $8, %rsp ;; addq $4, %rsp ;; movq 0x1c(%rsp), %r14 -;; jmp 0xc8 -;; c4: andq $0xfffffffffffffffe, %rax +;; jmp 0xca +;; c6: andq $0xfffffffffffffffe, %rax ;; testq %rax, %rax -;; je 0x1de -;; d1: movq 0x50(%r14), %r11 +;; je 0x1e2 +;; d3: movq 0x50(%r14), %r11 ;; movl (%r11), %ecx ;; movl 0x10(%rax), %edx ;; cmpl %edx, %ecx -;; jne 0x1e0 -;; e3: pushq %rax +;; jne 0x1e4 +;; e5: pushq %rax ;; popq %rcx ;; movq 0x18(%rcx), %r8 ;; movq 8(%rcx), %rbx @@ -109,10 +109,10 @@ ;; movl %ecx, (%rsp) ;; movl $0, %ecx ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0x1e2 -;; 132: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0x1e6 +;; 136: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -121,27 +121,27 @@ ;; cmovaeq %rsi, %rdx ;; movq (%rdx), %rax ;; testq %rax, %rax -;; jne 0x183 -;; 155: subq $4, %rsp +;; jne 0x187 +;; 159: subq $4, %rsp ;; movl %ecx, (%rsp) ;; subq $4, %rsp ;; movq %r14, %rdi ;; movl $0, %esi ;; movl 4(%rsp), %edx -;; callq 0x2ef +;; callq 0x2f3 ;; addq $4, %rsp ;; addq $4, %rsp ;; movq 0x20(%rsp), %r14 -;; jmp 0x187 -;; 183: andq $0xfffffffffffffffe, %rax +;; jmp 0x18b +;; 187: andq $0xfffffffffffffffe, %rax ;; testq %rax, %rax -;; je 0x1e4 -;; 190: movq 0x50(%r14), %r11 +;; je 0x1e8 +;; 194: movq 0x50(%r14), %r11 ;; movl (%r11), %ecx ;; movl 0x10(%rax), %edx ;; cmpl %edx, %ecx -;; jne 0x1e6 -;; 1a2: pushq %rax +;; jne 0x1ea +;; 1a6: pushq %rax ;; popq %rcx ;; movq 0x18(%rcx), %r8 ;; movq 8(%rcx), %rbx @@ -160,10 +160,10 @@ ;; addq $0x20, %rsp ;; popq %rbp ;; retq -;; 1da: ud2 -;; 1dc: ud2 ;; 1de: ud2 ;; 1e0: ud2 ;; 1e2: ud2 ;; 1e4: ud2 ;; 1e6: ud2 +;; 1e8: ud2 +;; 1ea: ud2 diff --git a/tests/disas/winch/x64/call_indirect/local_arg.wat b/tests/disas/winch/x64/call_indirect/local_arg.wat index c90cd6dd26d2..80e9c6b6ffc6 100644 --- a/tests/disas/winch/x64/call_indirect/local_arg.wat +++ b/tests/disas/winch/x64/call_indirect/local_arg.wat @@ -42,7 +42,7 @@ ;; movq (%r11), %r11 ;; addq $0x30, %r11 ;; cmpq %rsp, %r11 -;; ja 0x130 +;; ja 0x132 ;; 5b: movq %rdi, %r14 ;; subq $0x20, %rsp ;; movq %rdi, 0x18(%rsp) @@ -53,10 +53,10 @@ ;; movl %r11d, (%rsp) ;; movl $0, %ecx ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0x132 -;; 95: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0x134 +;; 97: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -65,27 +65,27 @@ ;; cmovaeq %rsi, %rdx ;; movq (%rdx), %rax ;; testq %rax, %rax -;; jne 0xe6 -;; b8: subq $4, %rsp +;; jne 0xe8 +;; ba: subq $4, %rsp ;; movl %ecx, (%rsp) ;; subq $8, %rsp ;; movq %r14, %rdi ;; movl $0, %esi ;; movl 8(%rsp), %edx -;; callq 0x30d +;; callq 0x30f ;; addq $8, %rsp ;; addq $4, %rsp ;; movq 0x1c(%rsp), %r14 -;; jmp 0xea -;; e6: andq $0xfffffffffffffffe, %rax +;; jmp 0xec +;; e8: andq $0xfffffffffffffffe, %rax ;; testq %rax, %rax -;; je 0x134 -;; f3: movq 0x50(%r14), %r11 +;; je 0x136 +;; f5: movq 0x50(%r14), %r11 ;; movl (%r11), %ecx ;; movl 0x10(%rax), %edx ;; cmpl %edx, %ecx -;; jne 0x136 -;; 105: movq 0x18(%rax), %rbx +;; jne 0x138 +;; 107: movq 0x18(%rax), %rbx ;; movq 8(%rax), %rcx ;; subq $0xc, %rsp ;; movq %rbx, %rdi @@ -98,7 +98,7 @@ ;; addq $0x20, %rsp ;; popq %rbp ;; retq -;; 130: ud2 ;; 132: ud2 ;; 134: ud2 ;; 136: ud2 +;; 138: ud2 diff --git a/tests/disas/winch/x64/table/fill.wat b/tests/disas/winch/x64/table/fill.wat index 65ccb3e59b89..43c45444ef6f 100644 --- a/tests/disas/winch/x64/table/fill.wat +++ b/tests/disas/winch/x64/table/fill.wat @@ -78,7 +78,7 @@ ;; movq (%r11), %r11 ;; addq $0x40, %r11 ;; cmpq %rsp, %r11 -;; ja 0x1d0 +;; ja 0x1d2 ;; db: movq %rdi, %r14 ;; subq $0x30, %rsp ;; movq %rdi, 0x28(%rsp) @@ -94,10 +94,10 @@ ;; movl (%rsp), %ecx ;; addq $4, %rsp ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0x1d2 -;; 12c: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0x1d4 +;; 12e: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -106,19 +106,19 @@ ;; cmovaeq %rsi, %rdx ;; movq (%rdx), %rax ;; testq %rax, %rax -;; jne 0x17d -;; 14f: subq $4, %rsp +;; jne 0x17f +;; 151: subq $4, %rsp ;; movl %ecx, (%rsp) ;; subq $0xc, %rsp ;; movq %r14, %rdi ;; movl $0, %esi ;; movl 0xc(%rsp), %edx -;; callq 0x4c1 +;; callq 0x4c3 ;; addq $0xc, %rsp ;; addq $4, %rsp ;; movq 0x28(%rsp), %r14 -;; jmp 0x181 -;; 17d: andq $0xfffffffffffffffe, %rax +;; jmp 0x183 +;; 17f: andq $0xfffffffffffffffe, %rax ;; movq %rax, 0xc(%rsp) ;; movl 0x1c(%rsp), %r11d ;; subq $4, %rsp @@ -139,5 +139,5 @@ ;; addq $0x30, %rsp ;; popq %rbp ;; retq -;; 1d0: ud2 ;; 1d2: ud2 +;; 1d4: ud2 diff --git a/tests/disas/winch/x64/table/get.wat b/tests/disas/winch/x64/table/get.wat index 6639318329e4..4facb29c3c50 100644 --- a/tests/disas/winch/x64/table/get.wat +++ b/tests/disas/winch/x64/table/get.wat @@ -34,7 +34,7 @@ ;; movq (%r11), %r11 ;; addq $0x30, %r11 ;; cmpq %rsp, %r11 -;; ja 0xed +;; ja 0xef ;; 5b: movq %rdi, %r14 ;; subq $0x20, %rsp ;; movq %rdi, 0x18(%rsp) @@ -46,10 +46,10 @@ ;; movl (%rsp), %ecx ;; addq $4, %rsp ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0xef -;; 92: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0xf1 +;; 94: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -58,21 +58,21 @@ ;; cmovaeq %rsi, %rdx ;; movq (%rdx), %rax ;; testq %rax, %rax -;; jne 0xe3 -;; b5: subq $4, %rsp +;; jne 0xe5 +;; b7: subq $4, %rsp ;; movl %ecx, (%rsp) ;; subq $0xc, %rsp ;; movq %r14, %rdi ;; movl $0, %esi ;; movl 0xc(%rsp), %edx -;; callq 0x2da +;; callq 0x2dc ;; addq $0xc, %rsp ;; addq $4, %rsp ;; movq 0x18(%rsp), %r14 -;; jmp 0xe7 -;; e3: andq $0xfffffffffffffffe, %rax +;; jmp 0xe9 +;; e5: andq $0xfffffffffffffffe, %rax ;; addq $0x20, %rsp ;; popq %rbp ;; retq -;; ed: ud2 ;; ef: ud2 +;; f1: ud2 diff --git a/tests/disas/winch/x64/table/init_copy_drop.wat b/tests/disas/winch/x64/table/init_copy_drop.wat index 25183063e34d..0bffbff0a972 100644 --- a/tests/disas/winch/x64/table/init_copy_drop.wat +++ b/tests/disas/winch/x64/table/init_copy_drop.wat @@ -142,11 +142,11 @@ ;; movl $7, %ecx ;; movl $0, %r8d ;; movl $4, %r9d -;; callq 0x8cd +;; callq 0x8cf ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $1, %esi -;; callq 0x916 +;; callq 0x912 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -154,11 +154,11 @@ ;; movl $0xf, %ecx ;; movl $1, %r8d ;; movl $3, %r9d -;; callq 0x8cd +;; callq 0x8cf ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $3, %esi -;; callq 0x916 +;; callq 0x912 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -166,7 +166,7 @@ ;; movl $0x14, %ecx ;; movl $0xf, %r8d ;; movl $5, %r9d -;; callq 0x955 +;; callq 0x951 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -174,7 +174,7 @@ ;; movl $0x15, %ecx ;; movl $0x1d, %r8d ;; movl $1, %r9d -;; callq 0x955 +;; callq 0x951 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -182,7 +182,7 @@ ;; movl $0x18, %ecx ;; movl $0xa, %r8d ;; movl $1, %r9d -;; callq 0x955 +;; callq 0x951 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -190,7 +190,7 @@ ;; movl $0xd, %ecx ;; movl $0xb, %r8d ;; movl $4, %r9d -;; callq 0x955 +;; callq 0x951 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -198,7 +198,7 @@ ;; movl $0x13, %ecx ;; movl $0x14, %r8d ;; movl $5, %r9d -;; callq 0x955 +;; callq 0x951 ;; movq 8(%rsp), %r14 ;; addq $0x10, %rsp ;; popq %rbp @@ -212,7 +212,7 @@ ;; movq (%r11), %r11 ;; addq $0x30, %r11 ;; cmpq %rsp, %r11 -;; ja 0x395 +;; ja 0x397 ;; 2cb: movq %rdi, %r14 ;; subq $0x20, %rsp ;; movq %rdi, 0x18(%rsp) @@ -224,10 +224,10 @@ ;; movl (%rsp), %ecx ;; addq $4, %rsp ;; movq %r14, %rdx -;; movl 0xd8(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0x397 -;; 305: movl %ecx, %r11d +;; movq 0xd8(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0x399 +;; 307: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0xd0(%rdx), %rdx ;; movq %rdx, %rsi @@ -236,27 +236,27 @@ ;; cmovaeq %rsi, %rdx ;; movq (%rdx), %rax ;; testq %rax, %rax -;; jne 0x359 -;; 32b: subq $4, %rsp +;; jne 0x35b +;; 32d: subq $4, %rsp ;; movl %ecx, (%rsp) ;; subq $0xc, %rsp ;; movq %r14, %rdi ;; movl $0, %esi ;; movl 0xc(%rsp), %edx -;; callq 0x99e +;; callq 0x994 ;; addq $0xc, %rsp ;; addq $4, %rsp ;; movq 0x18(%rsp), %r14 -;; jmp 0x35d -;; 359: andq $0xfffffffffffffffe, %rax +;; jmp 0x35f +;; 35b: andq $0xfffffffffffffffe, %rax ;; testq %rax, %rax -;; je 0x399 -;; 366: movq 0x50(%r14), %r11 +;; je 0x39b +;; 368: movq 0x50(%r14), %r11 ;; movl (%r11), %ecx ;; movl 0x10(%rax), %edx ;; cmpl %edx, %ecx -;; jne 0x39b -;; 378: pushq %rax +;; jne 0x39d +;; 37a: pushq %rax ;; popq %rcx ;; movq 0x18(%rcx), %rbx ;; movq 8(%rcx), %rdx @@ -267,7 +267,7 @@ ;; addq $0x20, %rsp ;; popq %rbp ;; retq -;; 395: ud2 ;; 397: ud2 ;; 399: ud2 ;; 39b: ud2 +;; 39d: ud2 diff --git a/tests/disas/winch/x64/table/set.wat b/tests/disas/winch/x64/table/set.wat index 9c61a637a365..3f0567fd777c 100644 --- a/tests/disas/winch/x64/table/set.wat +++ b/tests/disas/winch/x64/table/set.wat @@ -39,7 +39,7 @@ ;; movq (%r11), %r11 ;; addq $0x20, %r11 ;; cmpq %rsp, %r11 -;; ja 0xae +;; ja 0xb0 ;; 5b: movq %rdi, %r14 ;; subq $0x20, %rsp ;; movq %rdi, 0x18(%rsp) @@ -49,10 +49,10 @@ ;; movq (%rsp), %rax ;; movl 0xc(%rsp), %ecx ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0xb0 -;; 8a: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0xb2 +;; 8c: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -64,8 +64,8 @@ ;; addq $0x20, %rsp ;; popq %rbp ;; retq -;; ae: ud2 ;; b0: ud2 +;; b2: ud2 ;; ;; wasm[0]::function[2]: ;; pushq %rbp @@ -74,7 +74,7 @@ ;; movq (%r11), %r11 ;; addq $0x30, %r11 ;; cmpq %rsp, %r11 -;; ja 0x1b1 +;; ja 0x1b5 ;; db: movq %rdi, %r14 ;; subq $0x20, %rsp ;; movq %rdi, 0x18(%rsp) @@ -90,10 +90,10 @@ ;; movl (%rsp), %ecx ;; addq $4, %rsp ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0x1b3 -;; 123: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0x1b7 +;; 125: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -102,26 +102,26 @@ ;; cmovaeq %rsi, %rdx ;; movq (%rdx), %rax ;; testq %rax, %rax -;; jne 0x174 -;; 146: subq $4, %rsp +;; jne 0x176 +;; 148: subq $4, %rsp ;; movl %ecx, (%rsp) ;; subq $8, %rsp ;; movq %r14, %rdi ;; movl $0, %esi ;; movl 8(%rsp), %edx -;; callq 0x496 +;; callq 0x49a ;; addq $8, %rsp ;; addq $4, %rsp ;; movq 0x1c(%rsp), %r14 -;; jmp 0x178 -;; 174: andq $0xfffffffffffffffe, %rax +;; jmp 0x17a +;; 176: andq $0xfffffffffffffffe, %rax ;; movl (%rsp), %ecx ;; addq $4, %rsp ;; movq %r14, %rdx -;; movl 0x60(%rdx), %ebx -;; cmpl %ebx, %ecx -;; jae 0x1b5 -;; 18d: movl %ecx, %r11d +;; movq 0x60(%rdx), %rbx +;; cmpq %rbx, %rcx +;; jae 0x1b9 +;; 191: movq %rcx, %r11 ;; imulq $8, %r11, %r11 ;; movq 0x58(%rdx), %rdx ;; movq %rdx, %rsi @@ -133,6 +133,6 @@ ;; addq $0x20, %rsp ;; popq %rbp ;; retq -;; 1b1: ud2 -;; 1b3: ud2 ;; 1b5: ud2 +;; 1b7: ud2 +;; 1b9: ud2 diff --git a/tests/disas/winch/x64/table/size.wat b/tests/disas/winch/x64/table/size.wat index 212ee6ce1144..989b897196fd 100644 --- a/tests/disas/winch/x64/table/size.wat +++ b/tests/disas/winch/x64/table/size.wat @@ -18,7 +18,7 @@ ;; movq %rdi, 8(%rsp) ;; movq %rsi, (%rsp) ;; movq %r14, %r11 -;; movl 0x60(%r11), %eax +;; movq 0x60(%r11), %rax ;; addq $0x10, %rsp ;; popq %rbp ;; retq diff --git a/tests/misc_testsuite/component-model/import.wast b/tests/misc_testsuite/component-model/import.wast index 3e51d536311c..20688efe9b77 100644 --- a/tests/misc_testsuite/component-model/import.wast +++ b/tests/misc_testsuite/component-model/import.wast @@ -4,7 +4,7 @@ (export "x" (func $f))) "component export `x` is a reexport of an imported function which is not implemented") -(assert_invalid +(assert_unlinkable (component (import "host-return-two" (instance)) ) diff --git a/tests/misc_testsuite/component-model/instance.wast b/tests/misc_testsuite/component-model/instance.wast index 69f4f4917169..fe3cdedb48f1 100644 --- a/tests/misc_testsuite/component-model/instance.wast +++ b/tests/misc_testsuite/component-model/instance.wast @@ -267,3 +267,61 @@ (export "i" (instance $i)) ) + +(component definition $C1 + (type $r1 (resource (rep i32))) + (export "r" (type $r1)) +) +(component definition $C2 + (type $r1 (resource (rep i32))) + (export "r" (type $r1)) +) + +(component instance $I1 $C1) +(component instance $I2 $C1) +(component instance $I3 $C2) +(component instance $I4 $C2) + +;; all instances have different resource types +(assert_unlinkable + (component + (import "I1" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I2" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I1" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I3" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I1" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I4" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I2" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I3" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I2" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I4" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") +(assert_unlinkable + (component + (import "I3" (instance $i1 (export "r" (type (sub resource))))) + (alias export $i1 "r" (type $r)) + (import "I4" (instance $i2 (export "r" (type (eq $r))))) + ) + "mismatched resource types") diff --git a/tests/misc_testsuite/function-references/instance.wast b/tests/misc_testsuite/function-references/instance.wast new file mode 100644 index 000000000000..004c8ee95d87 --- /dev/null +++ b/tests/misc_testsuite/function-references/instance.wast @@ -0,0 +1,121 @@ +;; Instantiation is generative + +(module definition $M + (global (export "glob") (mut i32) (i32.const 0)) + (table (export "tab") 10 funcref (ref.null func)) + (memory (export "mem") 1) +) + +(module instance $I1 $M) +(module instance $I2 $M) +(register "I1" $I1) +(register "I2" $I2) + +(module + (import "I1" "glob" (global $glob1 (mut i32))) + (import "I2" "glob" (global $glob2 (mut i32))) + (import "I1" "tab" (table $tab1 10 funcref)) + (import "I2" "tab" (table $tab2 10 funcref)) + (import "I1" "mem" (memory $mem1 1)) + (import "I2" "mem" (memory $mem2 1)) + + (func $f) + (elem declare func $f) + + (func (export "glob") (result i32) + (global.set $glob1 (i32.const 1)) + (global.get $glob2) + ) + (func (export "tab") (result funcref) + (table.set $tab1 (i32.const 0) (ref.func $f)) + (table.get $tab2 (i32.const 0)) + ) + (func (export "mem") (result i32) + (i32.store $mem1 (i32.const 0) (i32.const 1)) + (i32.load $mem2 (i32.const 0)) + ) +) + +(assert_return (invoke "glob") (i32.const 0)) +(assert_return (invoke "tab") (ref.null)) +(assert_return (invoke "mem") (i32.const 0)) + + +;; Import is not generative + +(module + (import "I1" "glob" (global $glob1 (mut i32))) + (import "I1" "glob" (global $glob2 (mut i32))) + (import "I1" "tab" (table $tab1 10 funcref)) + (import "I1" "tab" (table $tab2 10 funcref)) + (import "I1" "mem" (memory $mem1 1)) + (import "I1" "mem" (memory $mem2 1)) + + (func $f) + (elem declare func $f) + + (func (export "glob") (result i32) + (global.set $glob1 (i32.const 1)) + (global.get $glob2) + ) + (func (export "tab") (result funcref) + (table.set $tab1 (i32.const 0) (ref.func $f)) + (table.get $tab2 (i32.const 0)) + ) + (func (export "mem") (result i32) + (i32.store $mem1 (i32.const 0) (i32.const 1)) + (i32.load $mem2 (i32.const 0)) + ) +) + +(assert_return (invoke "glob") (i32.const 1)) +(assert_return (invoke "tab") (ref.func)) +(assert_return (invoke "mem") (i32.const 1)) + + +;; Export is not generative + +(module definition $N + (global $glob (mut i32) (i32.const 0)) + (table $tab 10 funcref (ref.null func)) + (memory $mem 1) + + (export "glob1" (global $glob)) + (export "glob2" (global $glob)) + (export "tab1" (table $tab)) + (export "tab2" (table $tab)) + (export "mem1" (memory $mem)) + (export "mem2" (memory $mem)) +) + +(module instance $I $N) +(register "I" $I) + +(module + (import "I" "glob1" (global $glob1 (mut i32))) + (import "I" "glob2" (global $glob2 (mut i32))) + (import "I" "tab1" (table $tab1 10 funcref)) + (import "I" "tab2" (table $tab2 10 funcref)) + (import "I" "mem1" (memory $mem1 1)) + (import "I" "mem2" (memory $mem2 1)) + + (func $f) + (elem declare func $f) + + (func (export "glob") (result i32) + (global.set $glob1 (i32.const 1)) + (global.get $glob2) + ) + (func (export "tab") (result funcref) + (table.set $tab1 (i32.const 0) (ref.func $f)) + (table.get $tab2 (i32.const 0)) + ) + (func (export "mem") (result i32) + (i32.store $mem1 (i32.const 0) (i32.const 1)) + (i32.load $mem2 (i32.const 0)) + ) +) + +(assert_return (invoke "glob") (i32.const 1)) +(assert_return (invoke "tab") (ref.func)) +(assert_return (invoke "mem") (i32.const 1)) diff --git a/tests/rlimited-memory.rs b/tests/rlimited-memory.rs index 1fe77f6a521b..3ee15a056106 100644 --- a/tests/rlimited-memory.rs +++ b/tests/rlimited-memory.rs @@ -28,9 +28,9 @@ impl ResourceLimiter for MemoryGrowFailureDetector { } fn table_growing( &mut self, - _current: u32, - _desired: u32, - _maximum: Option, + _current: usize, + _desired: usize, + _maximum: Option, ) -> Result { Ok(true) } diff --git a/tests/wast.rs b/tests/wast.rs index 6f4e98575a09..738503694702 100644 --- a/tests/wast.rs +++ b/tests/wast.rs @@ -238,17 +238,6 @@ fn should_fail(test: &Path, strategy: Strategy) -> bool { if part == "memory64" { if [ - // Wasmtime doesn't implement the table64 extension yet. - "call_indirect.wast", - "table_copy.wast", - "table_get.wast", - "table_set.wast", - "table_fill.wast", - "table.wast", - "table_init.wast", - "table_copy_mixed.wast", - "table_grow.wast", - "table_size.wast", // wasmtime doesn't implement exceptions yet "imports.wast", "ref_null.wast", @@ -282,6 +271,10 @@ fn should_fail(test: &Path, strategy: Strategy) -> bool { { return true; } + // Tag linking is broken in the baseline implementation. + if cfg!(feature = "wasmfx_baseline") && test.ends_with("linking_tags.wast") { + return true; + } } } @@ -298,12 +291,14 @@ fn run_wast(wast: &Path, strategy: Strategy, pooling: bool) -> anyhow::Result<() let wast = Path::new(wast); + let misc = feature_found(wast, "misc_testsuite"); let memory64 = feature_found(wast, "memory64"); let custom_page_sizes = feature_found(wast, "custom-page-sizes"); let multi_memory = feature_found(wast, "multi-memory") || feature_found(wast, "component-model") || custom_page_sizes - || memory64; + || memory64 + || misc; let threads = feature_found(wast, "threads"); let typed_continuations = feature_found(wast, "typed-continuations"); let exceptions = feature_found(wast, "exception-handling") || typed_continuations; diff --git a/winch/codegen/Cargo.toml b/winch/codegen/Cargo.toml index b5f0f2709f77..724671a58b31 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.23.0" +version = "0.24.0" edition.workspace = true rust-version.workspace = true diff --git a/winch/codegen/src/codegen/builtin.rs b/winch/codegen/src/codegen/builtin.rs index eb0ad65a2899..a7a7de748bb6 100644 --- a/winch/codegen/src/codegen/builtin.rs +++ b/winch/codegen/src/codegen/builtin.rs @@ -127,6 +127,10 @@ macro_rules! declare_function_sig { WasmValType::I32 } + fn u8(&self) -> WasmValType { + WasmValType::I32 + } + fn f32(&self) -> WasmValType { WasmValType::F32 } diff --git a/winch/codegen/src/codegen/env.rs b/winch/codegen/src/codegen/env.rs index 772aff519080..baca13fc16a6 100644 --- a/winch/codegen/src/codegen/env.rs +++ b/winch/codegen/src/codegen/env.rs @@ -298,10 +298,9 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> { import_from, current_length_offset, style, - ty: if plan.memory.memory64 { - WasmValType::I64 - } else { - WasmValType::I32 + ty: match plan.memory.idx_type { + wasmtime_environ::IndexType::I32 => WasmValType::I32, + wasmtime_environ::IndexType::I64 => WasmValType::I64, }, min_size, max_size, diff --git a/winch/codegen/src/isa/aarch64/abi.rs b/winch/codegen/src/isa/aarch64/abi.rs index e142b036bd96..0bfce3e61498 100644 --- a/winch/codegen/src/isa/aarch64/abi.rs +++ b/winch/codegen/src/isa/aarch64/abi.rs @@ -43,6 +43,7 @@ impl ABI for Aarch64ABI { ty, stack_offset, &mut params_index_env, + call_conv, ParamsOrReturns::Params, ) }); @@ -64,6 +65,7 @@ impl ABI for Aarch64ABI { ty, stack_offset, &mut returns_index_env, + call_conv, ParamsOrReturns::Returns, ) }) @@ -108,6 +110,7 @@ impl Aarch64ABI { wasm_arg: &WasmValType, stack_offset: u32, index_env: &mut RegIndexEnv, + call_conv: &CallingConvention, params_or_returns: ParamsOrReturns, ) -> (ABIOperand, u32) { let (reg, ty) = match wasm_arg { @@ -128,9 +131,15 @@ impl Aarch64ABI { let slot_size = Self::stack_slot_size(); // Stack slots for parameters are aligned to a fixed slot size, // in the case of Aarch64, 8 bytes. - // Stack slots for returns are type-size aligned. + // For the non-default calling convention, stack slots for + // return values are type-sized aligned. + // For the default calling convention, we don't type-size align, + // given that results on the stack must match spills generated + // from within the compiler, which are not type-size aligned. let next_stack = if params_or_returns == ParamsOrReturns::Params { align_to(stack_offset, slot_size as u32) + (slot_size as u32) + } else if call_conv.is_default() { + stack_offset + (ty_size as u32) } else { align_to(stack_offset, ty_size as u32) + (ty_size as u32) }; diff --git a/winch/codegen/src/isa/aarch64/masm.rs b/winch/codegen/src/isa/aarch64/masm.rs index aa519f6df99c..8c9c7df04420 100644 --- a/winch/codegen/src/isa/aarch64/masm.rs +++ b/winch/codegen/src/isa/aarch64/masm.rs @@ -1,6 +1,6 @@ use super::{abi::Aarch64ABI, address::Address, asm::Assembler, regs}; use crate::{ - abi::{self, local::LocalSlot}, + abi::local::LocalSlot, codegen::{ptr_type_from_ptr_size, CodeGenContext, FuncEnv}, isa::reg::Reg, masm::{ @@ -113,12 +113,12 @@ impl Masm for MacroAssembler { Address::offset(reg, offset as i64) } - fn address_from_sp(&self, _offset: SPOffset) -> Self::Address { - todo!() + fn address_from_sp(&self, offset: SPOffset) -> Self::Address { + Address::from_shadow_sp((self.sp_offset - offset.as_u32()) as i64) } - fn address_at_sp(&self, _offset: SPOffset) -> Self::Address { - todo!() + fn address_at_sp(&self, offset: SPOffset) -> Self::Address { + Address::from_shadow_sp(offset.as_u32() as i64) } fn address_at_vmctx(&self, _offset: u32) -> Self::Address { @@ -133,13 +133,19 @@ impl Masm for MacroAssembler { let src = match src { RegImm::Imm(v) => { let imm = match v { - I::I32(v) => v as u64, - I::I64(v) => v, - _ => unreachable!(), + I::I32(v) | I::F32(v) => v as u64, + I::F64(v) | I::I64(v) => v, + I::V128(_) => unreachable!(), }; let scratch = regs::scratch(); self.asm.load_constant(imm, scratch); - scratch + if v.is_float() { + let float_scratch = regs::float_scratch(); + self.asm.mov_to_fpu(scratch, float_scratch, v.size()); + float_scratch + } else { + scratch + } } RegImm::Reg(reg) => reg, }; @@ -187,8 +193,10 @@ impl Masm for MacroAssembler { todo!() } - fn pop(&mut self, _dst: Reg, _size: OperandSize) { - todo!() + fn pop(&mut self, dst: Reg, size: OperandSize) { + let addr = self.address_from_sp(SPOffset::from_u32(self.sp_offset)); + self.asm.uload(addr, dst, size); + self.free_stack(size.bytes()); } fn sp_offset(&self) -> SPOffset { @@ -508,15 +516,14 @@ impl Masm for MacroAssembler { .cvt_float_to_float(src.into(), dst.into(), OperandSize::S32, OperandSize::S64); } - fn push(&mut self, reg: Reg, _size: OperandSize) -> StackSlot { - let size = ::word_bytes(); - self.reserve_stack(size as u32); - let address = Address::from_shadow_sp(size as i64); - self.asm.str(reg, address, OperandSize::S64); + fn push(&mut self, reg: Reg, size: OperandSize) -> StackSlot { + self.reserve_stack(size.bytes()); + let address = self.address_from_sp(SPOffset::from_u32(self.sp_offset)); + self.asm.str(reg, address, size); StackSlot { offset: SPOffset::from_u32(self.sp_offset), - size: size as u32, + size: size.bytes(), } } diff --git a/winch/codegen/src/isa/x64/asm.rs b/winch/codegen/src/isa/x64/asm.rs index 79eab2a8078b..b48cb5e0dd09 100644 --- a/winch/codegen/src/isa/x64/asm.rs +++ b/winch/codegen/src/isa/x64/asm.rs @@ -21,9 +21,10 @@ use cranelift_codegen::{ encoding::rex::{encode_modrm, RexFlags}, settings as x64_settings, EmitInfo, EmitState, Inst, }, + CallConv, }, - settings, Final, MachBuffer, MachBufferFinalized, MachInstEmit, MachInstEmitState, MachLabel, - PatchRegion, RelocDistance, VCodeConstantData, VCodeConstants, Writable, + settings, CallInfo, Final, MachBuffer, MachBufferFinalized, MachInstEmit, MachInstEmitState, + MachLabel, PatchRegion, RelocDistance, VCodeConstantData, VCodeConstants, Writable, }; use super::address::Address; @@ -1250,15 +1251,18 @@ impl Assembler { /// Emit a call to an unknown location through a register. pub fn call_with_reg(&mut self, callee: Reg) { self.emit(Inst::CallUnknown { - dest: RegMem::reg(callee.into()), - info: None, + info: Box::new(CallInfo::empty( + RegMem::reg(callee.into()), + CallConv::SystemV, + )), }); } /// Emit a call to a locally defined function through an index. pub fn call_with_name(&mut self, name: UserExternalNameRef) { - let dest = ExternalName::user(name); - self.emit(Inst::CallKnown { dest, info: None }); + self.emit(Inst::CallKnown { + info: Box::new(CallInfo::empty(ExternalName::user(name), CallConv::SystemV)), + }); } /// Emit a call to a well-known libcall. diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs index 98d75b3be658..bf266fa7406f 100644 --- a/winch/codegen/src/masm.rs +++ b/winch/codegen/src/masm.rs @@ -319,6 +319,23 @@ impl Imm { _ => None, } } + + /// Returns true if the [`Imm`] is float. + pub fn is_float(&self) -> bool { + match self { + Self::F32(_) | Self::F64(_) => true, + _ => false, + } + } + + /// Get the operand size of the immediate. + pub fn size(&self) -> OperandSize { + match self { + Self::I32(_) | Self::F32(_) => OperandSize::S32, + Self::I64(_) | Self::F64(_) => OperandSize::S64, + Self::V128(_) => OperandSize::S128, + } + } } /// The location of the [VMcontext] used for function calls. diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs index e313300af127..9f5c256db4dd 100644 --- a/winch/codegen/src/visitor.rs +++ b/winch/codegen/src/visitor.rs @@ -1424,7 +1424,7 @@ where fn visit_table_get(&mut self, table: u32) { let table_index = TableIndex::from_u32(table); let plan = self.env.table_plan(table_index); - let heap_type = plan.table.wasm_ty.heap_type; + let heap_type = plan.table.ref_type.heap_type; let style = &plan.style; match heap_type { @@ -1447,7 +1447,7 @@ where fn visit_table_grow(&mut self, table: u32) { let table_index = TableIndex::from_u32(table); let table_plan = self.env.table_plan(table_index); - let builtin = match table_plan.table.wasm_ty.heap_type { + let builtin = match table_plan.table.ref_type.heap_type { WasmHeapType::Func => self.env.builtins.table_grow_func_ref::(), ty => unimplemented!("Support for HeapType: {ty}"), }; @@ -1485,7 +1485,7 @@ where fn visit_table_fill(&mut self, table: u32) { let table_index = TableIndex::from_u32(table); let table_plan = self.env.table_plan(table_index); - let builtin = match table_plan.table.wasm_ty.heap_type { + let builtin = match table_plan.table.ref_type.heap_type { WasmHeapType::Func => self.env.builtins.table_fill_func_ref::(), ty => unimplemented!("Support for heap type: {ty}"), }; @@ -1509,7 +1509,7 @@ where let table_index = TableIndex::from_u32(table); let table_data = self.env.resolve_table_data(table_index); let plan = self.env.table_plan(table_index); - match plan.table.wasm_ty.heap_type { + match plan.table.ref_type.heap_type { WasmHeapType::Func => match plan.style { TableStyle::CallerChecksSignature { lazy_init: true } => { let value = self.context.pop_to_reg(self.masm, None);