Repository: bytecodealliance/wasmtime
Pull request #9199 (2024-09-05 15:04:05)

Remove `iadd_cin` and `isub_bin`, split `isub_borrow` and `iadd_carry`
This commit refactors the opcodes the Cranelift supports for add-with-carry and subtract-with-borrow. None of these opcodes are currently in use by the wasm frontend nor supported by any backend. In that sense it's unlikely they have many users and the hope is that refactoring won't cause much impact.

The `iadd_cin` and `isub_bin` opcodes are the equivalent of `*_borrow` and `*_carry` except that they don't return the carry flag, they only return the result of the operation. While theoretically useful I've elected to remove them here in favor of only the borrow-returning operations. They can be added back in in the future though if necessary.

I've split the preexisting operations `isub_borrow` and `iadd_carry` additionally into signed/unsigned portions:

* `isub_borrow` => `usub_overflow_bin` and `ssub_overflow_bin`
* `iadd_carry` => `uadd_overflow_cin` and `sadd_overflow_cin`

This reflects how the condition needs to differ on the carry flag computation for signed/unsigned inputs. I've additionally fixed the interpreter's implementation of `IsubBorrow` when switching to the signed/unsigned opcodes.

Finally the documentation for these instructions now explicitly say that the incoming carry/borrow is zero-or-nonzero even though it's typed as `i8`. Additionally the tests have been refactored to make use of multi-return which may not have existed when they were first written.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/.github/actions/install-rust/action.yml b/.github/actions/install-rust/action.yml
index 2301498e6..55ba39879 100644
--- a/.github/actions/install-rust/action.yml
+++ b/.github/actions/install-rust/action.yml
@@ -23,7 +23,7 @@ runs:
         elif [ "${{ inputs.toolchain }}" = "msrv" ]; then
           echo "version=1.$msrv.0" >> "$GITHUB_OUTPUT"
         elif [ "${{ inputs.toolchain }}" = "wasmtime-ci-pinned-nightly" ]; then
-          echo "version=nightly-2024-09-03" >> "$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 e494c98e3..46d2ea54d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -686,6 +686,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:
diff --git a/Cargo.lock b/Cargo.lock
index bb96d9f26..f8576badc 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",
@@ -1055,7 +1055,7 @@ checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
 
 [[package]]
 name = "embedding"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "dlmalloc",
@@ -1865,7 +1865,7 @@ dependencies = [
 
 [[package]]
 name = "min-platform-host"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "libloading",
@@ -2152,7 +2152,7 @@ dependencies = [
 
 [[package]]
 name = "pulley-interpreter"
-version = "0.1.0"
+version = "0.2.0"
 dependencies = [
  "arbitrary",
  "cranelift-bitset",
@@ -3146,7 +3146,7 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
 [[package]]
 name = "verify-component-adapter"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "wasmparser 0.216.0",
@@ -3196,7 +3196,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasi-common"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -3236,7 +3236,7 @@ dependencies = [
 
 [[package]]
 name = "wasi-preview1-component-adapter"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "bitflags 2.4.1",
  "byte-array-literals",
@@ -3469,7 +3469,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "addr2line",
  "anyhow",
@@ -3529,14 +3529,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",
@@ -3552,14 +3552,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",
@@ -3577,7 +3577,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-c-api-macros"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3585,7 +3585,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-cache"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "base64 0.21.0",
@@ -3607,7 +3607,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-cli"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3675,7 +3675,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-cli-flags"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "clap",
@@ -3688,7 +3688,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-component-macro"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "component-macro-test-helpers",
@@ -3708,11 +3708,11 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-component-util"
-version = "25.0.0"
+version = "26.0.0"
 
 [[package]]
 name = "wasmtime-cranelift"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "cfg-if",
@@ -3735,7 +3735,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-environ"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "clap",
@@ -3777,7 +3777,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-explorer"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "capstone",
@@ -3792,7 +3792,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-fiber"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "backtrace",
@@ -3864,7 +3864,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-jit-debug"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "object",
  "once_cell",
@@ -3874,7 +3874,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "cfg-if",
@@ -3884,7 +3884,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-slab"
-version = "25.0.0"
+version = "26.0.0"
 
 [[package]]
 name = "wasmtime-test-macros"
@@ -3898,7 +3898,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-types"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "cranelift-entity",
@@ -3910,7 +3910,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-versioned-export-macros"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3919,7 +3919,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3952,7 +3952,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-http"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3978,7 +3978,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-keyvalue"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "test-programs-artifacts",
@@ -3989,7 +3989,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-nn"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "cap-std",
@@ -4009,7 +4009,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-runtime-config"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "test-programs-artifacts",
@@ -4020,7 +4020,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-threads"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "log",
@@ -4032,7 +4032,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wast"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "log",
@@ -4042,7 +4042,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-winch"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -4057,7 +4057,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wit-bindgen"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "heck 0.4.0",
@@ -4067,7 +4067,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wmemcheck"
-version = "25.0.0"
+version = "26.0.0"
 
 [[package]]
 name = "wast"
@@ -4134,7 +4134,7 @@ dependencies = [
 
 [[package]]
 name = "wiggle"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -4151,7 +4151,7 @@ dependencies = [
 
 [[package]]
 name = "wiggle-generate"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "anyhow",
  "heck 0.4.0",
@@ -4164,7 +4164,7 @@ dependencies = [
 
 [[package]]
 name = "wiggle-macro"
-version = "25.0.0"
+version = "26.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4219,7 +4219,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "winch-codegen"
-version = "0.23.0"
+version = "0.24.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
diff --git a/Cargo.toml b/Cargo.toml
index 28be46ad5..a5147edcb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -156,12 +156,12 @@ 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
 # current stable release of Rust minus 2.
-rust-version = "1.78.0"
+rust-version = "1.79.0"
 
 [workspace.lints.rust]
 # Turn on some lints which are otherwise allow-by-default in rustc.
@@ -184,62 +184,62 @@ 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-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-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" }
diff --git a/RELEASES.md b/RELEASES.md
index b8b5e96fe..0e87cd88e 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.
 
 <!-- ARCHIVE_START -->
+* [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/bforest/Cargo.toml b/cranelift/bforest/Cargo.toml
index 41192317b..17f7c6575 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 2e6d2dd06..b72fda390 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 1126c2233..0d7b284f6 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"]
diff --git a/cranelift/codegen/meta/Cargo.toml b/cranelift/codegen/meta/Cargo.toml
index f6f039c08..047f35e6c 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/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs
index 4348a7b71..d094a2850 100644
--- a/cranelift/codegen/meta/src/shared/instructions.rs
+++ b/cranelift/codegen/meta/src/shared/instructions.rs
@@ -2008,18 +2008,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,
         )
@@ -2028,24 +2022,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,
         )
@@ -2207,18 +2197,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,
         )
@@ -2227,24 +2212,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 7628ba46a..62f563d46 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/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle
index 415d40854..7d18b602e 100644
--- a/cranelift/codegen/src/isa/aarch64/lower.isle
+++ b/cranelift/codegen/src/isa/aarch64/lower.isle
@@ -820,6 +820,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/control/Cargo.toml b/cranelift/control/Cargo.toml
index ebbc9447d..f6354051d 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 1c0c1bf0e..6f30f6f23 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/frontend/Cargo.toml b/cranelift/frontend/Cargo.toml
index 4352525dc..ca8662afa 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 b7b1049ae..fca6812cc 100644
--- a/cranelift/fuzzgen/src/function_generator.rs
+++ b/cranelift/fuzzgen/src/function_generator.rs
@@ -921,11 +921,11 @@ static OPCODE_SIGNATURES: Lazy<Vec<OpcodeSignature>> = 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 c91482397..9561216db 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 ed5e61772..f0afb83a1 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 f96e9325a..05519e797 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 28ea98299..e8058d9de 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 7cd0a4bf7..e2c8e10d5 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 599536d27..3b94c0d13 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 bbacba0d3..3e8384552 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 29579bc8a..a0ea0935b 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 f37986220..5d1fefd42 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 8da764de7..7e6d2d1ba 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 79d84ee4a..c51f2e3a4 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/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h
index 0cbae0c97..30b35b07d 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/wasi-http/src/body.rs b/crates/wasi-http/src/body.rs
index 5f16f4239..5913a4922 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/wasmtime/src/runtime/component/func/host.rs b/crates/wasmtime/src/runtime/component/func/host.rs
index ed203fdce..a28bb3aa0 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::<T>(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<T, Params, Return, F>(
-    cx: *mut VMOpaqueContext,
+    instance: *mut ComponentInstance,
+    types: &Arc<ComponentTypes>,
+    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<T: ComponentType>(memory: &[u8], ptr: &ValRaw) -> Result<us
     Ok(ptr)
 }
 
-unsafe fn handle_result(func: impl FnOnce() -> Result<()>) {
-    match crate::runtime::vm::catch_unwind_and_longjmp(func) {
+unsafe fn call_host_and_handle_result<T>(
+    cx: *mut VMOpaqueContext,
+    func: impl FnOnce(
+        *mut ComponentInstance,
+        &Arc<ComponentTypes>,
+        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<T, F>(
-    cx: *mut VMOpaqueContext,
+    instance: *mut ComponentInstance,
+    types: &Arc<ComponentTypes>,
+    mut store: StoreContextMut<'_, T>,
     ty: TypeFuncIndex,
     mut flags: InstanceFlags,
     memory: *mut VMMemoryDefinition,
@@ -309,10 +330,6 @@ unsafe fn call_host_dynamic<T, F>(
 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<T, F>(
 {
     let data = data as *const F;
     unsafe {
-        handle_result(|| {
+        call_host_and_handle_result(cx, |instance, types, store| {
             call_host_dynamic::<T, _>(
-                cx,
+                instance,
+                types,
+                store,
                 ty,
                 flags,
                 memory,
diff --git a/pulley/Cargo.toml b/pulley/Cargo.toml
index b8c9f3138..0c3677641 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/supply-chain/imports.lock b/supply-chain/imports.lock
index ad9686aa0..c185718a3 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"
@@ -1086,6 +1390,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"
@@ -1199,102 +1509,204 @@ 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"
@@ -1307,6 +1719,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"
@@ -1319,30 +1737,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"
@@ -1385,18 +1833,36 @@ 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"
@@ -1417,6 +1883,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"
diff --git a/winch/codegen/Cargo.toml b/winch/codegen/Cargo.toml
index b5f0f2709..724671a58 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
 


Test patch:
diff --git a/cranelift/filetests/filetests/isa/aarch64/i128.clif b/cranelift/filetests/filetests/isa/aarch64/i128.clif
new file mode 100644
index 000000000..bee69e094
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/aarch64/i128.clif
@@ -0,0 +1,48 @@
+test compile precise-output
+set enable_llvm_abi_extensions=true
+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
+
diff --git a/cranelift/filetests/filetests/parser/ternary.clif b/cranelift/filetests/filetests/parser/ternary.clif
index b521aecc8..2406fb293 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/iaddcarry.clif b/cranelift/filetests/filetests/runtests/iaddcarry.clif
index 04fd38f12..512d13db8 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 5b185af2a..000000000
--- 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 53ebcf116..000000000
--- 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 90dd04c53..4dcbf4190 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/crates/test-programs/src/bin/api_proxy_streaming.rs b/crates/test-programs/src/bin/api_proxy_streaming.rs
index 328e8a12d..39b178272 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<Item = Result<Vec<u8>>> {
-        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/docs/contributing-testing.md b/docs/contributing-testing.md
index c8cff4347..558c62d63 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/tests/all/call_hook.rs b/tests/all/call_hook.rs
index ef565f626..c4d4bcba4 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<Context>,
+pub struct State {
+    pub context: Vec<Context>,
 
-    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 dfb31842a..833efe56e 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<Ou
 /// Get the Wasmtime CLI as a [Command].
 pub fn get_wasmtime_command() -> Result<Command> {
     // 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<Command> {
         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<Command> {
     Ok(cmd)
 }
 
+fn get_wasmtime_path() -> Result<PathBuf> {
+    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<String> {
@@ -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 da4c1abcd..bb6ebc98b 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 000000000..91f71151a
--- /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::<State>::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<u8>` 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::<State>::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::<State>::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::<State>::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::<State>::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<anyhow::Error>) {
+        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<State> 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::<State>::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<u32> 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::<u32>::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<F> {
+        future: F,
+        times: u32,
+    }
+
+    impl<F: Future + Unpin> Future for PollNTimes<F> {
+        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;
+        }
+    }
+}