Repository: bytecodealliance/wasmtime
Pull request #7854 (2024-02-01 03:32:02)

Add C API for GuestProfiler

Milek7: Sorry for the noise with #7853, I messed up with Git.
github-actions[bot]: #### Subscribe to Label Action

cc @peterhuene

<details>
This issue or pull request has been labeled: "wasmtime:c-api"

Thus the following users have been cc'd because of the following labels:

* peterhuene: wasmtime:c-api

To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.

[Learn more.](https://github.com/bytecodealliance/subscribe-to-label-action)
</details>

Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 4d6062754..7f385bc00 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -520,6 +520,19 @@ jobs:
       shell: pwsh
       if: matrix.os == 'windows-latest'
 
+    # Since MPK (PKU) is not present on some GitHub runners, we check if it is
+    # available before force-enabling it. This occasional testing is better than
+    # none at all; ideally we would test in a system-mode QEMU VM.
+    - name: Force-run with MPK enabled, if available
+      if: ${{ contains(matrix.name, 'MPK') }}
+      run: |
+        if cargo run --example mpk-available; then
+          echo "::notice::This CI run will force-enable MPK; this ensures tests conditioned with the \`WASMTIME_TEST_FORCE_MPK\` environment variable will run with MPK-protected memory pool stripes."
+          echo WASMTIME_TEST_FORCE_MPK=1 >> $GITHUB_ENV
+        else
+          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
+
     # Build and test all features
     - run: ./ci/run-tests.sh --locked
       env:
diff --git a/Cargo.lock b/Cargo.lock
index c94c32784..fe8933d14 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -224,7 +224,7 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
 
 [[package]]
 name = "byte-array-literals"
-version = "18.0.0"
+version = "19.0.0"
 
 [[package]]
 name = "byteorder"
@@ -570,7 +570,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "cranelift-codegen",
  "cranelift-frontend",
@@ -578,14 +578,14 @@ dependencies = [
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "anyhow",
  "bincode",
@@ -613,25 +613,25 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.105.0"
+version = "0.106.0"
 
 [[package]]
 name = "cranelift-control"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "arbitrary",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "serde",
  "serde_derive",
@@ -670,7 +670,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "cranelift-codegen",
  "hashbrown 0.14.0",
@@ -694,7 +694,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-interpreter"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "cranelift-codegen",
  "cranelift-entity",
@@ -708,7 +708,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "codespan-reporting",
  "log",
@@ -717,7 +717,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-jit"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "anyhow",
  "cranelift",
@@ -738,7 +738,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -750,7 +750,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -759,7 +759,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -774,7 +774,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-reader"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -784,7 +784,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-serde"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "clap",
  "cranelift-codegen",
@@ -831,7 +831,7 @@ dependencies = [
 
 [[package]]
 name = "cranelift-wasm"
-version = "0.105.0"
+version = "0.106.0"
 dependencies = [
  "cranelift-codegen",
  "cranelift-entity",
@@ -2892,7 +2892,7 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
 [[package]]
 name = "verify-component-adapter"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "wasmparser 0.121.0",
@@ -2942,7 +2942,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasi-cap-std-sync"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -2964,7 +2964,7 @@ dependencies = [
 
 [[package]]
 name = "wasi-common"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -2997,7 +2997,7 @@ dependencies = [
 
 [[package]]
 name = "wasi-preview1-component-adapter"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "byte-array-literals",
  "object",
@@ -3008,7 +3008,7 @@ dependencies = [
 
 [[package]]
 name = "wasi-tokio"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cap-std",
@@ -3220,7 +3220,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "addr2line",
  "anyhow",
@@ -3265,14 +3265,14 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-asm-macros"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "cfg-if",
 ]
 
 [[package]]
 name = "wasmtime-bench-api"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cap-std",
@@ -3289,14 +3289,14 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-c-api"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "wasmtime-c-api-impl",
 ]
 
 [[package]]
 name = "wasmtime-c-api-impl"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cap-std",
@@ -3323,7 +3323,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-cache"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "base64",
@@ -3345,7 +3345,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-cli"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3401,7 +3401,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-cli-flags"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "clap",
@@ -3414,7 +3414,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-component-macro"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "component-macro-test-helpers",
@@ -3430,11 +3430,11 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-component-util"
-version = "18.0.0"
+version = "19.0.0"
 
 [[package]]
 name = "wasmtime-cranelift"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cfg-if",
@@ -3457,7 +3457,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-cranelift-shared"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -3471,7 +3471,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-environ"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "bincode",
@@ -3512,7 +3512,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-explorer"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "capstone",
@@ -3526,7 +3526,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-fiber"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "backtrace",
@@ -3595,7 +3595,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-jit-debug"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "object",
  "once_cell",
@@ -3605,7 +3605,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "cfg-if",
  "libc",
@@ -3614,7 +3614,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-runtime"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cc",
@@ -3645,7 +3645,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-types"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "cranelift-entity",
  "serde",
@@ -3656,7 +3656,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-versioned-export-macros"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3665,7 +3665,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3703,7 +3703,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-http"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3729,7 +3729,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-nn"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cap-std",
@@ -3745,7 +3745,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wasi-threads"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "log",
@@ -3757,7 +3757,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wast"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "log",
@@ -3767,7 +3767,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-winch"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -3782,7 +3782,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wit-bindgen"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "heck",
@@ -3792,7 +3792,7 @@ dependencies = [
 
 [[package]]
 name = "wasmtime-wmemcheck"
-version = "18.0.0"
+version = "19.0.0"
 
 [[package]]
 name = "wast"
@@ -3854,7 +3854,7 @@ dependencies = [
 
 [[package]]
 name = "wiggle"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3871,7 +3871,7 @@ dependencies = [
 
 [[package]]
 name = "wiggle-generate"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "anyhow",
  "heck",
@@ -3884,7 +3884,7 @@ dependencies = [
 
 [[package]]
 name = "wiggle-macro"
-version = "18.0.0"
+version = "19.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3939,7 +3939,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "winch-codegen"
-version = "0.16.0"
+version = "0.17.0"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
diff --git a/Cargo.toml b/Cargo.toml
index 8f0689c01..52d4d0496 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -130,7 +130,7 @@ exclude = [
 ]
 
 [workspace.package]
-version = "18.0.0"
+version = "19.0.0"
 authors = ["The Wasmtime Project Developers"]
 edition = "2021"
 # Wasmtime's current policy is that this number can be no larger than the
@@ -152,58 +152,58 @@ all = 'allow'
 
 [workspace.dependencies]
 arbitrary = { version = "1.3.1" }
-wasmtime-wmemcheck = { path = "crates/wmemcheck", version = "=18.0.0" }
-wasmtime = { path = "crates/wasmtime", version = "18.0.0", default-features = false }
-wasmtime-cache = { path = "crates/cache", version = "=18.0.0" }
-wasmtime-cli-flags = { path = "crates/cli-flags", version = "=18.0.0" }
-wasmtime-cranelift = { path = "crates/cranelift", version = "=18.0.0" }
-wasmtime-cranelift-shared = { path = "crates/cranelift-shared", version = "=18.0.0" }
-wasmtime-winch = { path = "crates/winch", version = "=18.0.0" }
-wasmtime-environ = { path = "crates/environ", version = "=18.0.0" }
-wasmtime-explorer = { path = "crates/explorer", version = "=18.0.0" }
-wasmtime-fiber = { path = "crates/fiber", version = "=18.0.0" }
-wasmtime-types = { path = "crates/types", version = "18.0.0" }
-wasmtime-jit-debug = { path = "crates/jit-debug", version = "=18.0.0" }
-wasmtime-runtime = { path = "crates/runtime", version = "=18.0.0" }
-wasmtime-wast = { path = "crates/wast", version = "=18.0.0" }
-wasmtime-wasi = { path = "crates/wasi", version = "18.0.0", default-features = false }
-wasmtime-wasi-http = { path = "crates/wasi-http", version = "=18.0.0", default-features = false }
-wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "18.0.0" }
-wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "18.0.0" }
-wasmtime-component-util = { path = "crates/component-util", version = "=18.0.0" }
-wasmtime-component-macro = { path = "crates/component-macro", version = "=18.0.0" }
-wasmtime-asm-macros = { path = "crates/asm-macros", version = "=18.0.0" }
-wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=18.0.0" }
+wasmtime-wmemcheck = { path = "crates/wmemcheck", version = "=19.0.0" }
+wasmtime = { path = "crates/wasmtime", version = "19.0.0", default-features = false }
+wasmtime-cache = { path = "crates/cache", version = "=19.0.0" }
+wasmtime-cli-flags = { path = "crates/cli-flags", version = "=19.0.0" }
+wasmtime-cranelift = { path = "crates/cranelift", version = "=19.0.0" }
+wasmtime-cranelift-shared = { path = "crates/cranelift-shared", version = "=19.0.0" }
+wasmtime-winch = { path = "crates/winch", version = "=19.0.0" }
+wasmtime-environ = { path = "crates/environ", version = "=19.0.0" }
+wasmtime-explorer = { path = "crates/explorer", version = "=19.0.0" }
+wasmtime-fiber = { path = "crates/fiber", version = "=19.0.0" }
+wasmtime-types = { path = "crates/types", version = "19.0.0" }
+wasmtime-jit-debug = { path = "crates/jit-debug", version = "=19.0.0" }
+wasmtime-runtime = { path = "crates/runtime", version = "=19.0.0" }
+wasmtime-wast = { path = "crates/wast", version = "=19.0.0" }
+wasmtime-wasi = { path = "crates/wasi", version = "19.0.0", default-features = false }
+wasmtime-wasi-http = { path = "crates/wasi-http", version = "=19.0.0", default-features = false }
+wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "19.0.0" }
+wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "19.0.0" }
+wasmtime-component-util = { path = "crates/component-util", version = "=19.0.0" }
+wasmtime-component-macro = { path = "crates/component-macro", version = "=19.0.0" }
+wasmtime-asm-macros = { path = "crates/asm-macros", version = "=19.0.0" }
+wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=19.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 = "=18.0.0", default-features = false }
-wiggle-macro = { path = "crates/wiggle/macro", version = "=18.0.0" }
-wiggle-generate = { path = "crates/wiggle/generate", version = "=18.0.0" }
-wasi-common = { path = "crates/wasi-common", version = "=18.0.0", default-features = false }
-wasi-tokio = { path = "crates/wasi-common/tokio", version = "=18.0.0" }
-wasi-cap-std-sync = { path = "crates/wasi-common/cap-std-sync", version = "=18.0.0" }
+wiggle = { path = "crates/wiggle", version = "=19.0.0", default-features = false }
+wiggle-macro = { path = "crates/wiggle/macro", version = "=19.0.0" }
+wiggle-generate = { path = "crates/wiggle/generate", version = "=19.0.0" }
+wasi-common = { path = "crates/wasi-common", version = "=19.0.0", default-features = false }
+wasi-tokio = { path = "crates/wasi-common/tokio", version = "=19.0.0" }
+wasi-cap-std-sync = { path = "crates/wasi-common/cap-std-sync", version = "=19.0.0" }
 wasmtime-fuzzing = { path = "crates/fuzzing" }
-wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=18.0.0" }
-wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=18.0.0" }
+wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=19.0.0" }
+wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=19.0.0" }
 test-programs-artifacts = { path = 'crates/test-programs/artifacts' }
 
-cranelift-wasm = { path = "cranelift/wasm", version = "0.105.0" }
-cranelift-codegen = { path = "cranelift/codegen", version = "0.105.0", default-features = false, features = ["std", "unwind"] }
-cranelift-frontend = { path = "cranelift/frontend", version = "0.105.0" }
-cranelift-entity = { path = "cranelift/entity", version = "0.105.0" }
-cranelift-native = { path = "cranelift/native", version = "0.105.0" }
-cranelift-module = { path = "cranelift/module", version = "0.105.0" }
-cranelift-interpreter = { path = "cranelift/interpreter", version = "0.105.0" }
-cranelift-reader = { path = "cranelift/reader", version = "0.105.0" }
+cranelift-wasm = { path = "cranelift/wasm", version = "0.106.0" }
+cranelift-codegen = { path = "cranelift/codegen", version = "0.106.0", default-features = false, features = ["std", "unwind"] }
+cranelift-frontend = { path = "cranelift/frontend", version = "0.106.0" }
+cranelift-entity = { path = "cranelift/entity", version = "0.106.0" }
+cranelift-native = { path = "cranelift/native", version = "0.106.0" }
+cranelift-module = { path = "cranelift/module", version = "0.106.0" }
+cranelift-interpreter = { path = "cranelift/interpreter", version = "0.106.0" }
+cranelift-reader = { path = "cranelift/reader", version = "0.106.0" }
 cranelift-filetests = { path = "cranelift/filetests" }
-cranelift-object = { path = "cranelift/object", version = "0.105.0" }
-cranelift-jit = { path = "cranelift/jit", version = "0.105.0" }
+cranelift-object = { path = "cranelift/object", version = "0.106.0" }
+cranelift-jit = { path = "cranelift/jit", version = "0.106.0" }
 cranelift-fuzzgen = { path = "cranelift/fuzzgen" }
-cranelift-bforest = { path = "cranelift/bforest", version = "0.105.0" }
-cranelift-control = { path = "cranelift/control", version = "0.105.0" }
-cranelift = { path = "cranelift/umbrella", version = "0.105.0" }
+cranelift-bforest = { path = "cranelift/bforest", version = "0.106.0" }
+cranelift-control = { path = "cranelift/control", version = "0.106.0" }
+cranelift = { path = "cranelift/umbrella", version = "0.106.0" }
 
-winch-codegen = { path = "winch/codegen", version = "=0.16.0" }
+winch-codegen = { path = "winch/codegen", version = "=0.17.0" }
 winch-filetests = { path = "winch/filetests" }
 winch-test-macros = { path = "winch/test-macros" }
 
diff --git a/RELEASES.md b/RELEASES.md
index 3618765bc..3d67a7c2f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,5 +1,15 @@
 --------------------------------------------------------------------------------
 
+## 19.0.0
+
+Unreleased.
+
+### Added
+
+### Changed
+
+--------------------------------------------------------------------------------
+
 ## 18.0.0
 
 Unreleased.
diff --git a/cranelift/bforest/Cargo.toml b/cranelift/bforest/Cargo.toml
index df489e8f7..1fa5bcac9 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.105.0"
+version = "0.106.0"
 description = "A forest of B+-trees"
 license = "Apache-2.0 WITH LLVM-exception"
 documentation = "https://docs.rs/cranelift-bforest"
diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml
index ff57921c9..5c99c9faa 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.105.0"
+version = "0.106.0"
 description = "Low-level code generator library"
 license = "Apache-2.0 WITH LLVM-exception"
 documentation = "https://docs.rs/cranelift-codegen"
@@ -19,7 +19,7 @@ workspace = true
 anyhow = { workspace = true, optional = true }
 bumpalo = "3"
 capstone = { workspace = true, optional = true }
-cranelift-codegen-shared = { path = "./shared", version = "0.105.0" }
+cranelift-codegen-shared = { path = "./shared", version = "0.106.0" }
 cranelift-entity = { workspace = true }
 cranelift-bforest = { workspace = true }
 cranelift-control = { workspace = true }
@@ -44,8 +44,8 @@ criterion = { version = "0.5.0", features = ["html_reports"] }
 similar = "2.1.0"
 
 [build-dependencies]
-cranelift-codegen-meta = { path = "meta", version = "0.105.0" }
-cranelift-isle = { path = "../isle/isle", version = "=0.105.0" }
+cranelift-codegen-meta = { path = "meta", version = "0.106.0" }
+cranelift-isle = { path = "../isle/isle", version = "=0.106.0" }
 
 [features]
 default = ["std", "unwind", "host-arch", "timing"]
diff --git a/cranelift/codegen/meta/Cargo.toml b/cranelift/codegen/meta/Cargo.toml
index aff2d6973..d0f0ee6bb 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.105.0"
+version = "0.106.0"
 description = "Metaprogram for cranelift-codegen code generator library"
 license = "Apache-2.0 WITH LLVM-exception"
 repository = "https://github.com/bytecodealliance/wasmtime"
@@ -15,4 +15,4 @@ workspace = true
 rustdoc-args = [ "--document-private-items" ]
 
 [dependencies]
-cranelift-codegen-shared = { path = "../shared", version = "0.105.0" }
+cranelift-codegen-shared = { path = "../shared", version = "0.106.0" }
diff --git a/cranelift/codegen/shared/Cargo.toml b/cranelift/codegen/shared/Cargo.toml
index d773aa743..59e5e22ec 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.105.0"
+version = "0.106.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/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle
index 2452966a1..516e3151b 100644
--- a/cranelift/codegen/src/isa/x64/lower.isle
+++ b/cranelift/codegen/src/isa/x64/lower.isle
@@ -4159,35 +4159,33 @@
 
 ;; Rules for `umulhi` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(rule (lower (umulhi a @ (value_type $I16) b))
-      (let ((res ValueRegs (mul_hi $I16 $false a b))
-            (hi Gpr (value_regs_get_gpr res 1)))
-        hi))
-
-(rule (lower (umulhi a @ (value_type $I32) b))
-      (let ((res ValueRegs (mul_hi $I32 $false a b))
-            (hi Gpr (value_regs_get_gpr res 1)))
+;; The umulhi instruction is not available for 8-bit types, so we can extend
+;; the inputs, use the 16-bit multiply and shift the result down.
+(rule 1 (lower (umulhi a @ (value_type $I8) b))
+      (let ((a_ext Gpr (extend_to_gpr a $I16 (ExtendKind.Zero)))
+            (b_ext Gpr (extend_to_gpr b $I16 (ExtendKind.Zero)))
+            (mul Gpr (x64_mul $I16 a_ext b_ext))
+            (hi Gpr (x64_shr $I64 mul (imm8_to_imm8_gpr 8))))
         hi))
 
-(rule (lower (umulhi a @ (value_type $I64) b))
-      (let ((res ValueRegs (mul_hi $I64 $false a b))
+(rule 0 (lower (umulhi a @ (value_type ty) b))
+      (let ((res ValueRegs (mul_hi ty $false a b))
             (hi Gpr (value_regs_get_gpr res 1)))
         hi))
 
 ;; Rules for `smulhi` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(rule (lower (smulhi a @ (value_type $I16) b))
-      (let ((res ValueRegs (mul_hi $I16 $true a b))
-            (hi Gpr (value_regs_get_gpr res 1)))
-        hi))
-
-(rule (lower (smulhi a @ (value_type $I32) b))
-      (let ((res ValueRegs (mul_hi $I32 $true a b))
-            (hi Gpr (value_regs_get_gpr res 1)))
+;; The smulhi instruction is not available for 8-bit types, so we can extend
+;; the inputs, use the 16-bit multiply and shift the result down.
+(rule 1 (lower (smulhi a @ (value_type $I8) b))
+      (let ((a_ext Gpr (extend_to_gpr a $I16 (ExtendKind.Sign)))
+            (b_ext Gpr (extend_to_gpr b $I16 (ExtendKind.Sign)))
+            (mul Gpr (x64_mul $I16 a_ext b_ext))
+            (hi Gpr (x64_sar $I64 mul (imm8_to_imm8_gpr 8))))
         hi))
 
-(rule (lower (smulhi a @ (value_type $I64) b))
-      (let ((res ValueRegs (mul_hi $I64 $true a b))
+(rule 0 (lower (smulhi a @ (value_type ty) b))
+      (let ((res ValueRegs (mul_hi ty $true a b))
             (hi Gpr (value_regs_get_gpr res 1)))
         hi))
 
diff --git a/cranelift/codegen/src/verifier/mod.rs b/cranelift/codegen/src/verifier/mod.rs
index 608d0ac05..d80724570 100644
--- a/cranelift/codegen/src/verifier/mod.rs
+++ b/cranelift/codegen/src/verifier/mod.rs
@@ -157,7 +157,7 @@ where
 
 /// Result of a step in the verification process.
 ///
-/// Functions that return `VerifierStepResult<()>` should also take a
+/// Functions that return `VerifierStepResult` should also take a
 /// mutable reference to `VerifierErrors` as argument in order to report
 /// errors.
 ///
@@ -165,11 +165,11 @@ where
 /// meaning that the verification process may continue. However, other (non-fatal)
 /// errors might have been reported through the previously mentioned `VerifierErrors`
 /// argument.
-pub type VerifierStepResult<T> = Result<T, ()>;
+pub type VerifierStepResult = Result<(), ()>;
 
 /// Result of a verification operation.
 ///
-/// Unlike `VerifierStepResult<()>` which may be `Ok` while still having reported
+/// Unlike `VerifierStepResult` which may be `Ok` while still having reported
 /// errors, this type always returns `Err` if an error (fatal or not) was reported.
 pub type VerifierResult<T> = Result<T, VerifierErrors>;
 
@@ -203,7 +203,7 @@ impl VerifierErrors {
     /// Return a `VerifierStepResult` that is fatal if at least one error was reported,
     /// and non-fatal otherwise.
     #[inline]
-    pub fn as_result(&self) -> VerifierStepResult<()> {
+    pub fn as_result(&self) -> VerifierStepResult {
         if self.is_empty() {
             Ok(())
         } else {
@@ -217,13 +217,13 @@ impl VerifierErrors {
     }
 
     /// Report a fatal error and return `Err`.
-    pub fn fatal(&mut self, error: impl Into<VerifierError>) -> VerifierStepResult<()> {
+    pub fn fatal(&mut self, error: impl Into<VerifierError>) -> VerifierStepResult {
         self.report(error);
         Err(())
     }
 
     /// Report a non-fatal error and return `Ok`.
-    pub fn nonfatal(&mut self, error: impl Into<VerifierError>) -> VerifierStepResult<()> {
+    pub fn nonfatal(&mut self, error: impl Into<VerifierError>) -> VerifierStepResult {
         self.report(error);
         Ok(())
     }
@@ -285,7 +285,7 @@ pub fn verify_context<'a, FOI: Into<FlagsOrIsa<'a>>>(
     domtree: &DominatorTree,
     fisa: FOI,
     errors: &mut VerifierErrors,
-) -> VerifierStepResult<()> {
+) -> VerifierStepResult {
     let _tt = timing::verifier();
     let verifier = Verifier::new(func, fisa.into());
     if cfg.is_valid() {
@@ -325,7 +325,7 @@ impl<'a> Verifier<'a> {
     // Check for:
     //  - cycles in the global value declarations.
     //  - use of 'vmctx' when no special parameter declares it.
-    fn verify_global_values(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn verify_global_values(&self, errors: &mut VerifierErrors) -> VerifierStepResult {
         let mut cycle_seen = false;
         let mut seen = SparseSet::new();
 
@@ -410,7 +410,7 @@ impl<'a> Verifier<'a> {
         Ok(())
     }
 
-    fn verify_memory_types(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn verify_memory_types(&self, errors: &mut VerifierErrors) -> VerifierStepResult {
         // Verify that all fields are statically-sized and lie within
         // the struct, do not overlap, and are in offset order
         for (mt, mt_data) in &self.func.memory_types {
@@ -457,7 +457,7 @@ impl<'a> Verifier<'a> {
         Ok(())
     }
 
-    fn verify_tables(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn verify_tables(&self, errors: &mut VerifierErrors) -> VerifierStepResult {
         if let Some(isa) = self.isa {
             for (table, table_data) in &self.func.tables {
                 let base = table_data.base_gv;
@@ -502,7 +502,7 @@ impl<'a> Verifier<'a> {
 
     /// Check that the given block can be encoded as a BB, by checking that only
     /// branching instructions are ending the block.
-    fn encodable_as_bb(&self, block: Block, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn encodable_as_bb(&self, block: Block, errors: &mut VerifierErrors) -> VerifierStepResult {
         match self.func.is_block_basic(block) {
             Ok(()) => Ok(()),
             Err((inst, message)) => errors.fatal((inst, self.context(inst), message)),
@@ -514,7 +514,7 @@ impl<'a> Verifier<'a> {
         block: Block,
         inst: Inst,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let is_terminator = self.func.dfg.insts[inst].opcode().is_terminator();
         let is_last_inst = self.func.layout.last_inst(block) == Some(inst);
 
@@ -560,11 +560,7 @@ impl<'a> Verifier<'a> {
         Ok(())
     }
 
-    fn instruction_integrity(
-        &self,
-        inst: Inst,
-        errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    fn instruction_integrity(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult {
         let inst_data = &self.func.dfg.insts[inst];
         let dfg = &self.func.dfg;
 
@@ -596,7 +592,7 @@ impl<'a> Verifier<'a> {
         &self,
         inst: Inst,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         use crate::ir::instructions::InstructionData::*;
 
         for arg in self.func.dfg.inst_values(inst) {
@@ -763,7 +759,7 @@ impl<'a> Verifier<'a> {
         loc: impl Into<AnyEntity>,
         e: Block,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.dfg.block_is_valid(e) || !self.func.layout.is_block_inserted(e) {
             return errors.fatal((loc, format!("invalid block reference {}", e)));
         }
@@ -780,7 +776,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         s: SigRef,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.dfg.signatures.is_valid(s) {
             errors.fatal((
                 inst,
@@ -797,7 +793,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         f: FuncRef,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.dfg.ext_funcs.is_valid(f) {
             errors.nonfatal((
                 inst,
@@ -814,7 +810,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         ss: StackSlot,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.sized_stack_slots.is_valid(ss) {
             errors.nonfatal((
                 inst,
@@ -831,7 +827,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         ss: DynamicStackSlot,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.dynamic_stack_slots.is_valid(ss) {
             errors.nonfatal((
                 inst,
@@ -848,7 +844,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         gv: GlobalValue,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.global_values.is_valid(gv) {
             errors.nonfatal((
                 inst,
@@ -865,7 +861,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         table: ir::Table,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.tables.is_valid(table) {
             errors.nonfatal((inst, self.context(inst), format!("invalid table {}", table)))
         } else {
@@ -878,7 +874,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         l: &ValueList,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !l.is_valid(&self.func.dfg.value_lists) {
             errors.nonfatal((
                 inst,
@@ -895,7 +891,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         j: JumpTable,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         if !self.func.stencil.dfg.jump_tables.is_valid(j) {
             errors.nonfatal((
                 inst,
@@ -916,7 +912,7 @@ impl<'a> Verifier<'a> {
         loc_inst: Inst,
         v: Value,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let dfg = &self.func.dfg;
         if !dfg.value_is_valid(v) {
             errors.nonfatal((
@@ -934,7 +930,7 @@ impl<'a> Verifier<'a> {
         loc_inst: Inst,
         v: Value,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         self.verify_value(loc_inst, v, errors)?;
 
         let dfg = &self.func.dfg;
@@ -1028,7 +1024,7 @@ impl<'a> Verifier<'a> {
         loc_inst: Inst,
         v: Value,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         self.verify_value(loc_inst, v, errors)?;
 
         match self.func.dfg.value_def(v) {
@@ -1062,7 +1058,7 @@ impl<'a> Verifier<'a> {
         flags: MemFlags,
         arg: Value,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let typ = self.func.dfg.ctrl_typevar(inst);
         let value_type = self.func.dfg.value_type(arg);
 
@@ -1099,7 +1095,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         constant: Constant,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let type_size = self.func.dfg.ctrl_typevar(inst).bytes() as usize;
         let constant_size = self.func.dfg.constants.get(constant).len();
         if type_size != constant_size {
@@ -1119,7 +1115,7 @@ impl<'a> Verifier<'a> {
         &self,
         domtree: &DominatorTree,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         // We consider two `DominatorTree`s to be equal if they return the same immediate
         // dominator for each block. Therefore the current domtree is valid if it matches the freshly
         // computed one.
@@ -1174,7 +1170,7 @@ impl<'a> Verifier<'a> {
         Ok(())
     }
 
-    fn typecheck_entry_block_params(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn typecheck_entry_block_params(&self, errors: &mut VerifierErrors) -> VerifierStepResult {
         if let Some(block) = self.func.layout.entry_block() {
             let expected_types = &self.func.signature.params;
             let block_param_count = self.func.dfg.num_block_params(block);
@@ -1207,7 +1203,7 @@ impl<'a> Verifier<'a> {
         errors.as_result()
     }
 
-    fn check_entry_not_cold(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn check_entry_not_cold(&self, errors: &mut VerifierErrors) -> VerifierStepResult {
         if let Some(entry_block) = self.func.layout.entry_block() {
             if self.func.layout.is_cold(entry_block) {
                 return errors
@@ -1217,7 +1213,7 @@ impl<'a> Verifier<'a> {
         errors.as_result()
     }
 
-    fn typecheck(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn typecheck(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult {
         let inst_data = &self.func.dfg.insts[inst];
         let constraints = inst_data.opcode().constraints();
 
@@ -1258,7 +1254,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         ctrl_type: Type,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let mut i = 0;
         for &result in self.func.dfg.inst_results(inst) {
             let result_type = self.func.dfg.value_type(result);
@@ -1300,7 +1296,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         ctrl_type: Type,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let constraints = self.func.dfg.insts[inst].opcode().constraints();
 
         for (i, &arg) in self.func.dfg.inst_fixed_args(inst).iter().enumerate() {
@@ -1341,7 +1337,7 @@ impl<'a> Verifier<'a> {
         &self,
         inst: Inst,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         match &self.func.dfg.insts[inst] {
             ir::InstructionData::Jump { destination, .. } => {
                 self.typecheck_block_call(inst, destination, errors)?;
@@ -1387,7 +1383,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         block: &ir::BlockCall,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let pool = &self.func.dfg.value_lists;
         let iter = self
             .func
@@ -1405,7 +1401,7 @@ impl<'a> Verifier<'a> {
         iter: I,
         variable_args: &[Value],
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let mut i = 0;
 
         for expected_type in iter {
@@ -1443,7 +1439,7 @@ impl<'a> Verifier<'a> {
         Ok(())
     }
 
-    fn typecheck_return(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn typecheck_return(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult {
         match self.func.dfg.insts[inst] {
             ir::InstructionData::MultiAry {
                 opcode: Opcode::Return,
@@ -1485,7 +1481,7 @@ impl<'a> Verifier<'a> {
         inst: Inst,
         sig_ref: SigRef,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let signature = &self.func.dfg.signatures[sig_ref];
         let cc = signature.call_conv;
         if !cc.supports_tail_calls() {
@@ -1513,7 +1509,7 @@ impl<'a> Verifier<'a> {
         actual_types: impl ExactSizeIterator<Item = Type>,
         errors: &mut VerifierErrors,
         message: &str,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let expected_types = &self.func.signature.returns;
         if actual_types.len() != expected_types.len() {
             return errors.nonfatal((inst, self.context(inst), message));
@@ -1535,7 +1531,7 @@ impl<'a> Verifier<'a> {
 
     // Check special-purpose type constraints that can't be expressed in the normal opcode
     // constraints.
-    fn typecheck_special(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn typecheck_special(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult {
         match self.func.dfg.insts[inst] {
             ir::InstructionData::TableAddr { table, arg, .. } => {
                 let index_type = self.func.dfg.value_type(arg);
@@ -1575,7 +1571,7 @@ impl<'a> Verifier<'a> {
         &self,
         cfg: &ControlFlowGraph,
         errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    ) -> VerifierStepResult {
         let mut expected_succs = BTreeSet::<Block>::new();
         let mut got_succs = BTreeSet::<Block>::new();
         let mut expected_preds = BTreeSet::<Inst>::new();
@@ -1643,11 +1639,7 @@ impl<'a> Verifier<'a> {
         errors.as_result()
     }
 
-    fn immediate_constraints(
-        &self,
-        inst: Inst,
-        errors: &mut VerifierErrors,
-    ) -> VerifierStepResult<()> {
+    fn immediate_constraints(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult {
         let inst_data = &self.func.dfg.insts[inst];
 
         match *inst_data {
@@ -1713,7 +1705,7 @@ impl<'a> Verifier<'a> {
         }
     }
 
-    fn iconst_bounds(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn iconst_bounds(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult {
         use crate::ir::instructions::InstructionData::UnaryImm;
 
         let inst_data = &self.func.dfg.insts[inst];
@@ -1746,7 +1738,7 @@ impl<'a> Verifier<'a> {
         }
     }
 
-    fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult {
         let params = self
             .func
             .signature
@@ -1806,7 +1798,7 @@ impl<'a> Verifier<'a> {
         }
     }
 
-    pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+    pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult {
         self.verify_global_values(errors)?;
         self.verify_memory_types(errors)?;
         self.verify_tables(errors)?;
diff --git a/cranelift/control/Cargo.toml b/cranelift/control/Cargo.toml
index b0492844d..64a6bf7dc 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.105.0"
+version = "0.106.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 3533274f7..4b16b6a0a 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.105.0"
+version = "0.106.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 ae84dee24..896168e36 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.105.0"
+version = "0.106.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 743a6a5d6..6ed5d8412 100644
--- a/cranelift/fuzzgen/src/function_generator.rs
+++ b/cranelift/fuzzgen/src/function_generator.rs
@@ -523,8 +523,6 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) -
                 rets,
                 (Opcode::UmulOverflow | Opcode::SmulOverflow, &[I128, I128]),
                 (Opcode::Imul, &[I8X16, I8X16]),
-                // https://github.com/bytecodealliance/wasmtime/issues/5468
-                (Opcode::Smulhi | Opcode::Umulhi, &[I8, I8]),
                 // https://github.com/bytecodealliance/wasmtime/issues/4756
                 (Opcode::Udiv | Opcode::Sdiv, &[I128, I128]),
                 // https://github.com/bytecodealliance/wasmtime/issues/5474
diff --git a/cranelift/interpreter/Cargo.toml b/cranelift/interpreter/Cargo.toml
index a2e0f703e..e59b31040 100644
--- a/cranelift/interpreter/Cargo.toml
+++ b/cranelift/interpreter/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-interpreter"
-version = "0.105.0"
+version = "0.106.0"
 authors = ["The Cranelift Project Developers"]
 description = "Interpret Cranelift IR"
 repository = "https://github.com/bytecodealliance/wasmtime"
diff --git a/cranelift/isle/isle/Cargo.toml b/cranelift/isle/isle/Cargo.toml
index 2394662fa..08fa18a2b 100644
--- a/cranelift/isle/isle/Cargo.toml
+++ b/cranelift/isle/isle/Cargo.toml
@@ -6,7 +6,7 @@ license = "Apache-2.0 WITH LLVM-exception"
 name = "cranelift-isle"
 readme = "../README.md"
 repository = "https://github.com/bytecodealliance/wasmtime/tree/main/cranelift/isle"
-version = "0.105.0"
+version = "0.106.0"
 
 [lints]
 workspace = true
diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml
index df9b94416..c06898fc9 100644
--- a/cranelift/jit/Cargo.toml
+++ b/cranelift/jit/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-jit"
-version = "0.105.0"
+version = "0.106.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 238fd3ba5..66ec7e2fe 100644
--- a/cranelift/module/Cargo.toml
+++ b/cranelift/module/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-module"
-version = "0.105.0"
+version = "0.106.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 e57577b8b..be8c2a5e5 100644
--- a/cranelift/native/Cargo.toml
+++ b/cranelift/native/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-native"
-version = "0.105.0"
+version = "0.106.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 4f2d29154..1086055a6 100644
--- a/cranelift/object/Cargo.toml
+++ b/cranelift/object/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-object"
-version = "0.105.0"
+version = "0.106.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 50a1f15d2..efbd15335 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.105.0"
+version = "0.106.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 626eb20ff..8577674ea 100644
--- a/cranelift/serde/Cargo.toml
+++ b/cranelift/serde/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-serde"
-version = "0.105.0"
+version = "0.106.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 c1da2f66f..83b6d8536 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.105.0"
+version = "0.106.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 9a5d249f7..6913d4d32 100644
--- a/cranelift/wasm/Cargo.toml
+++ b/cranelift/wasm/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cranelift-wasm"
-version = "0.105.0"
+version = "0.106.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 65b7b4157..6ba3e76b8 100644
--- a/crates/c-api/include/wasmtime.h
+++ b/crates/c-api/include/wasmtime.h
@@ -194,6 +194,7 @@
 #include <wasmtime/linker.h>
 #include <wasmtime/memory.h>
 #include <wasmtime/module.h>
+#include <wasmtime/profiling.h>
 #include <wasmtime/store.h>
 #include <wasmtime/table.h>
 #include <wasmtime/trap.h>
@@ -205,11 +206,11 @@
 /**
  * \brief Wasmtime version string.
  */
-#define WASMTIME_VERSION "18.0.0"
+#define WASMTIME_VERSION "19.0.0"
 /**
  * \brief Wasmtime major version number.
  */
-#define WASMTIME_VERSION_MAJOR 18
+#define WASMTIME_VERSION_MAJOR 19
 /**
  * \brief Wasmtime minor version number.
  */
diff --git a/crates/c-api/include/wasmtime/profiling.h b/crates/c-api/include/wasmtime/profiling.h
new file mode 100644
index 000000000..df3a68966
--- /dev/null
+++ b/crates/c-api/include/wasmtime/profiling.h
@@ -0,0 +1,113 @@
+/**
+ * \file wasmtime/profiling.h
+ *
+ * \brief API for Wasmtime guest profiler
+ */
+
+#ifndef WASMTIME_PROFILING_H
+#define WASMTIME_PROFILING_H
+
+#include <wasm.h>
+#include <wasmtime/error.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Collects basic profiling data for a single WebAssembly guest.
+ *
+ * To use this, you’ll need to arrange to call #wasmtime_guestprofiler_sample at
+ * regular intervals while the guest is on the stack. The most straightforward
+ * way to do that is to call it from a callback registered with
+ * #wasmtime_store_epoch_deadline_callback.
+ *
+ * For more information see the Rust documentation at:
+ * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html
+ */
+typedef struct wasmtime_guestprofiler wasmtime_guestprofiler_t;
+
+/**
+ * \brief Deletes profiler without finishing it.
+ *
+ * \param guestprofiler profiler that is being deleted
+ */
+WASM_API_EXTERN void wasmtime_guestprofiler_delete(
+    /* own */ wasmtime_guestprofiler_t *guestprofiler);
+
+/**
+ * \typedef wasmtime_guestprofiler_modules_t
+ * \brief Alias to #wasmtime_guestprofiler_modules
+ *
+ * \struct #wasmtime_guestprofiler_modules
+ * \brief Tuple of name and module for passing into #wasmtime_guestprofiler_new.
+ */
+typedef struct wasmtime_guestprofiler_modules {
+  const wasm_name_t *name; //!< Name recorded in the profile.
+  const wasmtime_module_t
+      *mod; //!< Module that is being allowed to appear in captured stack trace.
+} wasmtime_guestprofiler_modules_t;
+
+/**
+ * \brief Begin profiling a new guest.
+ *
+ * \param module_name    name recorded in the profile
+ * \param interval_nanos intended sampling interval in nanoseconds recorded in
+ *                       the profile
+ * \param modules        modules and associated names that will appear in
+ *                       captured stack traces, pointer to the first element
+ * \param modules_len    count of elements in `modules`
+ *
+ * \return Created profiler that is owned by the caller.
+ *
+ * This function does not take ownership of the arguments.
+ *
+ * For more information see the Rust documentation at:
+ * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html#method.new
+ */
+WASM_API_EXTERN /* own */ wasmtime_guestprofiler_t *wasmtime_guestprofiler_new(
+    const wasm_name_t *module_name, uint64_t interval_nanos,
+    const wasmtime_guestprofiler_modules_t *modules, size_t modules_len);
+
+/**
+ * \brief Add a sample to the profile.
+ *
+ * \param guestprofiler the profiler the sample is being added to
+ * \param store         store that is being used to collect the backtraces
+ *
+ * This function does not take ownership of the arguments.
+ *
+ * For more information see the Rust documentation at:
+ * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html#method.sample
+ */
+WASM_API_EXTERN void
+wasmtime_guestprofiler_sample(wasmtime_guestprofiler_t *guestprofiler,
+                              const wasmtime_store_t *store);
+
+/**
+ * \brief Writes out the captured profile.
+ *
+ * \param guestprofiler the profiler which is being finished and deleted
+ * \param out           pointer to where #wasm_byte_vec_t containing generated
+ *                      file will be written
+ *
+ * \return Returns #wasmtime_error_t owned by the caller in case of error,
+ * `NULL` otherwise.
+ *
+ * This function takes ownership of `guestprofiler`, even when error is
+ * returned.
+ * Only when returning without error `out` is filled with #wasm_byte_vec_t owned
+ * by the caller.
+ *
+ * For more information see the Rust documentation at:
+ * https://docs.wasmtime.dev/api/wasmtime/struct.GuestProfiler.html#method.finish
+ */
+WASM_API_EXTERN /* own */ wasmtime_error_t *
+wasmtime_guestprofiler_finish(/* own */ wasmtime_guestprofiler_t *guestprofiler,
+                              /* own */ wasm_byte_vec_t *out);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // WASMTIME_PROFILING_H
diff --git a/crates/c-api/src/lib.rs b/crates/c-api/src/lib.rs
index fb686427e..42f617196 100644
--- a/crates/c-api/src/lib.rs
+++ b/crates/c-api/src/lib.rs
@@ -23,6 +23,8 @@ mod instance;
 mod linker;
 mod memory;
 mod module;
+#[cfg(feature = "profiling")]
+mod profiling;
 mod r#ref;
 mod store;
 mod table;
diff --git a/crates/c-api/src/profiling.rs b/crates/c-api/src/profiling.rs
new file mode 100644
index 000000000..25fa32ed7
--- /dev/null
+++ b/crates/c-api/src/profiling.rs
@@ -0,0 +1,64 @@
+use crate::{wasm_byte_vec_t, wasm_name_t, wasmtime_error_t, wasmtime_module_t, wasmtime_store_t};
+use std::slice;
+use std::str::from_utf8;
+use std::time::Duration;
+use wasmtime::GuestProfiler;
+
+pub struct wasmtime_guestprofiler_t {
+    guest_profiler: GuestProfiler,
+}
+
+wasmtime_c_api_macros::declare_own!(wasmtime_guestprofiler_t);
+
+#[repr(C)]
+pub struct wasmtime_guestprofiler_modules_t<'a> {
+    name: &'a wasm_name_t,
+    module: &'a wasmtime_module_t,
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn wasmtime_guestprofiler_new(
+    module_name: &wasm_name_t,
+    interval_nanos: u64,
+    modules: *const wasmtime_guestprofiler_modules_t,
+    modules_len: usize,
+) -> Box<wasmtime_guestprofiler_t> {
+    let module_name = from_utf8(&module_name.as_slice()).expect("not valid utf-8");
+    let list = slice::from_raw_parts(modules, modules_len)
+        .iter()
+        .map(|entry| {
+            (
+                from_utf8(entry.name.as_slice())
+                    .expect("not valid utf-8")
+                    .to_owned(),
+                entry.module.module.clone(),
+            )
+        })
+        .collect();
+    Box::new(wasmtime_guestprofiler_t {
+        guest_profiler: GuestProfiler::new(module_name, Duration::from_nanos(interval_nanos), list),
+    })
+}
+
+#[no_mangle]
+pub extern "C" fn wasmtime_guestprofiler_sample(
+    guestprofiler: &mut wasmtime_guestprofiler_t,
+    store: &wasmtime_store_t,
+) {
+    guestprofiler.guest_profiler.sample(&store.store);
+}
+
+#[no_mangle]
+pub extern "C" fn wasmtime_guestprofiler_finish(
+    guestprofiler: Box<wasmtime_guestprofiler_t>,
+    out: &mut wasm_byte_vec_t,
+) -> Option<Box<wasmtime_error_t>> {
+    let mut buf = vec![];
+    match guestprofiler.guest_profiler.finish(&mut buf) {
+        Ok(()) => {
+            out.set_buffer(buf);
+            None
+        }
+        Err(e) => Some(Box::new(e.into())),
+    }
+}
diff --git a/crates/cranelift/src/builder.rs b/crates/cranelift/src/builder.rs
index 026960dd4..2c8583237 100644
--- a/crates/cranelift/src/builder.rs
+++ b/crates/cranelift/src/builder.rs
@@ -16,7 +16,7 @@ use wasmtime_cranelift_shared::isa_builder::IsaBuilder;
 use wasmtime_environ::{CacheStore, CompilerBuilder, Setting, Tunables};
 
 struct Builder {
-    tunables: Tunables,
+    tunables: Option<Tunables>,
     inner: IsaBuilder<CodegenResult<OwnedTargetIsa>>,
     linkopts: LinkOptions,
     cache_store: Option<Arc<dyn CacheStore>>,
@@ -39,7 +39,7 @@ pub struct LinkOptions {
 
 pub fn builder(triple: Option<Triple>) -> Result<Box<dyn CompilerBuilder>> {
     Ok(Box::new(Builder {
-        tunables: Tunables::default(),
+        tunables: None,
         inner: IsaBuilder::new(triple, |triple| isa::lookup(triple).map_err(|e| e.into()))?,
         linkopts: LinkOptions::default(),
         cache_store: None,
@@ -82,14 +82,17 @@ impl CompilerBuilder for Builder {
     }
 
     fn set_tunables(&mut self, tunables: Tunables) -> Result<()> {
-        self.tunables = tunables;
+        self.tunables = Some(tunables);
         Ok(())
     }
 
     fn build(&self) -> Result<Box<dyn wasmtime_environ::Compiler>> {
         let isa = self.inner.build()?;
         Ok(Box::new(crate::compiler::Compiler::new(
-            self.tunables.clone(),
+            self.tunables
+                .as_ref()
+                .expect("set_tunables not called")
+                .clone(),
             isa,
             self.cache_store.clone(),
             self.linkopts.clone(),
diff --git a/crates/cranelift/src/debug/transform/attr.rs b/crates/cranelift/src/debug/transform/attr.rs
index 13bf62e9f..354bcdace 100644
--- a/crates/cranelift/src/debug/transform/attr.rs
+++ b/crates/cranelift/src/debug/transform/attr.rs
@@ -95,7 +95,7 @@ where
                 let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0));
                 write::AttributeValue::Address(addr)
             }
-            AttributeValue::Block(d) => write::AttributeValue::Block(d.to_slice()?.to_vec()),
+            AttributeValue::Block(d) => write::AttributeValue::Block(d.to_slice()?.into_owned()),
             AttributeValue::Udata(u) => write::AttributeValue::Udata(u),
             AttributeValue::Data1(d) => write::AttributeValue::Data1(d),
             AttributeValue::Data2(d) => write::AttributeValue::Data2(d),
@@ -295,6 +295,7 @@ where
                 pending_di_refs.insert(current_scope_id, attr.name(), offset);
                 continue;
             }
+            AttributeValue::String(d) => write::AttributeValue::String(d.to_slice()?.into_owned()),
             a => bail!("Unexpected attribute: {:?}", a),
         };
         let current_scope = out_unit.get_mut(current_scope_id);
diff --git a/crates/environ/src/lib.rs b/crates/environ/src/lib.rs
index 9f34dd940..4df17658a 100644
--- a/crates/environ/src/lib.rs
+++ b/crates/environ/src/lib.rs
@@ -33,7 +33,7 @@ pub use crate::ref_bits::*;
 pub use crate::scopevec::ScopeVec;
 pub use crate::stack_map::StackMap;
 pub use crate::trap_encoding::*;
-pub use crate::tunables::Tunables;
+pub use crate::tunables::*;
 pub use crate::vmoffsets::*;
 pub use object;
 
diff --git a/crates/environ/src/tunables.rs b/crates/environ/src/tunables.rs
index 7ba3e6fdf..4ff360fcb 100644
--- a/crates/environ/src/tunables.rs
+++ b/crates/environ/src/tunables.rs
@@ -1,7 +1,7 @@
 use serde_derive::{Deserialize, Serialize};
 
 /// Tunable parameters for WebAssembly compilation.
-#[derive(Clone, Hash, Serialize, Deserialize)]
+#[derive(Clone, Hash, Serialize, Deserialize, Debug)]
 pub struct Tunables {
     /// For static heaps, the size in wasm pages of the heap protected by bounds
     /// checking.
@@ -56,62 +56,85 @@ pub struct Tunables {
     pub tail_callable: bool,
 }
 
-impl Default for Tunables {
-    fn default() -> Self {
-        let (static_memory_bound, static_memory_offset_guard_size) = if cfg!(miri) {
+impl Tunables {
+    /// Returns a `Tunables` configuration assumed for running code on the host.
+    pub fn default_host() -> Self {
+        if cfg!(miri) {
+            Tunables::default_miri()
+        } else if cfg!(target_pointer_width = "32") {
+            Tunables::default_u32()
+        } else if cfg!(target_pointer_width = "64") {
+            Tunables::default_u64()
+        } else {
+            panic!("unsupported target_pointer_width");
+        }
+    }
+
+    /// Returns the default set of tunables for running under MIRI.
+    pub fn default_miri() -> Tunables {
+        Tunables {
             // No virtual memory tricks are available on miri so make these
             // limits quite conservative.
-            ((1 << 20) / crate::WASM_PAGE_SIZE as u64, 0)
-        } else if cfg!(target_pointer_width = "64") {
+            static_memory_bound: (1 << 20) / crate::WASM_PAGE_SIZE as u64,
+            static_memory_offset_guard_size: 0,
+            dynamic_memory_offset_guard_size: 0,
+            dynamic_memory_growth_reserve: 0,
+
+            // General options which have the same defaults regardless of
+            // architecture.
+            generate_native_debuginfo: false,
+            parse_wasm_debuginfo: true,
+            consume_fuel: false,
+            epoch_interruption: false,
+            static_memory_bound_is_maximum: false,
+            guard_before_linear_memory: true,
+            generate_address_map: true,
+            debug_adapter_modules: false,
+            relaxed_simd_deterministic: false,
+            tail_callable: false,
+        }
+    }
+
+    /// Returns the default set of tunables for running under a 32-bit host.
+    pub fn default_u32() -> Tunables {
+        Tunables {
+            // For 32-bit we scale way down to 10MB of reserved memory. This
+            // impacts performance severely but allows us to have more than a
+            // few instances running around.
+            static_memory_bound: (10 * (1 << 20)) / crate::WASM_PAGE_SIZE as u64,
+            static_memory_offset_guard_size: 0x1_0000,
+            dynamic_memory_offset_guard_size: 0x1_0000,
+            dynamic_memory_growth_reserve: 1 << 20, // 1MB
+
+            ..Tunables::default_miri()
+        }
+    }
+
+    /// Returns the default set of tunables for running under a 64-bit host.
+    pub fn default_u64() -> Tunables {
+        Tunables {
             // 64-bit has tons of address space to static memories can have 4gb
             // address space reservations liberally by default, allowing us to
             // help eliminate bounds checks.
             //
             // Coupled with a 2 GiB address space guard it lets us translate
             // wasm offsets into x86 offsets as aggressively as we can.
-            (0x1_0000, 0x8000_0000)
-        } else if cfg!(target_pointer_width = "32") {
-            // For 32-bit we scale way down to 10MB of reserved memory. This
-            // impacts performance severely but allows us to have more than a
-            // few instances running around.
-            ((10 * (1 << 20)) / crate::WASM_PAGE_SIZE as u64, 0x1_0000)
-        } else {
-            panic!("unsupported target_pointer_width");
-        };
-        Self {
-            static_memory_bound,
-            static_memory_offset_guard_size,
+            static_memory_bound: 0x1_0000,
+            static_memory_offset_guard_size: 0x8000_0000,
 
             // Size in bytes of the offset guard for dynamic memories.
             //
             // Allocate a small guard to optimize common cases but without
             // wasting too much memory.
-            dynamic_memory_offset_guard_size: if cfg!(miri) { 0 } else { 0x1_0000 },
+            dynamic_memory_offset_guard_size: 0x1_0000,
 
             // We've got lots of address space on 64-bit so use a larger
             // grow-into-this area, but on 32-bit we aren't as lucky. Miri is
             // not exactly fast so reduce memory consumption instead of trying
             // to avoid memory movement.
-            dynamic_memory_growth_reserve: if cfg!(miri) {
-                0
-            } else if cfg!(target_pointer_width = "64") {
-                2 << 30 // 2GB
-            } else if cfg!(target_pointer_width = "32") {
-                1 << 20 // 1MB
-            } else {
-                panic!("unsupported target_pointer_width");
-            },
+            dynamic_memory_growth_reserve: 2 << 30, // 2GB
 
-            generate_native_debuginfo: false,
-            parse_wasm_debuginfo: true,
-            consume_fuel: false,
-            epoch_interruption: false,
-            static_memory_bound_is_maximum: false,
-            guard_before_linear_memory: true,
-            generate_address_map: true,
-            debug_adapter_modules: false,
-            relaxed_simd_deterministic: false,
-            tail_callable: false,
+            ..Tunables::default_miri()
         }
     }
 }
diff --git a/crates/runtime/src/instance/allocator/pooling.rs b/crates/runtime/src/instance/allocator/pooling.rs
index 928069b5e..a7154c7c9 100644
--- a/crates/runtime/src/instance/allocator/pooling.rs
+++ b/crates/runtime/src/instance/allocator/pooling.rs
@@ -579,7 +579,7 @@ mod test {
                 &config,
                 &Tunables {
                     static_memory_bound: 1,
-                    ..Tunables::default()
+                    ..Tunables::default_host()
                 },
             )
             .map_err(|e| e.to_string())
@@ -603,7 +603,7 @@ mod test {
             async_stack_zeroing: true,
             ..PoolingInstanceAllocatorConfig::default()
         };
-        let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default())?;
+        let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default_host())?;
 
         unsafe {
             for _ in 0..255 {
@@ -637,7 +637,7 @@ mod test {
             async_stack_zeroing: false,
             ..PoolingInstanceAllocatorConfig::default()
         };
-        let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default())?;
+        let allocator = PoolingInstanceAllocator::new(&config, &Tunables::default_host())?;
 
         unsafe {
             for i in 0..255 {
diff --git a/crates/runtime/src/instance/allocator/pooling/memory_pool.rs b/crates/runtime/src/instance/allocator/pooling/memory_pool.rs
index 9658e43d8..414ecb797 100644
--- a/crates/runtime/src/instance/allocator/pooling/memory_pool.rs
+++ b/crates/runtime/src/instance/allocator/pooling/memory_pool.rs
@@ -774,7 +774,7 @@ mod tests {
             &Tunables {
                 static_memory_bound: 1,
                 static_memory_offset_guard_size: 0,
-                ..Tunables::default()
+                ..Tunables::default_host()
             },
         )?;
 
@@ -808,7 +808,7 @@ mod tests {
             &Tunables {
                 static_memory_bound: 1,
                 static_memory_offset_guard_size: 0,
-                ..Tunables::default()
+                ..Tunables::default_host()
             },
         )
         .unwrap();
@@ -828,7 +828,7 @@ mod tests {
             memory_protection_keys: MpkEnabled::Enable,
             ..PoolingInstanceAllocatorConfig::default()
         };
-        let pool = MemoryPool::new(&config, &Tunables::default()).unwrap();
+        let pool = MemoryPool::new(&config, &Tunables::default_host()).unwrap();
         assert!(pool.stripes.len() >= 2);
 
         let max_memory_slots = config.limits.total_memories;
diff --git a/crates/wasi-common/Cargo.toml b/crates/wasi-common/Cargo.toml
index c0479b9be..8b4898c80 100644
--- a/crates/wasi-common/Cargo.toml
+++ b/crates/wasi-common/Cargo.toml
@@ -63,4 +63,4 @@ trace_log = [ "wiggle/tracing_log", "tracing/log" ]
 # crate if they want the snapshots to have metadata available.
 wiggle_metadata = ["wiggle/wiggle_metadata"]
 # This feature enables integration with wasmtime.
-wasmtime = ["dep:wasmtime", "wiggle/wasmtime"]
\ No newline at end of file
+wasmtime = ["dep:wasmtime", "wiggle/wasmtime"]
diff --git a/crates/wasi-nn/Cargo.toml b/crates/wasi-nn/Cargo.toml
index 64fe8604d..62f582cce 100644
--- a/crates/wasi-nn/Cargo.toml
+++ b/crates/wasi-nn/Cargo.toml
@@ -17,10 +17,10 @@ workspace = true
 [dependencies]
 # These dependencies are necessary for the WITX-generation macros to work:
 anyhow = { workspace = true }
-wiggle = { workspace = true }
+wiggle = { workspace = true, features = ["wasmtime"] }
 
 # This dependency is necessary for the WIT-generation macros to work:
-wasmtime = { workspace = true, features = ["component-model"] }
+wasmtime = { workspace = true, features = ["component-model", "runtime"] }
 
 # These dependencies are necessary for the wasi-nn implementation:
 tracing = { workspace = true }
diff --git a/crates/wasmtime/src/compile.rs b/crates/wasmtime/src/compile.rs
index 71bc5a96c..b8811619d 100644
--- a/crates/wasmtime/src/compile.rs
+++ b/crates/wasmtime/src/compile.rs
@@ -54,7 +54,7 @@ pub(crate) fn build_artifacts<T: FinishedObject>(
     engine: &Engine,
     wasm: &[u8],
 ) -> Result<(T, Option<(CompiledModuleInfo, ModuleTypes)>)> {
-    let tunables = &engine.config().tunables;
+    let tunables = engine.tunables();
 
     // First a `ModuleEnvironment` is created which records type information
     // about the wasm module. This is where the WebAssembly is parsed and
@@ -117,7 +117,7 @@ pub(crate) fn build_component_artifacts<T: FinishedObject>(
     use wasmtime_environ::component::{CompiledComponentInfo, ComponentArtifacts};
     use wasmtime_environ::ScopeVec;
 
-    let tunables = &engine.config().tunables;
+    let tunables = engine.tunables();
     let compiler = engine.compiler();
 
     let scope = ScopeVec::new();
@@ -610,7 +610,7 @@ impl FunctionIndices {
         // `symbol_ids_and_locs[i]` is the symbol ID and function location of
         // `compiled_funcs[i]`.
         let compiler = engine.compiler();
-        let tunables = &engine.config().tunables;
+        let tunables = engine.tunables();
         let symbol_ids_and_locs = compiler.append_code(
             &mut obj,
             &compiled_funcs,
diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs
index 75a1c616f..944afd255 100644
--- a/crates/wasmtime/src/config.rs
+++ b/crates/wasmtime/src/config.rs
@@ -6,7 +6,7 @@ use std::fmt;
 use std::path::Path;
 use std::str::FromStr;
 use std::sync::Arc;
-use target_lexicon::Architecture;
+use target_lexicon::{Architecture, PointerWidth};
 use wasmparser::WasmFeatures;
 #[cfg(feature = "cache")]
 use wasmtime_cache::CacheConfig;
@@ -103,8 +103,8 @@ pub struct Config {
     #[cfg(any(feature = "cranelift", feature = "winch"))]
     compiler_config: CompilerConfig,
     profiling_strategy: ProfilingStrategy,
+    tunables: ConfigTunables,
 
-    pub(crate) tunables: Tunables,
     #[cfg(feature = "cache")]
     pub(crate) cache_config: CacheConfig,
     #[cfg(feature = "runtime")]
@@ -130,6 +130,24 @@ pub struct Config {
     pub(crate) macos_use_mach_ports: bool,
 }
 
+#[derive(Default, Clone)]
+struct ConfigTunables {
+    static_memory_bound: Option<u64>,
+    static_memory_offset_guard_size: Option<u64>,
+    dynamic_memory_offset_guard_size: Option<u64>,
+    dynamic_memory_growth_reserve: Option<u64>,
+    generate_native_debuginfo: Option<bool>,
+    parse_wasm_debuginfo: Option<bool>,
+    consume_fuel: Option<bool>,
+    epoch_interruption: Option<bool>,
+    static_memory_bound_is_maximum: Option<bool>,
+    guard_before_linear_memory: Option<bool>,
+    generate_address_map: Option<bool>,
+    debug_adapter_modules: Option<bool>,
+    relaxed_simd_deterministic: Option<bool>,
+    tail_callable: Option<bool>,
+}
+
 /// User-provided configuration for the compiler.
 #[cfg(any(feature = "cranelift", feature = "winch"))]
 #[derive(Debug, Clone)]
@@ -190,7 +208,7 @@ impl Config {
     /// specified.
     pub fn new() -> Self {
         let mut ret = Self {
-            tunables: Tunables::default(),
+            tunables: ConfigTunables::default(),
             #[cfg(any(feature = "cranelift", feature = "winch"))]
             compiler_config: CompilerConfig::default(),
             #[cfg(feature = "cache")]
@@ -386,7 +404,7 @@ impl Config {
     ///
     /// By default this option is `false`.
     pub fn debug_info(&mut self, enable: bool) -> &mut Self {
-        self.tunables.generate_native_debuginfo = enable;
+        self.tunables.generate_native_debuginfo = Some(enable);
         self
     }
 
@@ -433,13 +451,13 @@ impl Config {
     pub fn wasm_backtrace_details(&mut self, enable: WasmBacktraceDetails) -> &mut Self {
         self.wasm_backtrace_details_env_used = false;
         self.tunables.parse_wasm_debuginfo = match enable {
-            WasmBacktraceDetails::Enable => true,
-            WasmBacktraceDetails::Disable => false,
+            WasmBacktraceDetails::Enable => Some(true),
+            WasmBacktraceDetails::Disable => Some(false),
             WasmBacktraceDetails::Environment => {
                 self.wasm_backtrace_details_env_used = true;
                 std::env::var("WASMTIME_BACKTRACE_DETAILS")
-                    .map(|s| s == "1")
-                    .unwrap_or(false)
+                    .map(|s| Some(s == "1"))
+                    .unwrap_or(Some(false))
             }
         };
         self
@@ -482,7 +500,7 @@ impl Config {
     ///
     /// [`Store`]: crate::Store
     pub fn consume_fuel(&mut self, enable: bool) -> &mut Self {
-        self.tunables.consume_fuel = enable;
+        self.tunables.consume_fuel = Some(enable);
         self
     }
 
@@ -576,7 +594,7 @@ impl Config {
     /// - [`Store::epoch_deadline_callback`](crate::Store::epoch_deadline_callback)
     /// - [`Store::epoch_deadline_async_yield_and_update`](crate::Store::epoch_deadline_async_yield_and_update)
     pub fn epoch_interruption(&mut self, enable: bool) -> &mut Self {
-        self.tunables.epoch_interruption = enable;
+        self.tunables.epoch_interruption = Some(enable);
         self
     }
 
@@ -667,7 +685,7 @@ impl Config {
     /// [WebAssembly tail calls proposal]: https://github.com/WebAssembly/tail-call
     pub fn wasm_tail_call(&mut self, enable: bool) -> &mut Self {
         self.features.tail_call = enable;
-        self.tunables.tail_callable = enable;
+        self.tunables.tail_callable = Some(enable);
         self
     }
 
@@ -794,7 +812,7 @@ impl Config {
     ///
     /// [proposal]: https://github.com/webassembly/relaxed-simd
     pub fn relaxed_simd_deterministic(&mut self, enable: bool) -> &mut Self {
-        self.tunables.relaxed_simd_deterministic = enable;
+        self.tunables.relaxed_simd_deterministic = Some(enable);
         self
     }
 
@@ -1239,7 +1257,7 @@ impl Config {
     /// `PoolingAllocatorConfig::memory_protection_keys` for details.
     pub fn static_memory_maximum_size(&mut self, max_size: u64) -> &mut Self {
         let max_pages = max_size / u64::from(wasmtime_environ::WASM_PAGE_SIZE);
-        self.tunables.static_memory_bound = max_pages;
+        self.tunables.static_memory_bound = Some(max_pages);
         self
     }
 
@@ -1255,7 +1273,7 @@ impl Config {
     /// For the difference between static and dynamic memories, see the
     /// [`Config::static_memory_maximum_size`].
     pub fn static_memory_forced(&mut self, force: bool) -> &mut Self {
-        self.tunables.static_memory_bound_is_maximum = force;
+        self.tunables.static_memory_bound_is_maximum = Some(force);
         self
     }
 
@@ -1311,7 +1329,7 @@ impl Config {
     /// than the value configured for [`Config::dynamic_memory_guard_size`].
     pub fn static_memory_guard_size(&mut self, guard_size: u64) -> &mut Self {
         let guard_size = round_up_to_pages(guard_size);
-        self.tunables.static_memory_offset_guard_size = guard_size;
+        self.tunables.static_memory_offset_guard_size = Some(guard_size);
         self
     }
 
@@ -1344,7 +1362,7 @@ impl Config {
     /// than the value configured for [`Config::static_memory_guard_size`].
     pub fn dynamic_memory_guard_size(&mut self, guard_size: u64) -> &mut Self {
         let guard_size = round_up_to_pages(guard_size);
-        self.tunables.dynamic_memory_offset_guard_size = guard_size;
+        self.tunables.dynamic_memory_offset_guard_size = Some(guard_size);
         self
     }
 
@@ -1383,7 +1401,7 @@ impl Config {
     /// For 64-bit platforms this defaults to 2GB, and for 32-bit platforms this
     /// defaults to 1MB.
     pub fn dynamic_memory_reserved_for_growth(&mut self, reserved: u64) -> &mut Self {
-        self.tunables.dynamic_memory_growth_reserve = round_up_to_pages(reserved);
+        self.tunables.dynamic_memory_growth_reserve = Some(round_up_to_pages(reserved));
         self
     }
 
@@ -1408,7 +1426,7 @@ impl Config {
     ///
     /// This value defaults to `true`.
     pub fn guard_before_linear_memory(&mut self, guard: bool) -> &mut Self {
-        self.tunables.guard_before_linear_memory = guard;
+        self.tunables.guard_before_linear_memory = Some(guard);
         self
     }
 
@@ -1455,7 +1473,7 @@ impl Config {
     /// numbers if so configured as well (and the original wasm module has DWARF
     /// debugging information present).
     pub fn generate_address_map(&mut self, generate: bool) -> &mut Self {
-        self.tunables.generate_address_map = generate;
+        self.tunables.generate_address_map = Some(generate);
         self
     }
 
@@ -1589,7 +1607,7 @@ impl Config {
         self
     }
 
-    pub(crate) fn validate(&self) -> Result<()> {
+    pub(crate) fn validate(&self) -> Result<Tunables> {
         if self.features.reference_types && !self.features.bulk_memory {
             bail!("feature 'reference_types' requires 'bulk_memory' to be enabled");
         }
@@ -1603,27 +1621,73 @@ impl Config {
         if self.max_wasm_stack == 0 {
             bail!("max_wasm_stack size cannot be zero");
         }
-        if self.tunables.static_memory_offset_guard_size
-            < self.tunables.dynamic_memory_offset_guard_size
-        {
-            bail!("static memory guard size cannot be smaller than dynamic memory guard size");
-        }
         #[cfg(not(feature = "wmemcheck"))]
         if self.wmemcheck {
             bail!("wmemcheck (memory checker) was requested but is not enabled in this build");
         }
 
-        Ok(())
+        #[cfg(not(any(feature = "cranelift", feature = "winch")))]
+        let mut tunables = Tunables::default_host();
+        #[cfg(any(feature = "cranelift", feature = "winch"))]
+        let mut tunables = match &self.compiler_config.target.as_ref() {
+            Some(target) => match target.pointer_width() {
+                Ok(PointerWidth::U32) => Tunables::default_u32(),
+                Ok(PointerWidth::U64) => Tunables::default_u64(),
+                _ => bail!("unknown pointer width"),
+            },
+            None => Tunables::default_host(),
+        };
+
+        macro_rules! set_fields {
+            ($($field:ident)*) => (
+                let ConfigTunables {
+                    $($field,)*
+                } = &self.tunables;
+
+                $(
+                    if let Some(e) = $field {
+                        tunables.$field = *e;
+                    }
+                )*
+            )
+        }
+
+        set_fields! {
+            static_memory_bound
+            static_memory_offset_guard_size
+            dynamic_memory_offset_guard_size
+            dynamic_memory_growth_reserve
+            generate_native_debuginfo
+            parse_wasm_debuginfo
+            consume_fuel
+            epoch_interruption
+            static_memory_bound_is_maximum
+            guard_before_linear_memory
+            generate_address_map
+            debug_adapter_modules
+            relaxed_simd_deterministic
+            tail_callable
+        }
+
+        if tunables.static_memory_offset_guard_size < tunables.dynamic_memory_offset_guard_size {
+            bail!("static memory guard size cannot be smaller than dynamic memory guard size");
+        }
+        Ok(tunables)
     }
 
     #[cfg(feature = "runtime")]
-    pub(crate) fn build_allocator(&self) -> Result<Box<dyn InstanceAllocator + Send + Sync>> {
+    pub(crate) fn build_allocator(
+        &self,
+        tunables: &Tunables,
+    ) -> Result<Box<dyn InstanceAllocator + Send + Sync>> {
         #[cfg(feature = "async")]
         let stack_size = self.async_stack_size;
 
         #[cfg(not(feature = "async"))]
         let stack_size = 0;
 
+        let _ = tunables;
+
         match &self.allocation_strategy {
             InstanceAllocationStrategy::OnDemand => {
                 #[allow(unused_mut)]
@@ -1642,8 +1706,7 @@ impl Config {
                 let mut config = config.config;
                 config.stack_size = stack_size;
                 Ok(Box::new(wasmtime_runtime::PoolingInstanceAllocator::new(
-                    &config,
-                    &self.tunables,
+                    &config, tunables,
                 )?))
             }
         }
@@ -1660,7 +1723,10 @@ impl Config {
     }
 
     #[cfg(any(feature = "cranelift", feature = "winch"))]
-    pub(crate) fn build_compiler(mut self) -> Result<(Self, Box<dyn wasmtime_environ::Compiler>)> {
+    pub(crate) fn build_compiler(
+        mut self,
+        tunables: &Tunables,
+    ) -> Result<(Self, Box<dyn wasmtime_environ::Compiler>)> {
         let target = self.compiler_config.target.clone();
 
         let mut compiler = match self.compiler_config.strategy {
@@ -1767,7 +1833,7 @@ impl Config {
             compiler.enable_incremental_compilation(cache_store.clone())?;
         }
 
-        compiler.set_tunables(self.tunables.clone())?;
+        compiler.set_tunables(tunables.clone())?;
         compiler.wmemcheck(self.compiler_config.wmemcheck);
 
         Ok((self, compiler.build()?))
@@ -1778,7 +1844,7 @@ impl Config {
     /// then are necessary.
     #[cfg(feature = "component-model")]
     pub fn debug_adapter_modules(&mut self, debug: bool) -> &mut Self {
-        self.tunables.debug_adapter_modules = debug;
+        self.tunables.debug_adapter_modules = Some(debug);
         self
     }
 
@@ -1849,7 +1915,6 @@ impl fmt::Debug for Config {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut f = f.debug_struct("Config");
         f.field("debug_info", &self.tunables.generate_native_debuginfo)
-            .field("parse_wasm_debuginfo", &self.tunables.parse_wasm_debuginfo)
             .field("wasm_threads", &self.features.threads)
             .field("wasm_reference_types", &self.features.reference_types)
             .field(
@@ -1860,28 +1925,30 @@ impl fmt::Debug for Config {
             .field("wasm_simd", &self.features.simd)
             .field("wasm_relaxed_simd", &self.features.relaxed_simd)
             .field("wasm_multi_value", &self.features.multi_value)
-            .field(
-                "static_memory_maximum_size",
-                &(u64::from(self.tunables.static_memory_bound)
-                    * u64::from(wasmtime_environ::WASM_PAGE_SIZE)),
-            )
-            .field(
-                "static_memory_guard_size",
-                &self.tunables.static_memory_offset_guard_size,
-            )
-            .field(
-                "dynamic_memory_guard_size",
-                &self.tunables.dynamic_memory_offset_guard_size,
-            )
-            .field(
-                "guard_before_linear_memory",
-                &self.tunables.guard_before_linear_memory,
-            )
             .field("parallel_compilation", &self.parallel_compilation);
         #[cfg(any(feature = "cranelift", feature = "winch"))]
         {
             f.field("compiler_config", &self.compiler_config);
         }
+
+        if let Some(enable) = self.tunables.parse_wasm_debuginfo {
+            f.field("parse_wasm_debuginfo", &enable);
+        }
+        if let Some(size) = self.tunables.static_memory_bound {
+            f.field(
+                "static_memory_maximum_size",
+                &(u64::from(size) * u64::from(wasmtime_environ::WASM_PAGE_SIZE)),
+            );
+        }
+        if let Some(size) = self.tunables.static_memory_offset_guard_size {
+            f.field("static_memory_guard_size", &size);
+        }
+        if let Some(size) = self.tunables.dynamic_memory_offset_guard_size {
+            f.field("dynamic_memory_guard_size", &size);
+        }
+        if let Some(enable) = self.tunables.guard_before_linear_memory {
+            f.field("guard_before_linear_memory", &enable);
+        }
         f.finish()
     }
 }
diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs
index 567838f2f..2a6aba471 100644
--- a/crates/wasmtime/src/engine.rs
+++ b/crates/wasmtime/src/engine.rs
@@ -9,7 +9,7 @@ use std::path::Path;
 use std::sync::atomic::{AtomicU64, Ordering};
 use std::sync::Arc;
 use wasmtime_environ::obj;
-use wasmtime_environ::{FlagValue, ObjectKind};
+use wasmtime_environ::{FlagValue, ObjectKind, Tunables};
 
 mod serialization;
 
@@ -37,27 +37,28 @@ mod serialization;
 /// default settings.
 #[derive(Clone)]
 pub struct Engine {
-    pub(crate) inner: Arc<EngineInner>,
+    inner: Arc<EngineInner>,
 }
 
-pub(crate) struct EngineInner {
-    pub(crate) config: Config,
+struct EngineInner {
+    config: Config,
+    tunables: Tunables,
     #[cfg(any(feature = "cranelift", feature = "winch"))]
-    pub(crate) compiler: Box<dyn wasmtime_environ::Compiler>,
+    compiler: Box<dyn wasmtime_environ::Compiler>,
     #[cfg(feature = "runtime")]
-    pub(crate) allocator: Box<dyn wasmtime_runtime::InstanceAllocator + Send + Sync>,
+    allocator: Box<dyn wasmtime_runtime::InstanceAllocator + Send + Sync>,
     #[cfg(feature = "runtime")]
-    pub(crate) profiler: Box<dyn crate::profiling_agent::ProfilingAgent>,
+    profiler: Box<dyn crate::profiling_agent::ProfilingAgent>,
     #[cfg(feature = "runtime")]
-    pub(crate) signatures: TypeRegistry,
+    signatures: TypeRegistry,
     #[cfg(feature = "runtime")]
-    pub(crate) epoch: AtomicU64,
+    epoch: AtomicU64,
     #[cfg(feature = "runtime")]
-    pub(crate) unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator,
+    unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator,
 
     /// One-time check of whether the compiler's settings, if present, are
     /// compatible with the native host.
-    pub(crate) compatible_with_native_host: OnceCell<Result<(), String>>,
+    compatible_with_native_host: OnceCell<Result<(), String>>,
 }
 
 impl Default for Engine {
@@ -94,17 +95,17 @@ impl Engine {
         }
 
         let config = config.clone();
-        config.validate()?;
+        let tunables = config.validate()?;
 
         #[cfg(any(feature = "cranelift", feature = "winch"))]
-        let (config, compiler) = config.build_compiler()?;
+        let (config, compiler) = config.build_compiler(&tunables)?;
 
         Ok(Engine {
             inner: Arc::new(EngineInner {
                 #[cfg(any(feature = "cranelift", feature = "winch"))]
                 compiler,
                 #[cfg(feature = "runtime")]
-                allocator: config.build_allocator()?,
+                allocator: config.build_allocator(&tunables)?,
                 #[cfg(feature = "runtime")]
                 profiler: config.build_profiler()?,
                 #[cfg(feature = "runtime")]
@@ -115,6 +116,7 @@ impl Engine {
                 unique_id_allocator: wasmtime_runtime::CompiledModuleIdAllocator::new(),
                 compatible_with_native_host: OnceCell::new(),
                 config,
+                tunables,
             }),
         })
     }
@@ -161,6 +163,10 @@ impl Engine {
         }
     }
 
+    pub(crate) fn tunables(&self) -> &Tunables {
+        &self.inner.tunables
+    }
+
     /// Returns whether the engine `a` and `b` refer to the same configuration.
     pub fn same(a: &Engine, b: &Engine) -> bool {
         Arc::ptr_eq(&a.inner, &b.inner)
diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs
index 410776d45..f4063bd6e 100644
--- a/crates/wasmtime/src/engine/serialization.rs
+++ b/crates/wasmtime/src/engine/serialization.rs
@@ -231,7 +231,7 @@ impl Metadata<'_> {
             target: engine.compiler().triple().to_string(),
             shared_flags: engine.compiler().flags(),
             isa_flags: engine.compiler().isa_flags(),
-            tunables: engine.config().tunables.clone(),
+            tunables: engine.tunables().clone(),
             features: WasmFeatures {
                 reference_types,
                 multi_value,
@@ -254,7 +254,7 @@ impl Metadata<'_> {
         self.check_triple(engine)?;
         self.check_shared_flags(engine)?;
         self.check_isa_flags(engine)?;
-        self.check_tunables(&engine.config().tunables)?;
+        self.check_tunables(&engine.tunables())?;
         self.check_features(&engine.config().features)?;
         Ok(())
     }
diff --git a/crates/wasmtime/src/runtime/memory.rs b/crates/wasmtime/src/runtime/memory.rs
index d79736958..0a625ee21 100644
--- a/crates/wasmtime/src/runtime/memory.rs
+++ b/crates/wasmtime/src/runtime/memory.rs
@@ -732,7 +732,7 @@ impl SharedMemory {
         }
         debug_assert!(ty.maximum().is_some());
 
-        let tunables = &engine.config().tunables;
+        let tunables = engine.tunables();
         let plan = MemoryPlan::for_memory(ty.wasmtime_memory().clone(), tunables);
         let memory = wasmtime_runtime::SharedMemory::new(plan)?;
         Ok(Self(memory, engine.clone()))
diff --git a/crates/wasmtime/src/runtime/module.rs b/crates/wasmtime/src/runtime/module.rs
index 564bacd21..94c9470b6 100644
--- a/crates/wasmtime/src/runtime/module.rs
+++ b/crates/wasmtime/src/runtime/module.rs
@@ -1105,7 +1105,7 @@ impl std::hash::Hash for HashedEngineCompileEnv<'_> {
 
         // Hash configuration state read for compilation
         let config = self.0.config();
-        config.tunables.hash(hasher);
+        self.0.tunables().hash(hasher);
         config.features.hash(hasher);
         config.wmemcheck.hash(hasher);
 
diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs
index 5a5c1e94e..631f49b3b 100644
--- a/crates/wasmtime/src/runtime/store.rs
+++ b/crates/wasmtime/src/runtime/store.rs
@@ -1390,7 +1390,7 @@ impl StoreOpaque {
 
     pub fn get_fuel(&self) -> Result<u64> {
         anyhow::ensure!(
-            self.engine().config().tunables.consume_fuel,
+            self.engine().tunables().consume_fuel,
             "fuel is not configured in this store"
         );
         let injected_fuel = unsafe { *self.runtime_limits.fuel_consumed.get() };
@@ -1408,7 +1408,7 @@ impl StoreOpaque {
 
     pub fn set_fuel(&mut self, fuel: u64) -> Result<()> {
         anyhow::ensure!(
-            self.engine().config().tunables.consume_fuel,
+            self.engine().tunables().consume_fuel,
             "fuel is not configured in this store"
         );
         let injected_fuel = unsafe { &mut *self.runtime_limits.fuel_consumed.get() };
@@ -1423,7 +1423,7 @@ impl StoreOpaque {
 
     pub fn fuel_async_yield_interval(&mut self, interval: Option<u64>) -> Result<()> {
         anyhow::ensure!(
-            self.engine().config().tunables.consume_fuel,
+            self.engine().tunables().consume_fuel,
             "fuel is not configured in this store"
         );
         anyhow::ensure!(
diff --git a/crates/wasmtime/src/runtime/trampoline/func.rs b/crates/wasmtime/src/runtime/trampoline/func.rs
index ab90d5dcf..c6c0f49fb 100644
--- a/crates/wasmtime/src/runtime/trampoline/func.rs
+++ b/crates/wasmtime/src/runtime/trampoline/func.rs
@@ -94,10 +94,7 @@ where
             &mut obj,
         )?;
     engine.append_bti(&mut obj);
-    let obj = finish_object(wasmtime_environ::ObjectBuilder::new(
-        obj,
-        &engine.config().tunables,
-    ))?;
+    let obj = finish_object(wasmtime_environ::ObjectBuilder::new(obj, engine.tunables()))?;
 
     // Copy the results of JIT compilation into executable memory, and this will
     // also take care of unwind table registration.
diff --git a/crates/wasmtime/src/runtime/trampoline/memory.rs b/crates/wasmtime/src/runtime/trampoline/memory.rs
index 72c7eb891..9d2583757 100644
--- a/crates/wasmtime/src/runtime/trampoline/memory.rs
+++ b/crates/wasmtime/src/runtime/trampoline/memory.rs
@@ -40,7 +40,7 @@ pub fn create_memory(
     // preallocated (i.e., shared memory) or allocated manually below.
     let plan = wasmtime_environ::MemoryPlan::for_memory(
         memory_ty.wasmtime_memory().clone(),
-        &store.engine().config().tunables,
+        store.engine().tunables(),
     );
     let memory_id = module.memory_plans.push(plan.clone());
 
diff --git a/crates/wasmtime/src/runtime/trampoline/table.rs b/crates/wasmtime/src/runtime/trampoline/table.rs
index f351a2609..b6034dc3e 100644
--- a/crates/wasmtime/src/runtime/trampoline/table.rs
+++ b/crates/wasmtime/src/runtime/trampoline/table.rs
@@ -8,7 +8,7 @@ pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result<Instan
     let mut module = Module::new();
     let table_plan = wasmtime_environ::TablePlan::for_table(
         table.wasmtime_table().clone(),
-        &store.engine().config().tunables,
+        store.engine().tunables(),
     );
     let table_id = module.table_plans.push(table_plan);
     // TODO: can this `exports.insert` get removed?
diff --git a/examples/mpk-available.rs b/examples/mpk-available.rs
new file mode 100644
index 000000000..e48663112
--- /dev/null
+++ b/examples/mpk-available.rs
@@ -0,0 +1,16 @@
+//! This example checks if memory protection keys (MPK) are available on the
+//! current system using the
+//! [`PoolingAllocationConfig::are_memory_protection_keys_available`] API.
+
+use std::process::exit;
+use wasmtime::*;
+
+fn main() {
+    if PoolingAllocationConfig::are_memory_protection_keys_available() {
+        eprintln!("MPK is available");
+        exit(0);
+    } else {
+        eprintln!("MPK is not available");
+        exit(1);
+    }
+}
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 643372a7a..a89ee8181 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -5,190 +5,378 @@
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-bforest]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-bforest]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-codegen]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-codegen]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-codegen-meta]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-codegen-meta]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-codegen-shared]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-codegen-shared]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-control]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-control]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-entity]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-entity]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-frontend]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-frontend]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-interpreter]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-interpreter]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-isle]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-isle]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-jit]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-jit]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-module]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-module]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-native]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-native]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-object]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-object]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-reader]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-reader]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-serde]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-serde]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.cranelift-wasm]]
 version = "0.105.0"
 audited_as = "0.104.0"
 
+[[unpublished.cranelift-wasm]]
+version = "0.106.0"
+audited_as = "0.104.0"
+
 [[unpublished.wasi-cap-std-sync]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasi-cap-std-sync]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasi-common]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasi-common]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasi-tokio]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasi-tokio]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-asm-macros]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-asm-macros]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-cache]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-cache]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-cli]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-cli]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-cli-flags]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-cli-flags]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-component-macro]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-component-macro]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-component-util]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-component-util]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-cranelift]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-cranelift]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-cranelift-shared]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-cranelift-shared]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-environ]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-environ]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-explorer]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-explorer]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-fiber]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-fiber]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-jit-debug]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-jit-debug]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-jit-icache-coherence]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-jit-icache-coherence]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-runtime]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-runtime]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-types]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-types]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-wasi]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-wasi]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-wasi-http]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-wasi-http]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-wasi-nn]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-wasi-nn]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-wasi-threads]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-wasi-threads]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-wast]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-wast]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-winch]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-winch]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-wit-bindgen]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-wit-bindgen]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wasmtime-wmemcheck]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wasmtime-wmemcheck]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wiggle]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wiggle]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wiggle-generate]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wiggle-generate]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wiggle-macro]]
 version = "18.0.0"
 audited_as = "17.0.0"
 
+[[unpublished.wiggle-macro]]
+version = "19.0.0"
+audited_as = "17.0.0"
+
 [[unpublished.wiggle-test]]
 version = "0.0.0"
 audited_as = "0.1.0"
@@ -197,6 +385,10 @@ audited_as = "0.1.0"
 version = "0.16.0"
 audited_as = "0.15.0"
 
+[[unpublished.winch-codegen]]
+version = "0.17.0"
+audited_as = "0.15.0"
+
 [[publisher.aho-corasick]]
 version = "1.0.2"
 when = "2023-06-04"
diff --git a/winch/codegen/Cargo.toml b/winch/codegen/Cargo.toml
index 90c52fa5c..fe7347655 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.16.0"
+version = "0.17.0"
 edition.workspace = true
 
 [lints]
diff --git a/winch/src/compile.rs b/winch/src/compile.rs
index ec2b12acf..276055820 100644
--- a/winch/src/compile.rs
+++ b/winch/src/compile.rs
@@ -32,7 +32,7 @@ pub fn run(opt: &Options) -> Result<()> {
     let mut validator = Validator::new();
     let parser = WasmParser::new(0);
     let mut types = Default::default();
-    let tunables = Tunables::default();
+    let tunables = Tunables::default_host();
     let mut translation = ModuleEnvironment::new(&tunables, &mut validator, &mut types)
         .translate(parser, &bytes)
         .context("Failed to translate WebAssembly module")?;


Test patch:
diff --git a/ci/build-test-matrix.js b/ci/build-test-matrix.js
index 5fee846d6..b5b776fc7 100644
--- a/ci/build-test-matrix.js
+++ b/ci/build-test-matrix.js
@@ -48,6 +48,12 @@ const array = [
     "isa": "x64",
     "rust": "msrv",
   },
+  {
+    "os": "ubuntu-latest",
+    "name": "Test Linux x86_64 with MPK",
+    "filter": "linux-x64",
+    "isa": "x64"
+  },
   {
     "os": "macos-latest",
     "name": "Test macOS x86_64",
diff --git a/cranelift/filetests/filetests/isa/x64/smulhi.clif b/cranelift/filetests/filetests/isa/x64/smulhi.clif
index 25c6db99c..fb8356e4b 100644
--- a/cranelift/filetests/filetests/isa/x64/smulhi.clif
+++ b/cranelift/filetests/filetests/isa/x64/smulhi.clif
@@ -1,6 +1,37 @@
 test compile precise-output
 target x86_64
 
+function %smulhi_i8(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+  v2 = smulhi v0, v1
+  return v2
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movsbl  %dil, %eax
+;   movsbl  %sil, %r8d
+;   imull   %eax, %r8d, %eax
+;   sarq    $8, %rax, %rax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movsbl %dil, %eax
+;   movsbl %sil, %r8d
+;   imull %r8d, %eax
+;   sarq $8, %rax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
 function %f1(i16, i16) -> i16 {
 block0(v0: i16, v1: i16):
   v2 = smulhi v0, v1
diff --git a/cranelift/filetests/filetests/isa/x64/umulhi.clif b/cranelift/filetests/filetests/isa/x64/umulhi.clif
index e910de46e..487d2a897 100644
--- a/cranelift/filetests/filetests/isa/x64/umulhi.clif
+++ b/cranelift/filetests/filetests/isa/x64/umulhi.clif
@@ -1,6 +1,37 @@
 test compile precise-output
 target x86_64
 
+function %umulhi_i8(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+  v2 = umulhi v0, v1
+  return v2
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movzbl  %dil, %eax
+;   movzbl  %sil, %r8d
+;   imull   %eax, %r8d, %eax
+;   shrq    $8, %rax, %rax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movzbl %dil, %eax
+;   movzbl %sil, %r8d
+;   imull %r8d, %eax
+;   shrq $8, %rax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+
 function %f1(i16, i16) -> i16 {
 block0(v0: i16, v1: i16):
   v2 = umulhi v0, v1
diff --git a/cranelift/filetests/filetests/runtests/smulhi.clif b/cranelift/filetests/filetests/runtests/smulhi.clif
index 52a8d4d0e..df9f13adf 100644
--- a/cranelift/filetests/filetests/runtests/smulhi.clif
+++ b/cranelift/filetests/filetests/runtests/smulhi.clif
@@ -8,6 +8,15 @@ target riscv64
 target riscv64 has_c has_zcb
 
 
+function %smulhi_i8(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+    v2 = smulhi v0, v1
+    return v2
+}
+; run: %smulhi_i8(-2, -4) == 0
+; run: %smulhi_i8(2, -4) == -1
+; run: %smulhi_i8(255, 255) == 0
+
 function %smulhi_i16(i16, i16) -> i16 {
 block0(v0: i16, v1: i16):
     v2 = smulhi v0, v1
diff --git a/cranelift/filetests/filetests/runtests/umulhi.clif b/cranelift/filetests/filetests/runtests/umulhi.clif
index 464a2bc67..51d4eee45 100644
--- a/cranelift/filetests/filetests/runtests/umulhi.clif
+++ b/cranelift/filetests/filetests/runtests/umulhi.clif
@@ -6,6 +6,14 @@ target s390x
 target riscv64
 target riscv64 has_c has_zcb
 
+function %umulhi_i8(i8, i8) -> i8 {
+block0(v0: i8, v1: i8):
+    v2 = umulhi v0, v1
+    return v2
+}
+; run: %umulhi_i8(2, 4) == 0
+; run: %umulhi_i8(255, 255) == 254
+
 function %umulhi_i16(i16, i16) -> i16 {
 block0(v0: i16, v1: i16):
     v2 = umulhi v0, v1
diff --git a/winch/filetests/src/lib.rs b/winch/filetests/src/lib.rs
index 68e5a6b7a..85606d1d2 100644
--- a/winch/filetests/src/lib.rs
+++ b/winch/filetests/src/lib.rs
@@ -104,7 +104,7 @@ mod test {
         let mut validator = Validator::new();
         let parser = WasmParser::new(0);
         let mut types = Default::default();
-        let tunables = Tunables::default();
+        let tunables = Tunables::default_host();
         let mut translation = ModuleEnvironment::new(&tunables, &mut validator, &mut types)
             .translate(parser, &wasm)
             .context("Failed to translate WebAssembly module")