Repository: bytecodealliance/wasmtime
Pull request #7818 (2024-01-24 23:36:32)

x64: Break more data dependencies in float-related instructions
This commit takes a stab at #7816 without diving a whole lot into it. I noticed that the loop started with `vcvtss2sd` which is along the same lines as previous false dependencies found earlier in PRs such as #7098. I had forgotten these instructions at the time and meant to go back and touch them up and #7731 has provided sufficient motivation to do so!

Locally this takes that test case from 1.6s to 0.4s for me.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index e7893096a..a5f1d0e3e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -664,7 +664,7 @@ dependencies = [
  "target-lexicon",
  "thiserror",
  "toml",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wat",
 ]
 
@@ -843,7 +843,7 @@ dependencies = [
  "serde_derive",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime-types",
  "wat",
 ]
@@ -2607,7 +2607,7 @@ version = "0.0.0"
 dependencies = [
  "cargo_metadata",
  "heck",
- "wit-component 0.19.1",
+ "wit-component 0.20.0",
 ]
 
 [[package]]
@@ -2895,7 +2895,7 @@ name = "verify-component-adapter"
 version = "18.0.0"
 dependencies = [
  "anyhow",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wat",
 ]
 
@@ -3002,7 +3002,7 @@ dependencies = [
  "byte-array-literals",
  "object",
  "wasi",
- "wasm-encoder 0.39.0",
+ "wasm-encoder 0.40.0",
  "wit-bindgen",
 ]
 
@@ -3088,19 +3088,18 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.39.0"
+version = "0.40.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "111495d6204760238512f57a9af162f45086504da332af210f2f75dd80b34f1d"
+checksum = "d162eb64168969ae90e8668ca0593b0e47667e315aa08e717a9c9574d700d826"
 dependencies = [
  "leb128",
- "wasmparser 0.119.0",
 ]
 
 [[package]]
 name = "wasm-metadata"
-version = "0.10.15"
+version = "0.10.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "818931c85b1d197909699d36c509fa89550ccfa0d66932ba3c1726faddb4d0c7"
+checksum = "0b313e616ef69d1b4c64155451439db26d1923e8bbc13d451ec24cf14579632e"
 dependencies = [
  "anyhow",
  "indexmap 2.0.0",
@@ -3108,35 +3107,35 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "spdx",
- "wasm-encoder 0.39.0",
- "wasmparser 0.119.0",
+ "wasm-encoder 0.40.0",
+ "wasmparser 0.120.0",
 ]
 
 [[package]]
 name = "wasm-mutate"
-version = "0.2.44"
+version = "0.2.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f95378917a3e9c61e79d41ca4629eb3e0a3ca1714d745c1c2a186439472578c"
+checksum = "31c97c7c401830ef659b9df5778647aef0c493ad6dde06296dc8c9b52b9495f9"
 dependencies = [
  "egg",
  "log",
  "rand",
  "thiserror",
- "wasm-encoder 0.39.0",
- "wasmparser 0.119.0",
+ "wasm-encoder 0.40.0",
+ "wasmparser 0.120.0",
 ]
 
 [[package]]
 name = "wasm-smith"
-version = "0.14.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a419bbbab75f5ad71744256b74fdaeeb9215ea9e9bfc59c477e96c462ee0ef59"
+checksum = "51803e2c31e82f93ec1796f781f9855844ff1203f993409eb74d1d17130928a7"
 dependencies = [
  "arbitrary",
  "flagset",
  "indexmap 2.0.0",
  "leb128",
- "wasm-encoder 0.39.0",
+ "wasm-encoder 0.40.0",
 ]
 
 [[package]]
@@ -3191,9 +3190,9 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.119.0"
+version = "0.120.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c35daf77afb4f9b14016625144a391085ec2ca99ca9cc53ed291bb53ab5278d"
+checksum = "e9148127f39cbffe43efee8d5442b16ecdba21567785268daa1ec9e134389705"
 dependencies = [
  "bitflags 2.4.1",
  "indexmap 2.0.0",
@@ -3211,12 +3210,12 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.2.76"
+version = "0.2.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cac2a7745372074e5573e365e17100f5a26058740576313784ef03fb900ea8d2"
+checksum = "d8389a95eb0b3165fea0537a6988960cc23a33d9be650e63fc3d63065fe20dcb"
 dependencies = [
  "anyhow",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
 ]
 
 [[package]]
@@ -3247,8 +3246,8 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "wasi-cap-std-sync",
- "wasm-encoder 0.39.0",
- "wasmparser 0.119.0",
+ "wasm-encoder 0.40.0",
+ "wasmparser 0.120.0",
  "wasmtime-cache",
  "wasmtime-component-macro",
  "wasmtime-component-util",
@@ -3380,7 +3379,7 @@ dependencies = [
  "tokio",
  "tracing",
  "walkdir",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime",
  "wasmtime-cache",
  "wasmtime-cli-flags",
@@ -3394,10 +3393,10 @@ dependencies = [
  "wasmtime-wasi-nn",
  "wasmtime-wasi-threads",
  "wasmtime-wast",
- "wast 70.0.0",
+ "wast 70.0.1",
  "wat",
  "windows-sys 0.52.0",
- "wit-component 0.19.1",
+ "wit-component 0.20.0",
 ]
 
 [[package]]
@@ -3450,7 +3449,7 @@ dependencies = [
  "object",
  "target-lexicon",
  "thiserror",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime-cranelift-shared",
  "wasmtime-environ",
  "wasmtime-versioned-export-macros",
@@ -3489,8 +3488,8 @@ dependencies = [
  "serde_derive",
  "target-lexicon",
  "thiserror",
- "wasm-encoder 0.39.0",
- "wasmparser 0.119.0",
+ "wasm-encoder 0.40.0",
+ "wasmparser 0.120.0",
  "wasmprinter",
  "wasmtime-component-util",
  "wasmtime-types",
@@ -3505,7 +3504,7 @@ dependencies = [
  "component-fuzz-util",
  "env_logger",
  "libfuzzer-sys",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmprinter",
  "wasmtime-environ",
  "wat",
@@ -3562,7 +3561,7 @@ dependencies = [
  "rand",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime",
  "wasmtime-fuzzing",
 ]
@@ -3582,12 +3581,12 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "v8",
- "wasm-encoder 0.39.0",
+ "wasm-encoder 0.40.0",
  "wasm-mutate",
  "wasm-smith",
  "wasm-spec-interpreter",
  "wasmi",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmprinter",
  "wasmtime",
  "wasmtime-wast",
@@ -3634,7 +3633,7 @@ dependencies = [
  "rand",
  "rustix",
  "sptr",
- "wasm-encoder 0.39.0",
+ "wasm-encoder 0.40.0",
  "wasmtime-asm-macros",
  "wasmtime-environ",
  "wasmtime-fiber",
@@ -3652,7 +3651,7 @@ dependencies = [
  "serde",
  "serde_derive",
  "thiserror",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
 ]
 
 [[package]]
@@ -3763,7 +3762,7 @@ dependencies = [
  "anyhow",
  "log",
  "wasmtime",
- "wast 70.0.0",
+ "wast 70.0.1",
 ]
 
 [[package]]
@@ -3775,7 +3774,7 @@ dependencies = [
  "gimli",
  "object",
  "target-lexicon",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime-cranelift-shared",
  "wasmtime-environ",
  "winch-codegen",
@@ -3806,23 +3805,23 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "70.0.0"
+version = "70.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ee4bc54bbe1c6924160b9f75e374a1d07532e7580eb632c0ee6cdd109bb217e"
+checksum = "f5d415036fe747a32b30c76c8bd6c73f69b7705fb7ebca5f16e852eef0c95802"
 dependencies = [
  "leb128",
  "memchr",
  "unicode-width",
- "wasm-encoder 0.39.0",
+ "wasm-encoder 0.40.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.0.83"
+version = "1.0.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f0dce8cdc288c717cf01e461a1e451a7b8445d53451123536ba576e423a101a"
+checksum = "8241f34599d413d2243a21015ab43aef68bfb32a0e447c54eef8d423525ca15e"
 dependencies = [
- "wast 70.0.0",
+ "wast 70.0.1",
 ]
 
 [[package]]
@@ -3947,7 +3946,7 @@ dependencies = [
  "regalloc2",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime-environ",
 ]
 
@@ -3963,7 +3962,7 @@ dependencies = [
  "similar",
  "target-lexicon",
  "toml",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime-environ",
  "wat",
  "winch-codegen",
@@ -3993,7 +3992,7 @@ dependencies = [
  "similar",
  "target-lexicon",
  "toml",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wasmtime-environ",
  "wat",
  "winch-codegen",
@@ -4222,9 +4221,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.19.1"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "429e3c06fba3a7566aab724ae3ffff3152ede5399d44789e7dd11f5421292859"
+checksum = "8fa6229817f3a3e4a7fafe02e063b5dc64b73b286fb0e0c14addbc0d47809c9b"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -4233,9 +4232,9 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.39.0",
+ "wasm-encoder 0.40.0",
  "wasm-metadata",
- "wasmparser 0.119.0",
+ "wasmparser 0.120.0",
  "wit-parser",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index c66ed0db4..2bffa7bcd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -232,15 +232,15 @@ is-terminal = "0.4.0"
 wit-bindgen = { version = "0.15.0", default-features = false }
 
 # wasm-tools family:
-wasmparser = "0.119.0"
-wat = "1.0.83"
-wast = "70.0.0"
-wasmprinter = "0.2.76"
-wasm-encoder = "0.39.0"
-wasm-smith = "0.14.0"
-wasm-mutate = "0.2.44"
+wasmparser = "0.120.0"
+wat = "1.0.84"
+wast = "70.0.1"
+wasmprinter = "0.2.77"
+wasm-encoder = "0.40.0"
+wasm-smith = "0.15.0"
+wasm-mutate = "0.2.45"
 wit-parser = "0.13.1"
-wit-component = "0.19.1"
+wit-component = "0.20.0"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
diff --git a/RELEASES.md b/RELEASES.md
index 3b209b29f..3618765bc 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -12,12 +12,79 @@ Unreleased.
 
 ## 17.0.0
 
-Unreleased.
+Released 2024-01-25
+
+The major feature of this release is that the WASI support in Wasmtime is now
+considered stable and flagged at an 0.2.0 version approved by the WASI subgroup.
+The release was delayed a few days to hold off until the WASI subgroup voted to
+approve the CLI and HTTP worlds and they're now on-by-default! Additionally the
+component model is now enabled by default in Wasmtime, for example an opt-in
+flag is no longer required on the CLI. Note that embeddings still must opt-in to
+using the component model by using the `wasmtime::component` module.
 
 ### Added
 
+* Cranelift optimizations have been added for "3-way comparisons", or `Ord::cmp`
+  in Rust or `<=>` in C++.
+  [#7636](https://github.com/bytecodealliance/wasmtime/pull/7636)
+  [#7702](https://github.com/bytecodealliance/wasmtime/pull/7702)
+
+* Components now use Wasmtime's compilation cache used for core wasm modules by
+  default.
+  [#7649](https://github.com/bytecodealliance/wasmtime/pull/7649)
+
+* The `Resource<T>` and `ResourceAny` types can now be converted between each
+  other.
+  [#7649](https://github.com/bytecodealliance/wasmtime/pull/7649)
+  [#7712](https://github.com/bytecodealliance/wasmtime/pull/7712)
+
 ### Changed
 
+* Minor changes have been made to a number of WITs as they progressed to their
+  official 0.2.0 status.
+  [#7625](https://github.com/bytecodealliance/wasmtime/pull/7625)
+  [#7640](https://github.com/bytecodealliance/wasmtime/pull/7640)
+  [#7690](https://github.com/bytecodealliance/wasmtime/pull/7690)
+  [#7781](https://github.com/bytecodealliance/wasmtime/pull/7781)
+  [#7817](https://github.com/bytecodealliance/wasmtime/pull/7817)
+
+* The component model is now enabled by default.
+  [#7821](https://github.com/bytecodealliance/wasmtime/pull/7821)
+
+* The implementation of `memory.atomic.{wait,notify}` has been rewritten.
+  [#7629](https://github.com/bytecodealliance/wasmtime/pull/7629)
+
+* The `wasmtime_wasi::preview2::Table` type has been moved to
+  `wasmtime::component::ResourceTable`.
+  [#7655](https://github.com/bytecodealliance/wasmtime/pull/7655)
+
+* Creating a UDP stream now validates the address being sent to.
+  [#7648](https://github.com/bytecodealliance/wasmtime/pull/7648)
+
+* Defining resource types in `Linker<T>` now takes the type to define as a
+  runtime parameter.
+  [#7680](https://github.com/bytecodealliance/wasmtime/pull/7680)
+
+* Socket address checks can now be performed dynamically at runtime.
+  [#7662](https://github.com/bytecodealliance/wasmtime/pull/7662)
+
+* Wasmtime and Cranelift's MSRV is now 1.73.0.
+  [#7739](https://github.com/bytecodealliance/wasmtime/pull/7739)
+
+### Fixed
+
+* Bindings for WIT APIs where interfaces have multiple versions are now fixed by
+  putting the version in the generated binding names.
+  [#7656](https://github.com/bytecodealliance/wasmtime/pull/7656)
+
+* The preview1 `fd_{read,write}` APIs are now fixed when a shared memory is
+  used.
+  [#7755](https://github.com/bytecodealliance/wasmtime/pull/7755)
+
+* The preview1 `fd_{read,write}` APIs no longer leak an intermediate stream
+  created.
+  [#7819](https://github.com/bytecodealliance/wasmtime/pull/7819)
+
 --------------------------------------------------------------------------------
 
 ## 16.0.0
diff --git a/build.rs b/build.rs
index 0826f0a86..0421313e7 100644
--- a/build.rs
+++ b/build.rs
@@ -204,30 +204,7 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
     assert!(strategy == "Cranelift" || strategy == "Winch");
 
     // Ignore everything except the winch misc test suite.
-    // We ignore tests that assert for traps on windows, given
-    // that Winch doesn't encode unwind information for Windows, yet.
     if strategy == "Winch" {
-        let assert_trap = [
-            "i32",
-            "i64",
-            "call",
-            "call_indirect",
-            "conversions",
-            "table_fill",
-            "table_init",
-            "table_copy",
-            "table_set",
-            "table_get",
-            "memory_grow",
-            "memory_init",
-            "memory_fill",
-        ]
-        .contains(&testname);
-
-        if assert_trap && env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() == "windows" {
-            return true;
-        }
-
         if testsuite == "misc_testsuite" {
             // The misc/call_indirect is fully supported by Winch.
             if testname != "call_indirect" {
diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle
index e55867ab4..82fbcd052 100644
--- a/cranelift/codegen/src/isa/x64/inst.isle
+++ b/cranelift/codegen/src/isa/x64/inst.isle
@@ -4281,18 +4281,27 @@
 (rule (x64_vfnmadd132 $F64X2 a b c) (xmm_rmr_vex3 (AvxOpcode.Vfnmadd132pd) a b c))
 
 ;; Helper for creating `sqrtss` instructions.
-(decl x64_sqrtss (XmmMem) Xmm)
-(rule (x64_sqrtss x) (xmm_unary_rm_r_unaligned (SseOpcode.Sqrtss) x))
-(rule 1 (x64_sqrtss x)
+;;
+;; NB: the square-root operation technically only has one operand but this
+;; instruction has two. This is to reflect how the square root operation copies
+;; the upper bits of the first register and only performs the square root
+;; operation on the low bits of the second register. This introduces
+;; a data-dependency on the contents of the first register which is modeled
+;; here.
+(decl x64_sqrtss (Xmm XmmMem) Xmm)
+(rule (x64_sqrtss x y) (xmm_rm_r_unaligned (SseOpcode.Sqrtss) x y))
+(rule 1 (x64_sqrtss x y)
         (if-let $true (use_avx))
-        (xmm_unary_rm_r_vex (AvxOpcode.Vsqrtss) x))
+        (xmm_rmir_vex (AvxOpcode.Vsqrtss) x y))
 
 ;; Helper for creating `sqrtsd` instructions.
-(decl x64_sqrtsd (XmmMem) Xmm)
-(rule (x64_sqrtsd x) (xmm_unary_rm_r_unaligned (SseOpcode.Sqrtsd) x))
-(rule 1 (x64_sqrtsd x)
+;;
+;; NB: see `x64_sqrtss` for explanation of why this has two args.
+(decl x64_sqrtsd (Xmm XmmMem) Xmm)
+(rule (x64_sqrtsd x y) (xmm_rm_r_unaligned (SseOpcode.Sqrtsd) x y))
+(rule 1 (x64_sqrtsd x y)
         (if-let $true (use_avx))
-        (xmm_unary_rm_r_vex (AvxOpcode.Vsqrtsd) x))
+        (xmm_rmir_vex (AvxOpcode.Vsqrtsd) x y))
 
 ;; Helper for creating `sqrtps` instructions.
 (decl x64_sqrtps (XmmMem) Xmm)
@@ -4309,18 +4318,22 @@
         (xmm_unary_rm_r_vex (AvxOpcode.Vsqrtpd) x))
 
 ;; Helper for creating `cvtss2sd` instructions.
-(decl x64_cvtss2sd (XmmMem) Xmm)
-(rule (x64_cvtss2sd x) (xmm_unary_rm_r_unaligned (SseOpcode.Cvtss2sd) x))
-(rule 1 (x64_cvtss2sd x)
+;;
+;; NB: see `x64_sqrtss` for why this has two args (same reasoning, different op)
+(decl x64_cvtss2sd (Xmm XmmMem) Xmm)
+(rule (x64_cvtss2sd x y) (xmm_rm_r_unaligned (SseOpcode.Cvtss2sd) x y))
+(rule 1 (x64_cvtss2sd x y)
         (if-let $true (use_avx))
-        (xmm_unary_rm_r_vex (AvxOpcode.Vcvtss2sd) x))
+        (xmm_rmir_vex (AvxOpcode.Vcvtss2sd) x y))
 
 ;; Helper for creating `cvtsd2ss` instructions.
-(decl x64_cvtsd2ss (XmmMem) Xmm)
-(rule (x64_cvtsd2ss x) (xmm_unary_rm_r_unaligned (SseOpcode.Cvtsd2ss) x))
-(rule 1 (x64_cvtsd2ss x)
+;;
+;; NB: see `x64_sqrtss` for why this has two args (same reasoning, different op)
+(decl x64_cvtsd2ss (Xmm XmmMem) Xmm)
+(rule (x64_cvtsd2ss x y) (xmm_rm_r_unaligned (SseOpcode.Cvtsd2ss) x y))
+(rule 1 (x64_cvtsd2ss x y)
         (if-let $true (use_avx))
-        (xmm_unary_rm_r_vex (AvxOpcode.Vcvtsd2ss) x))
+        (xmm_rmir_vex (AvxOpcode.Vcvtsd2ss) x y))
 
 ;; Helper for creating `cvtdq2ps` instructions.
 (decl x64_cvtdq2ps (XmmMem) Xmm)
diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs
index 6bd65154e..1312a1578 100644
--- a/cranelift/codegen/src/isa/x64/inst/emit.rs
+++ b/cranelift/codegen/src/isa/x64/inst/emit.rs
@@ -1969,8 +1969,6 @@ pub(crate) fn emit(
                 SseOpcode::Cvtpd2ps => (LegacyPrefixes::_66, 0x0F5A, 2),
                 SseOpcode::Cvtps2pd => (LegacyPrefixes::None, 0x0F5A, 2),
                 SseOpcode::Cvtdq2ps => (LegacyPrefixes::None, 0x0F5B, 2),
-                SseOpcode::Cvtss2sd => (LegacyPrefixes::_F3, 0x0F5A, 2),
-                SseOpcode::Cvtsd2ss => (LegacyPrefixes::_F2, 0x0F5A, 2),
                 SseOpcode::Cvttpd2dq => (LegacyPrefixes::_66, 0x0FE6, 2),
                 SseOpcode::Cvttps2dq => (LegacyPrefixes::_F3, 0x0F5B, 2),
                 SseOpcode::Movaps => (LegacyPrefixes::None, 0x0F28, 2),
@@ -1998,8 +1996,6 @@ pub(crate) fn emit(
                 SseOpcode::Pmovzxdq => (LegacyPrefixes::_66, 0x0F3835, 3),
                 SseOpcode::Sqrtps => (LegacyPrefixes::None, 0x0F51, 2),
                 SseOpcode::Sqrtpd => (LegacyPrefixes::_66, 0x0F51, 2),
-                SseOpcode::Sqrtss => (LegacyPrefixes::_F3, 0x0F51, 2),
-                SseOpcode::Sqrtsd => (LegacyPrefixes::_F2, 0x0F51, 2),
                 SseOpcode::Movddup => (LegacyPrefixes::_F2, 0x0F12, 2),
                 _ => unimplemented!("Opcode {:?} not implemented", op),
             };
@@ -2231,6 +2227,10 @@ pub(crate) fn emit(
                 SseOpcode::Phaddw => (LegacyPrefixes::_66, 0x0F3801, 3),
                 SseOpcode::Phaddd => (LegacyPrefixes::_66, 0x0F3802, 3),
                 SseOpcode::Movss => (LegacyPrefixes::_F3, 0x0F10, 2),
+                SseOpcode::Cvtss2sd => (LegacyPrefixes::_F3, 0x0F5A, 2),
+                SseOpcode::Cvtsd2ss => (LegacyPrefixes::_F2, 0x0F5A, 2),
+                SseOpcode::Sqrtss => (LegacyPrefixes::_F3, 0x0F51, 2),
+                SseOpcode::Sqrtsd => (LegacyPrefixes::_F2, 0x0F51, 2),
                 _ => unimplemented!("Opcode {:?} not implemented", op),
             };
 
@@ -2452,6 +2452,10 @@ pub(crate) fn emit(
                 AvxOpcode::Vpunpckhqdq => (LP::_66, OM::_0F, 0x6D),
                 AvxOpcode::Vmovsd => (LP::_F2, OM::_0F, 0x10),
                 AvxOpcode::Vmovss => (LP::_F3, OM::_0F, 0x10),
+                AvxOpcode::Vcvtss2sd => (LP::_F3, OM::_0F, 0x5A),
+                AvxOpcode::Vcvtsd2ss => (LP::_F2, OM::_0F, 0x5A),
+                AvxOpcode::Vsqrtss => (LP::_F3, OM::_0F, 0x51),
+                AvxOpcode::Vsqrtsd => (LP::_F2, OM::_0F, 0x51),
                 _ => panic!("unexpected rmir vex opcode {op:?}"),
             };
             VexInstruction::new()
@@ -2681,36 +2685,17 @@ pub(crate) fn emit(
                 AvxOpcode::Vbroadcastss => (LegacyPrefixes::_66, OpcodeMap::_0F38, 0x18),
                 AvxOpcode::Vmovddup => (LegacyPrefixes::_F2, OpcodeMap::_0F, 0x12),
 
-                AvxOpcode::Vcvtss2sd => (LegacyPrefixes::_F3, OpcodeMap::_0F, 0x5A),
-                AvxOpcode::Vcvtsd2ss => (LegacyPrefixes::_F2, OpcodeMap::_0F, 0x5A),
-                AvxOpcode::Vsqrtss => (LegacyPrefixes::_F3, OpcodeMap::_0F, 0x51),
-                AvxOpcode::Vsqrtsd => (LegacyPrefixes::_F2, OpcodeMap::_0F, 0x51),
-
                 _ => panic!("unexpected rmr_imm_vex opcode {op:?}"),
             };
 
-            let vex = VexInstruction::new()
+            VexInstruction::new()
                 .length(VexVectorLength::V128)
                 .prefix(prefix)
                 .map(map)
                 .opcode(opcode)
                 .reg(dst.to_real_reg().unwrap().hw_enc())
-                .rm(src);
-
-            // These opcodes take a second operand through `vvvv` which copies
-            // the upper bits into the destination register. That's not
-            // reflected in the CLIF instruction, however, since the SSE version
-            // doesn't have this functionality. Instead just copy whatever
-            // happens to already be in the destination, which at least is what
-            // LLVM seems to do.
-            let vex = match op {
-                AvxOpcode::Vcvtss2sd
-                | AvxOpcode::Vcvtsd2ss
-                | AvxOpcode::Vsqrtss
-                | AvxOpcode::Vsqrtsd => vex.vvvv(dst.to_real_reg().unwrap().hw_enc()),
-                _ => vex,
-            };
-            vex.encode(sink);
+                .rm(src)
+                .encode(sink);
         }
 
         Inst::XmmUnaryRmRImmVex { op, src, dst, imm } => {
diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle
index e0d17fe62..2452966a1 100644
--- a/cranelift/codegen/src/isa/x64/lower.isle
+++ b/cranelift/codegen/src/isa/x64/lower.isle
@@ -2577,9 +2577,9 @@
 
 ;; Rules for `sqrt` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (rule (lower (has_type $F32 (sqrt x)))
-      (x64_sqrtss x))
+      (x64_sqrtss (xmm_zero $F32X4) x))
 (rule (lower (has_type $F64 (sqrt x)))
-      (x64_sqrtsd x))
+      (x64_sqrtsd (xmm_zero $F64X2) x))
 (rule (lower (has_type $F32X4 (sqrt x)))
       (x64_sqrtps x))
 (rule (lower (has_type $F64X2 (sqrt x)))
@@ -2587,7 +2587,7 @@
 
 ;; Rules for `fpromote` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (rule (lower (has_type $F64 (fpromote x)))
-      (x64_cvtss2sd x))
+      (x64_cvtss2sd (xmm_zero $F64X2) x))
 
 ;; Rules for `fvpromote` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (rule (lower (has_type $F64X2 (fvpromote_low x)))
@@ -2595,7 +2595,7 @@
 
 ;; Rules for `fdemote` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (rule (lower (has_type $F32 (fdemote x)))
-      (x64_cvtsd2ss x))
+      (x64_cvtsd2ss (xmm_zero $F32X4) x))
 
 ;; Rules for `fvdemote` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (rule (lower (has_type $F32X4 (fvdemote x)))
diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs
index 38a9c668c..5aaa664fc 100644
--- a/cranelift/codegen/src/isa/x64/mod.rs
+++ b/cranelift/codegen/src/isa/x64/mod.rs
@@ -15,6 +15,7 @@ use crate::machinst::{
 };
 use crate::result::CodegenResult;
 use crate::settings::{self as shared_settings, Flags};
+use crate::{Final, MachBufferFinalized};
 use alloc::{boxed::Box, vec::Vec};
 use core::fmt;
 use cranelift_control::ControlPlane;
@@ -27,6 +28,8 @@ mod lower;
 mod pcc;
 pub mod settings;
 
+pub use inst::unwind::systemv::create_cie;
+
 /// An X64 backend.
 pub(crate) struct X64Backend {
     triple: Triple,
@@ -118,26 +121,7 @@ impl TargetIsa for X64Backend {
         result: &CompiledCode,
         kind: crate::isa::unwind::UnwindInfoKind,
     ) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
-        use crate::isa::unwind::UnwindInfo;
-        use crate::isa::unwind::UnwindInfoKind;
-        Ok(match kind {
-            UnwindInfoKind::SystemV => {
-                let mapper = self::inst::unwind::systemv::RegisterMapper;
-                Some(UnwindInfo::SystemV(
-                    crate::isa::unwind::systemv::create_unwind_info_from_insts(
-                        &result.buffer.unwind_info[..],
-                        result.buffer.data().len(),
-                        &mapper,
-                    )?,
-                ))
-            }
-            UnwindInfoKind::Windows => Some(UnwindInfo::WindowsX64(
-                crate::isa::unwind::winx64::create_unwind_info_from_insts::<
-                    self::inst::unwind::winx64::RegisterMapper,
-                >(&result.buffer.unwind_info[..])?,
-            )),
-            _ => None,
-        })
+        emit_unwind_info(&result.buffer, kind)
     }
 
     #[cfg(feature = "unwind")]
@@ -193,6 +177,32 @@ impl TargetIsa for X64Backend {
     }
 }
 
+/// Emit unwind info for an x86 target.
+pub fn emit_unwind_info(
+    buffer: &MachBufferFinalized<Final>,
+    kind: crate::isa::unwind::UnwindInfoKind,
+) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
+    use crate::isa::unwind::{UnwindInfo, UnwindInfoKind};
+    Ok(match kind {
+        UnwindInfoKind::SystemV => {
+            let mapper = self::inst::unwind::systemv::RegisterMapper;
+            Some(UnwindInfo::SystemV(
+                crate::isa::unwind::systemv::create_unwind_info_from_insts(
+                    &buffer.unwind_info[..],
+                    buffer.data().len(),
+                    &mapper,
+                )?,
+            ))
+        }
+        UnwindInfoKind::Windows => Some(UnwindInfo::WindowsX64(
+            crate::isa::unwind::winx64::create_unwind_info_from_insts::<
+                self::inst::unwind::winx64::RegisterMapper,
+            >(&buffer.unwind_info[..])?,
+        )),
+        _ => None,
+    })
+}
+
 impl fmt::Display for X64Backend {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("MachBackend")
diff --git a/cranelift/codegen/src/lib.rs b/cranelift/codegen/src/lib.rs
index 5d9922bf7..1908bdd3d 100644
--- a/cranelift/codegen/src/lib.rs
+++ b/cranelift/codegen/src/lib.rs
@@ -59,8 +59,8 @@ pub use crate::machinst::buffer::{
 };
 pub use crate::machinst::{
     CompiledCode, Final, MachBuffer, MachBufferFinalized, MachInst, MachInstEmit,
-    MachInstEmitState, MachLabel, Reg, TextSectionBuilder, VCodeConstantData, VCodeConstants,
-    Writable,
+    MachInstEmitState, MachLabel, RealReg, Reg, TextSectionBuilder, VCodeConstantData,
+    VCodeConstants, Writable,
 };
 
 mod alias_analysis;
diff --git a/cranelift/codegen/src/machinst/reg.rs b/cranelift/codegen/src/machinst/reg.rs
index 8aadc11b5..4e21377d2 100644
--- a/cranelift/codegen/src/machinst/reg.rs
+++ b/cranelift/codegen/src/machinst/reg.rs
@@ -112,6 +112,7 @@ impl RealReg {
         self.0.class()
     }
 
+    /// The physical register number.
     pub fn hw_enc(self) -> u8 {
         PReg::from(self).hw_enc() as u8
     }
diff --git a/crates/wasi-http/src/lib.rs b/crates/wasi-http/src/lib.rs
index d331eb56b..e7218250a 100644
--- a/crates/wasi-http/src/lib.rs
+++ b/crates/wasi-http/src/lib.rs
@@ -11,9 +11,9 @@ pub mod bindings {
     wasmtime::component::bindgen!({
         path: "wit",
         interfaces: "
-            import wasi:http/incoming-handler@0.2.0-rc-2024-01-16;
-            import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
-            import wasi:http/types@0.2.0-rc-2024-01-16;
+            import wasi:http/incoming-handler@0.2.0;
+            import wasi:http/outgoing-handler@0.2.0;
+            import wasi:http/types@0.2.0;
         ",
         tracing: true,
         async: false,
diff --git a/crates/wasi-http/wit/command-extended.wit b/crates/wasi-http/wit/command-extended.wit
index 2f1491ef9..4bff99e65 100644
--- a/crates/wasi-http/wit/command-extended.wit
+++ b/crates/wasi-http/wit/command-extended.wit
@@ -1,6 +1,6 @@
 // All of the same imports and exports available in the wasi:cli/command world
 // with addition of HTTP proxy related imports:
 world command-extended {
-  include wasi:cli/command@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/command@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/crates/wasi-http/wit/deps/cli/command.wit b/crates/wasi-http/wit/deps/cli/command.wit
index a9889164f..d8005bd38 100644
--- a/crates/wasi-http/wit/deps/cli/command.wit
+++ b/crates/wasi-http/wit/deps/cli/command.wit
@@ -1,4 +1,4 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world command {
   include imports;
diff --git a/crates/wasi-http/wit/deps/cli/imports.wit b/crates/wasi-http/wit/deps/cli/imports.wit
index 8ce1abec3..083b84a03 100644
--- a/crates/wasi-http/wit/deps/cli/imports.wit
+++ b/crates/wasi-http/wit/deps/cli/imports.wit
@@ -1,11 +1,11 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world imports {
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  include wasi:filesystem/imports@0.2.0-rc-2023-11-10;
-  include wasi:sockets/imports@0.2.0-rc-2024-01-16;
-  include wasi:random/imports@0.2.0-rc-2023-11-10;
-  include wasi:io/imports@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  include wasi:filesystem/imports@0.2.0;
+  include wasi:sockets/imports@0.2.0;
+  include wasi:random/imports@0.2.0;
+  include wasi:io/imports@0.2.0;
 
   import environment;
   import exit;
diff --git a/crates/wasi-http/wit/deps/cli/stdio.wit b/crates/wasi-http/wit/deps/cli/stdio.wit
index 1b653b6e2..31ef35b5a 100644
--- a/crates/wasi-http/wit/deps/cli/stdio.wit
+++ b/crates/wasi-http/wit/deps/cli/stdio.wit
@@ -1,17 +1,17 @@
 interface stdin {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream};
+  use wasi:io/streams@0.2.0.{input-stream};
 
   get-stdin: func() -> input-stream;
 }
 
 interface stdout {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stdout: func() -> output-stream;
 }
 
 interface stderr {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stderr: func() -> output-stream;
 }
diff --git a/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit b/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit
index 09ef32c36..4e4dc3a19 100644
--- a/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit
+++ b/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 /// WASI Monotonic Clock is a clock API intended to let users measure elapsed
 /// time.
 ///
@@ -10,7 +10,7 @@ package wasi:clocks@0.2.0-rc-2023-11-10;
 ///
 /// It is intended for measuring elapsed time.
 interface monotonic-clock {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
 
     /// An instant in time, in nanoseconds. An instant is relative to an
     /// unspecified initial value, and can only be compared to instances from
diff --git a/crates/wasi-http/wit/deps/clocks/wall-clock.wit b/crates/wasi-http/wit/deps/clocks/wall-clock.wit
index 8abb9a0c0..440ca0f33 100644
--- a/crates/wasi-http/wit/deps/clocks/wall-clock.wit
+++ b/crates/wasi-http/wit/deps/clocks/wall-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 /// WASI Wall Clock is a clock API intended to let users query the current
 /// time. The name "wall" makes an analogy to a "clock on the wall", which
 /// is not necessarily monotonic as it may be reset.
diff --git a/crates/wasi-http/wit/deps/clocks/world.wit b/crates/wasi-http/wit/deps/clocks/world.wit
index 8fa080f0e..c0224572a 100644
--- a/crates/wasi-http/wit/deps/clocks/world.wit
+++ b/crates/wasi-http/wit/deps/clocks/world.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 
 world imports {
     import monotonic-clock;
diff --git a/crates/wasi-http/wit/deps/filesystem/preopens.wit b/crates/wasi-http/wit/deps/filesystem/preopens.wit
index 95ec67843..da801f6d6 100644
--- a/crates/wasi-http/wit/deps/filesystem/preopens.wit
+++ b/crates/wasi-http/wit/deps/filesystem/preopens.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 interface preopens {
     use types.{descriptor};
diff --git a/crates/wasi-http/wit/deps/filesystem/types.wit b/crates/wasi-http/wit/deps/filesystem/types.wit
index 059722ab8..11108fcda 100644
--- a/crates/wasi-http/wit/deps/filesystem/types.wit
+++ b/crates/wasi-http/wit/deps/filesystem/types.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 /// WASI filesystem is a filesystem API primarily intended to let users run WASI
 /// programs that access their files on their existing filesystems, without
 /// significant overhead.
@@ -24,8 +24,8 @@ package wasi:filesystem@0.2.0-rc-2023-11-10;
 ///
 /// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md
 interface types {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream, error};
-    use wasi:clocks/wall-clock@0.2.0-rc-2023-11-10.{datetime};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream, error};
+    use wasi:clocks/wall-clock@0.2.0.{datetime};
 
     /// File size or length of a region within a file.
     type filesize = u64;
diff --git a/crates/wasi-http/wit/deps/filesystem/world.wit b/crates/wasi-http/wit/deps/filesystem/world.wit
index 285e0bae9..663f57920 100644
--- a/crates/wasi-http/wit/deps/filesystem/world.wit
+++ b/crates/wasi-http/wit/deps/filesystem/world.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 world imports {
     import types;
diff --git a/crates/wasi-http/wit/deps/http/proxy.wit b/crates/wasi-http/wit/deps/http/proxy.wit
index 2b0ce4b8a..687c24d23 100644
--- a/crates/wasi-http/wit/deps/http/proxy.wit
+++ b/crates/wasi-http/wit/deps/http/proxy.wit
@@ -1,4 +1,4 @@
-package wasi:http@0.2.0-rc-2024-01-16;
+package wasi:http@0.2.0;
 
 /// The `wasi:http/proxy` world captures a widely-implementable intersection of
 /// hosts that includes HTTP forward and reverse proxies. Components targeting
@@ -6,19 +6,19 @@ package wasi:http@0.2.0-rc-2024-01-16;
 /// outgoing HTTP requests.
 world proxy {
   /// HTTP proxies have access to time and randomness.
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  import wasi:random/random@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  import wasi:random/random@0.2.0;
 
   /// Proxies have standard output and error streams which are expected to
   /// terminate in a developer-facing console provided by the host.
-  import wasi:cli/stdout@0.2.0-rc-2024-01-16;
-  import wasi:cli/stderr@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdout@0.2.0;
+  import wasi:cli/stderr@0.2.0;
 
   /// TODO: this is a temporary workaround until component tooling is able to
   /// gracefully handle the absence of stdin. Hosts must return an eof stream
   /// for this import, which is what wasi-libc + tooling will do automatically
   /// when this import is properly removed.
-  import wasi:cli/stdin@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdin@0.2.0;
 
   /// This is the default handler to use when user code simply wants to make an
   /// HTTP request (e.g., via `fetch()`).
diff --git a/crates/wasi-http/wit/deps/http/types.wit b/crates/wasi-http/wit/deps/http/types.wit
index 0f698e769..755ac6a6b 100644
--- a/crates/wasi-http/wit/deps/http/types.wit
+++ b/crates/wasi-http/wit/deps/http/types.wit
@@ -2,10 +2,10 @@
 /// HTTP Requests and Responses, both incoming and outgoing, as well as
 /// their headers, trailers, and bodies.
 interface types {
-  use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-  use wasi:io/error@0.2.0-rc-2023-11-10.{error as io-error};
-  use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+  use wasi:clocks/monotonic-clock@0.2.0.{duration};
+  use wasi:io/streams@0.2.0.{input-stream, output-stream};
+  use wasi:io/error@0.2.0.{error as io-error};
+  use wasi:io/poll@0.2.0.{pollable};
 
   /// This type corresponds to HTTP standard Methods.
   variant method {
diff --git a/crates/wasi-http/wit/deps/io/error.wit b/crates/wasi-http/wit/deps/io/error.wit
index 31918acbb..22e5b6489 100644
--- a/crates/wasi-http/wit/deps/io/error.wit
+++ b/crates/wasi-http/wit/deps/io/error.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 
 interface error {
diff --git a/crates/wasi-http/wit/deps/io/poll.wit b/crates/wasi-http/wit/deps/io/poll.wit
index 81b1cab99..ddc67f8b7 100644
--- a/crates/wasi-http/wit/deps/io/poll.wit
+++ b/crates/wasi-http/wit/deps/io/poll.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// A poll API intended to let users wait for I/O events on multiple handles
 /// at once.
diff --git a/crates/wasi-http/wit/deps/io/streams.wit b/crates/wasi-http/wit/deps/io/streams.wit
index 82e6e073e..6d2f871e3 100644
--- a/crates/wasi-http/wit/deps/io/streams.wit
+++ b/crates/wasi-http/wit/deps/io/streams.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// WASI I/O is an I/O abstraction API which is currently focused on providing
 /// stream types.
diff --git a/crates/wasi-http/wit/deps/io/world.wit b/crates/wasi-http/wit/deps/io/world.wit
index 8243da2ee..5f0b43fe5 100644
--- a/crates/wasi-http/wit/deps/io/world.wit
+++ b/crates/wasi-http/wit/deps/io/world.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 world imports {
     import streams;
diff --git a/crates/wasi-http/wit/deps/random/insecure-seed.wit b/crates/wasi-http/wit/deps/random/insecure-seed.wit
index f76e87dad..47210ac6b 100644
--- a/crates/wasi-http/wit/deps/random/insecure-seed.wit
+++ b/crates/wasi-http/wit/deps/random/insecure-seed.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure-seed interface for seeding hash-map DoS resistance.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi-http/wit/deps/random/insecure.wit b/crates/wasi-http/wit/deps/random/insecure.wit
index ec7b99737..c58f4ee85 100644
--- a/crates/wasi-http/wit/deps/random/insecure.wit
+++ b/crates/wasi-http/wit/deps/random/insecure.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure interface for insecure pseudo-random numbers.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi-http/wit/deps/random/random.wit b/crates/wasi-http/wit/deps/random/random.wit
index 7a7dfa27a..0c017f093 100644
--- a/crates/wasi-http/wit/deps/random/random.wit
+++ b/crates/wasi-http/wit/deps/random/random.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// WASI Random is a random data API.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi-http/wit/deps/random/world.wit b/crates/wasi-http/wit/deps/random/world.wit
index 49e5743b4..3da34914a 100644
--- a/crates/wasi-http/wit/deps/random/world.wit
+++ b/crates/wasi-http/wit/deps/random/world.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 
 world imports {
     import random;
diff --git a/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit b/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit
index 931ccf7e0..8e639ec59 100644
--- a/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit
+++ b/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit
@@ -1,6 +1,6 @@
 
 interface ip-name-lookup {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-address};
 
 
diff --git a/crates/wasi-http/wit/deps/sockets/tcp.wit b/crates/wasi-http/wit/deps/sockets/tcp.wit
index 9f12b8212..5902b9ee0 100644
--- a/crates/wasi-http/wit/deps/sockets/tcp.wit
+++ b/crates/wasi-http/wit/deps/sockets/tcp.wit
@@ -1,8 +1,8 @@
 
 interface tcp {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
-    use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream};
+    use wasi:io/poll@0.2.0.{pollable};
+    use wasi:clocks/monotonic-clock@0.2.0.{duration};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     enum shutdown-type {
diff --git a/crates/wasi-http/wit/deps/sockets/udp.wit b/crates/wasi-http/wit/deps/sockets/udp.wit
index 6ba380ff7..d987a0a90 100644
--- a/crates/wasi-http/wit/deps/sockets/udp.wit
+++ b/crates/wasi-http/wit/deps/sockets/udp.wit
@@ -1,6 +1,6 @@
 
 interface udp {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     /// A received datagram.
diff --git a/crates/wasi-http/wit/deps/sockets/world.wit b/crates/wasi-http/wit/deps/sockets/world.wit
index 8588cc6c1..f8bb92ae0 100644
--- a/crates/wasi-http/wit/deps/sockets/world.wit
+++ b/crates/wasi-http/wit/deps/sockets/world.wit
@@ -1,4 +1,4 @@
-package wasi:sockets@0.2.0-rc-2024-01-16;
+package wasi:sockets@0.2.0;
 
 world imports {
     import instance-network;
diff --git a/crates/wasi-preview1-component-adapter/src/descriptors.rs b/crates/wasi-preview1-component-adapter/src/descriptors.rs
index 23e0a45d4..52b2378c7 100644
--- a/crates/wasi-preview1-component-adapter/src/descriptors.rs
+++ b/crates/wasi-preview1-component-adapter/src/descriptors.rs
@@ -194,7 +194,7 @@ impl Descriptors {
 
     #[cfg(not(feature = "proxy"))]
     fn open_preopens(&self, import_alloc: &ImportAlloc, arena: &BumpArena) {
-        #[link(wasm_import_module = "wasi:filesystem/preopens@0.2.0-rc-2023-11-10")]
+        #[link(wasm_import_module = "wasi:filesystem/preopens@0.2.0")]
         #[allow(improper_ctypes)] // FIXME(bytecodealliance/wit-bindgen#684)
         extern "C" {
             #[link_name = "get-directories"]
diff --git a/crates/wasi-preview1-component-adapter/src/lib.rs b/crates/wasi-preview1-component-adapter/src/lib.rs
index bd1d94e40..0df1b5e1f 100644
--- a/crates/wasi-preview1-component-adapter/src/lib.rs
+++ b/crates/wasi-preview1-component-adapter/src/lib.rs
@@ -84,12 +84,12 @@ pub mod bindings {
             package wasmtime:adapter;
 
             world adapter {
-                import wasi:clocks/wall-clock@0.2.0-rc-2023-11-10;
-                import wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10;
-                import wasi:random/random@0.2.0-rc-2023-11-10;
-                import wasi:cli/stdout@0.2.0-rc-2024-01-16;
-                import wasi:cli/stderr@0.2.0-rc-2024-01-16;
-                import wasi:cli/stdin@0.2.0-rc-2024-01-16;
+                import wasi:clocks/wall-clock@0.2.0;
+                import wasi:clocks/monotonic-clock@0.2.0;
+                import wasi:random/random@0.2.0;
+                import wasi:cli/stdout@0.2.0;
+                import wasi:cli/stderr@0.2.0;
+                import wasi:cli/stdin@0.2.0;
             }
         "#,
         std_feature,
@@ -98,7 +98,7 @@ pub mod bindings {
     });
 }
 
-#[export_name = "wasi:cli/run@0.2.0-rc-2024-01-16#run"]
+#[export_name = "wasi:cli/run@0.2.0#run"]
 #[cfg(feature = "command")]
 pub unsafe extern "C" fn run() -> u32 {
     #[link(wasm_import_module = "__main_module__")]
@@ -1942,7 +1942,7 @@ pub unsafe extern "C" fn poll_oneoff(
             });
         }
 
-        #[link(wasm_import_module = "wasi:io/poll@0.2.0-rc-2023-11-10")]
+        #[link(wasm_import_module = "wasi:io/poll@0.2.0")]
         #[allow(improper_ctypes)] // FIXME(bytecodealliance/wit-bindgen#684)
         extern "C" {
             #[link_name = "poll"]
@@ -2665,7 +2665,7 @@ impl State {
     #[cfg(not(feature = "proxy"))]
     fn get_environment(&self) -> &[StrTuple] {
         if self.env_vars.get().is_none() {
-            #[link(wasm_import_module = "wasi:cli/environment@0.2.0-rc-2024-01-16")]
+            #[link(wasm_import_module = "wasi:cli/environment@0.2.0")]
             extern "C" {
                 #[link_name = "get-environment"]
                 fn get_environment_import(rval: *mut StrTupleList);
@@ -2690,7 +2690,7 @@ impl State {
     #[cfg(not(feature = "proxy"))]
     fn get_args(&self) -> &[WasmStr] {
         if self.args.get().is_none() {
-            #[link(wasm_import_module = "wasi:cli/environment@0.2.0-rc-2024-01-16")]
+            #[link(wasm_import_module = "wasi:cli/environment@0.2.0")]
             extern "C" {
                 #[link_name = "get-arguments"]
                 fn get_args_import(rval: *mut WasmStrList);
diff --git a/crates/wasi/src/preview2/mod.rs b/crates/wasi/src/preview2/mod.rs
index f7fc9004e..160875043 100644
--- a/crates/wasi/src/preview2/mod.rs
+++ b/crates/wasi/src/preview2/mod.rs
@@ -69,9 +69,9 @@ pub mod bindings {
             wasmtime::component::bindgen!({
                 path: "wit",
                 interfaces: "
-                    import wasi:io/poll@0.2.0-rc-2023-11-10;
-                    import wasi:io/streams@0.2.0-rc-2023-11-10;
-                    import wasi:filesystem/types@0.2.0-rc-2023-11-10;
+                    import wasi:io/poll@0.2.0;
+                    import wasi:io/streams@0.2.0;
+                    import wasi:filesystem/types@0.2.0;
                 ",
                 tracing: true,
                 trappable_error_type: {
diff --git a/crates/wasi/src/preview2/preview1.rs b/crates/wasi/src/preview2/preview1.rs
index a06cd5580..52cfcc531 100644
--- a/crates/wasi/src/preview2/preview1.rs
+++ b/crates/wasi/src/preview2/preview1.rs
@@ -1335,8 +1335,10 @@ impl<
                         .unwrap_or_else(types::Error::trap)
                 })?;
                 let read = blocking_mode
-                    .read(self, stream, buf.len().try_into()?)
-                    .await?;
+                    .read(self, stream.borrowed(), buf.len().try_into()?)
+                    .await;
+                streams::HostInputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                let read = read?;
                 let n = read.len().try_into()?;
                 let pos = pos.checked_add(n).ok_or(types::Errno::Overflow)?;
                 position.store(pos, Ordering::Relaxed);
@@ -1393,9 +1395,10 @@ impl<
                         .unwrap_or_else(types::Error::trap)
                 })?;
                 let read = blocking_mode
-                    .read(self, stream, buf.len().try_into()?)
-                    .await?;
-                (buf, read)
+                    .read(self, stream.borrowed(), buf.len().try_into()?)
+                    .await;
+                streams::HostInputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                (buf, read?)
             }
             Descriptor::Stdin { .. } => {
                 // NOTE: legacy implementation returns SPIPE here
@@ -1454,7 +1457,9 @@ impl<
                     })?;
                     (stream, pos)
                 };
-                let n = blocking_mode.write(self, stream, buf).await?;
+                let n = blocking_mode.write(self, stream.borrowed(), buf).await;
+                streams::HostOutputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                let n = n?;
                 if append {
                     let len = self.stat(fd2).await?;
                     position.store(len.size, Ordering::Relaxed);
@@ -1507,7 +1512,9 @@ impl<
                         .context("failed to call `write-via-stream`")
                         .unwrap_or_else(types::Error::trap)
                 })?;
-                blocking_mode.write(self, stream, buf).await?
+                let result = blocking_mode.write(self, stream.borrowed(), buf).await;
+                streams::HostOutputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                result?
             }
             Descriptor::Stdout { .. } | Descriptor::Stderr { .. } => {
                 // NOTE: legacy implementation returns SPIPE here
diff --git a/crates/wasi/wit/command-extended.wit b/crates/wasi/wit/command-extended.wit
index 2f1491ef9..4bff99e65 100644
--- a/crates/wasi/wit/command-extended.wit
+++ b/crates/wasi/wit/command-extended.wit
@@ -1,6 +1,6 @@
 // All of the same imports and exports available in the wasi:cli/command world
 // with addition of HTTP proxy related imports:
 world command-extended {
-  include wasi:cli/command@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/command@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/crates/wasi/wit/deps/cli/command.wit b/crates/wasi/wit/deps/cli/command.wit
index a9889164f..d8005bd38 100644
--- a/crates/wasi/wit/deps/cli/command.wit
+++ b/crates/wasi/wit/deps/cli/command.wit
@@ -1,4 +1,4 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world command {
   include imports;
diff --git a/crates/wasi/wit/deps/cli/imports.wit b/crates/wasi/wit/deps/cli/imports.wit
index 8ce1abec3..083b84a03 100644
--- a/crates/wasi/wit/deps/cli/imports.wit
+++ b/crates/wasi/wit/deps/cli/imports.wit
@@ -1,11 +1,11 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world imports {
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  include wasi:filesystem/imports@0.2.0-rc-2023-11-10;
-  include wasi:sockets/imports@0.2.0-rc-2024-01-16;
-  include wasi:random/imports@0.2.0-rc-2023-11-10;
-  include wasi:io/imports@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  include wasi:filesystem/imports@0.2.0;
+  include wasi:sockets/imports@0.2.0;
+  include wasi:random/imports@0.2.0;
+  include wasi:io/imports@0.2.0;
 
   import environment;
   import exit;
diff --git a/crates/wasi/wit/deps/cli/stdio.wit b/crates/wasi/wit/deps/cli/stdio.wit
index 1b653b6e2..31ef35b5a 100644
--- a/crates/wasi/wit/deps/cli/stdio.wit
+++ b/crates/wasi/wit/deps/cli/stdio.wit
@@ -1,17 +1,17 @@
 interface stdin {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream};
+  use wasi:io/streams@0.2.0.{input-stream};
 
   get-stdin: func() -> input-stream;
 }
 
 interface stdout {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stdout: func() -> output-stream;
 }
 
 interface stderr {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stderr: func() -> output-stream;
 }
diff --git a/crates/wasi/wit/deps/clocks/monotonic-clock.wit b/crates/wasi/wit/deps/clocks/monotonic-clock.wit
index 09ef32c36..4e4dc3a19 100644
--- a/crates/wasi/wit/deps/clocks/monotonic-clock.wit
+++ b/crates/wasi/wit/deps/clocks/monotonic-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 /// WASI Monotonic Clock is a clock API intended to let users measure elapsed
 /// time.
 ///
@@ -10,7 +10,7 @@ package wasi:clocks@0.2.0-rc-2023-11-10;
 ///
 /// It is intended for measuring elapsed time.
 interface monotonic-clock {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
 
     /// An instant in time, in nanoseconds. An instant is relative to an
     /// unspecified initial value, and can only be compared to instances from
diff --git a/crates/wasi/wit/deps/clocks/wall-clock.wit b/crates/wasi/wit/deps/clocks/wall-clock.wit
index 8abb9a0c0..440ca0f33 100644
--- a/crates/wasi/wit/deps/clocks/wall-clock.wit
+++ b/crates/wasi/wit/deps/clocks/wall-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 /// WASI Wall Clock is a clock API intended to let users query the current
 /// time. The name "wall" makes an analogy to a "clock on the wall", which
 /// is not necessarily monotonic as it may be reset.
diff --git a/crates/wasi/wit/deps/clocks/world.wit b/crates/wasi/wit/deps/clocks/world.wit
index 8fa080f0e..c0224572a 100644
--- a/crates/wasi/wit/deps/clocks/world.wit
+++ b/crates/wasi/wit/deps/clocks/world.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 
 world imports {
     import monotonic-clock;
diff --git a/crates/wasi/wit/deps/filesystem/preopens.wit b/crates/wasi/wit/deps/filesystem/preopens.wit
index 95ec67843..da801f6d6 100644
--- a/crates/wasi/wit/deps/filesystem/preopens.wit
+++ b/crates/wasi/wit/deps/filesystem/preopens.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 interface preopens {
     use types.{descriptor};
diff --git a/crates/wasi/wit/deps/filesystem/types.wit b/crates/wasi/wit/deps/filesystem/types.wit
index 059722ab8..11108fcda 100644
--- a/crates/wasi/wit/deps/filesystem/types.wit
+++ b/crates/wasi/wit/deps/filesystem/types.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 /// WASI filesystem is a filesystem API primarily intended to let users run WASI
 /// programs that access their files on their existing filesystems, without
 /// significant overhead.
@@ -24,8 +24,8 @@ package wasi:filesystem@0.2.0-rc-2023-11-10;
 ///
 /// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md
 interface types {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream, error};
-    use wasi:clocks/wall-clock@0.2.0-rc-2023-11-10.{datetime};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream, error};
+    use wasi:clocks/wall-clock@0.2.0.{datetime};
 
     /// File size or length of a region within a file.
     type filesize = u64;
diff --git a/crates/wasi/wit/deps/filesystem/world.wit b/crates/wasi/wit/deps/filesystem/world.wit
index 285e0bae9..663f57920 100644
--- a/crates/wasi/wit/deps/filesystem/world.wit
+++ b/crates/wasi/wit/deps/filesystem/world.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 world imports {
     import types;
diff --git a/crates/wasi/wit/deps/http/proxy.wit b/crates/wasi/wit/deps/http/proxy.wit
index 2b0ce4b8a..687c24d23 100644
--- a/crates/wasi/wit/deps/http/proxy.wit
+++ b/crates/wasi/wit/deps/http/proxy.wit
@@ -1,4 +1,4 @@
-package wasi:http@0.2.0-rc-2024-01-16;
+package wasi:http@0.2.0;
 
 /// The `wasi:http/proxy` world captures a widely-implementable intersection of
 /// hosts that includes HTTP forward and reverse proxies. Components targeting
@@ -6,19 +6,19 @@ package wasi:http@0.2.0-rc-2024-01-16;
 /// outgoing HTTP requests.
 world proxy {
   /// HTTP proxies have access to time and randomness.
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  import wasi:random/random@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  import wasi:random/random@0.2.0;
 
   /// Proxies have standard output and error streams which are expected to
   /// terminate in a developer-facing console provided by the host.
-  import wasi:cli/stdout@0.2.0-rc-2024-01-16;
-  import wasi:cli/stderr@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdout@0.2.0;
+  import wasi:cli/stderr@0.2.0;
 
   /// TODO: this is a temporary workaround until component tooling is able to
   /// gracefully handle the absence of stdin. Hosts must return an eof stream
   /// for this import, which is what wasi-libc + tooling will do automatically
   /// when this import is properly removed.
-  import wasi:cli/stdin@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdin@0.2.0;
 
   /// This is the default handler to use when user code simply wants to make an
   /// HTTP request (e.g., via `fetch()`).
diff --git a/crates/wasi/wit/deps/http/types.wit b/crates/wasi/wit/deps/http/types.wit
index 0f698e769..755ac6a6b 100644
--- a/crates/wasi/wit/deps/http/types.wit
+++ b/crates/wasi/wit/deps/http/types.wit
@@ -2,10 +2,10 @@
 /// HTTP Requests and Responses, both incoming and outgoing, as well as
 /// their headers, trailers, and bodies.
 interface types {
-  use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-  use wasi:io/error@0.2.0-rc-2023-11-10.{error as io-error};
-  use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+  use wasi:clocks/monotonic-clock@0.2.0.{duration};
+  use wasi:io/streams@0.2.0.{input-stream, output-stream};
+  use wasi:io/error@0.2.0.{error as io-error};
+  use wasi:io/poll@0.2.0.{pollable};
 
   /// This type corresponds to HTTP standard Methods.
   variant method {
diff --git a/crates/wasi/wit/deps/io/error.wit b/crates/wasi/wit/deps/io/error.wit
index 31918acbb..22e5b6489 100644
--- a/crates/wasi/wit/deps/io/error.wit
+++ b/crates/wasi/wit/deps/io/error.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 
 interface error {
diff --git a/crates/wasi/wit/deps/io/poll.wit b/crates/wasi/wit/deps/io/poll.wit
index 81b1cab99..ddc67f8b7 100644
--- a/crates/wasi/wit/deps/io/poll.wit
+++ b/crates/wasi/wit/deps/io/poll.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// A poll API intended to let users wait for I/O events on multiple handles
 /// at once.
diff --git a/crates/wasi/wit/deps/io/streams.wit b/crates/wasi/wit/deps/io/streams.wit
index 82e6e073e..6d2f871e3 100644
--- a/crates/wasi/wit/deps/io/streams.wit
+++ b/crates/wasi/wit/deps/io/streams.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// WASI I/O is an I/O abstraction API which is currently focused on providing
 /// stream types.
diff --git a/crates/wasi/wit/deps/io/world.wit b/crates/wasi/wit/deps/io/world.wit
index 8243da2ee..5f0b43fe5 100644
--- a/crates/wasi/wit/deps/io/world.wit
+++ b/crates/wasi/wit/deps/io/world.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 world imports {
     import streams;
diff --git a/crates/wasi/wit/deps/random/insecure-seed.wit b/crates/wasi/wit/deps/random/insecure-seed.wit
index f76e87dad..47210ac6b 100644
--- a/crates/wasi/wit/deps/random/insecure-seed.wit
+++ b/crates/wasi/wit/deps/random/insecure-seed.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure-seed interface for seeding hash-map DoS resistance.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi/wit/deps/random/insecure.wit b/crates/wasi/wit/deps/random/insecure.wit
index ec7b99737..c58f4ee85 100644
--- a/crates/wasi/wit/deps/random/insecure.wit
+++ b/crates/wasi/wit/deps/random/insecure.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure interface for insecure pseudo-random numbers.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi/wit/deps/random/random.wit b/crates/wasi/wit/deps/random/random.wit
index 7a7dfa27a..0c017f093 100644
--- a/crates/wasi/wit/deps/random/random.wit
+++ b/crates/wasi/wit/deps/random/random.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// WASI Random is a random data API.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi/wit/deps/random/world.wit b/crates/wasi/wit/deps/random/world.wit
index 49e5743b4..3da34914a 100644
--- a/crates/wasi/wit/deps/random/world.wit
+++ b/crates/wasi/wit/deps/random/world.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 
 world imports {
     import random;
diff --git a/crates/wasi/wit/deps/sockets/ip-name-lookup.wit b/crates/wasi/wit/deps/sockets/ip-name-lookup.wit
index 931ccf7e0..8e639ec59 100644
--- a/crates/wasi/wit/deps/sockets/ip-name-lookup.wit
+++ b/crates/wasi/wit/deps/sockets/ip-name-lookup.wit
@@ -1,6 +1,6 @@
 
 interface ip-name-lookup {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-address};
 
 
diff --git a/crates/wasi/wit/deps/sockets/tcp.wit b/crates/wasi/wit/deps/sockets/tcp.wit
index 9f12b8212..5902b9ee0 100644
--- a/crates/wasi/wit/deps/sockets/tcp.wit
+++ b/crates/wasi/wit/deps/sockets/tcp.wit
@@ -1,8 +1,8 @@
 
 interface tcp {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
-    use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream};
+    use wasi:io/poll@0.2.0.{pollable};
+    use wasi:clocks/monotonic-clock@0.2.0.{duration};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     enum shutdown-type {
diff --git a/crates/wasi/wit/deps/sockets/udp.wit b/crates/wasi/wit/deps/sockets/udp.wit
index 6ba380ff7..d987a0a90 100644
--- a/crates/wasi/wit/deps/sockets/udp.wit
+++ b/crates/wasi/wit/deps/sockets/udp.wit
@@ -1,6 +1,6 @@
 
 interface udp {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     /// A received datagram.
diff --git a/crates/wasi/wit/deps/sockets/world.wit b/crates/wasi/wit/deps/sockets/world.wit
index 8588cc6c1..f8bb92ae0 100644
--- a/crates/wasi/wit/deps/sockets/world.wit
+++ b/crates/wasi/wit/deps/sockets/world.wit
@@ -1,4 +1,4 @@
-package wasi:sockets@0.2.0-rc-2024-01-16;
+package wasi:sockets@0.2.0;
 
 world imports {
     import instance-network;
diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs
index fd44bd443..221c45470 100644
--- a/crates/wasmtime/src/config.rs
+++ b/crates/wasmtime/src/config.rs
@@ -228,6 +228,8 @@ impl Config {
         ret.wasm_multi_value(true);
         ret.wasm_bulk_memory(true);
         ret.wasm_simd(true);
+        #[cfg(feature = "component-model")]
+        ret.wasm_component_model(true);
         ret.wasm_backtrace_details(WasmBacktraceDetails::Environment);
 
         // This is on-by-default in `wasmparser` since it's a stage 4+ proposal
diff --git a/crates/winch/src/compiler.rs b/crates/winch/src/compiler.rs
index bc1191887..c58318eb8 100644
--- a/crates/winch/src/compiler.rs
+++ b/crates/winch/src/compiler.rs
@@ -1,4 +1,5 @@
 use anyhow::Result;
+use cranelift_codegen::isa::unwind::UnwindInfoKind;
 use object::write::{Object, SymbolId};
 use std::any::Any;
 use std::mem;
@@ -63,6 +64,27 @@ impl Compiler {
         context.allocations = allocs;
         self.contexts.lock().unwrap().push(context);
     }
+
+    /// Emit unwind info into the [`CompiledFunction`].
+    fn emit_unwind_info(
+        &self,
+        compiled_function: &mut CompiledFunction<CompiledFuncEnv>,
+    ) -> Result<(), CompileError> {
+        let kind = match self.isa.triple().operating_system {
+            target_lexicon::OperatingSystem::Windows => UnwindInfoKind::Windows,
+            _ => UnwindInfoKind::SystemV,
+        };
+
+        if let Some(info) = self
+            .isa
+            .emit_unwind_info(&compiled_function.buffer, kind)
+            .map_err(|e| CompileError::Codegen(format!("{e:?}")))?
+        {
+            compiled_function.set_unwind_info(info);
+        }
+
+        Ok(())
+    }
 }
 
 impl wasmtime_environ::Compiler for Compiler {
@@ -98,9 +120,14 @@ impl wasmtime_environ::Compiler for Compiler {
             .map_err(|e| CompileError::Codegen(format!("{e:?}")));
         self.save_context(context, validator.into_allocations());
         let buffer = buffer?;
-        let compiled_function =
+
+        let mut compiled_function =
             CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
 
+        if self.isa.flags().unwind_info() {
+            self.emit_unwind_info(&mut compiled_function)?;
+        }
+
         Ok((
             WasmFunctionInfo {
                 start_srcloc,
@@ -123,9 +150,14 @@ impl wasmtime_environ::Compiler for Compiler {
             .isa
             .compile_trampoline(&ty, TrampolineKind::ArrayToWasm(func_index))
             .map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
-        let compiled_function =
+
+        let mut compiled_function =
             CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
 
+        if self.isa.flags().unwind_info() {
+            self.emit_unwind_info(&mut compiled_function)?;
+        }
+
         Ok(Box::new(compiled_function))
     }
 
@@ -144,9 +176,13 @@ impl wasmtime_environ::Compiler for Compiler {
             .compile_trampoline(ty, TrampolineKind::NativeToWasm(func_index))
             .map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
 
-        let compiled_function =
+        let mut compiled_function =
             CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
 
+        if self.isa.flags().unwind_info() {
+            self.emit_unwind_info(&mut compiled_function)?;
+        }
+
         Ok(Box::new(compiled_function))
     }
 
@@ -159,9 +195,13 @@ impl wasmtime_environ::Compiler for Compiler {
             .compile_trampoline(wasm_func_ty, TrampolineKind::WasmToNative)
             .map_err(|e| CompileError::Codegen(format!("{:?}", e)))?;
 
-        let compiled_function =
+        let mut compiled_function =
             CompiledFunction::new(buffer, CompiledFuncEnv {}, self.isa.function_alignment());
 
+        if self.isa.flags().unwind_info() {
+            self.emit_unwind_info(&mut compiled_function)?;
+        }
+
         Ok(Box::new(compiled_function))
     }
 
diff --git a/src/common.rs b/src/common.rs
index 70782c0b3..2850639d0 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -107,7 +107,7 @@ impl RunCommon {
 
     #[cfg(feature = "component-model")]
     fn ensure_allow_components(&self) -> Result<()> {
-        if self.common.wasm.component_model != Some(true) {
+        if self.common.wasm.component_model == Some(false) {
             bail!("cannot execute a component without `--wasm component-model`");
         }
 
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 1ffc14475..2ab2a8a11 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -1954,6 +1954,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-encoder]]
+version = "0.40.0"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-metadata]]
 version = "0.10.9"
 when = "2023-10-14"
@@ -1996,6 +2003,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-metadata]]
+version = "0.10.16"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-mutate]]
 version = "0.2.38"
 when = "2023-10-14"
@@ -2031,6 +2045,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-mutate]]
+version = "0.2.45"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-smith]]
 version = "0.12.21"
 when = "2023-10-14"
@@ -2073,6 +2094,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-smith]]
+version = "0.15.0"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmparser]]
 version = "0.115.0"
 when = "2023-10-14"
@@ -2115,6 +2143,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmparser]]
+version = "0.120.0"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmprinter]]
 version = "0.2.70"
 when = "2023-10-14"
@@ -2157,6 +2192,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmprinter]]
+version = "0.2.77"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmtime]]
 version = "14.0.2"
 when = "2023-10-26"
@@ -2775,6 +2817,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wast]]
+version = "70.0.1"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wat]]
 version = "1.0.77"
 when = "2023-10-14"
@@ -2817,6 +2866,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wat]]
+version = "1.0.84"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wiggle]]
 version = "14.0.2"
 when = "2023-10-26"
@@ -3200,6 +3256,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-component]]
+version = "0.20.0"
+when = "2024-01-24"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wit-parser]]
 version = "0.12.1"
 when = "2023-10-18"
diff --git a/winch/codegen/Cargo.toml b/winch/codegen/Cargo.toml
index cc2b942ff..90c52fa5c 100644
--- a/winch/codegen/Cargo.toml
+++ b/winch/codegen/Cargo.toml
@@ -19,7 +19,7 @@ target-lexicon = { workspace = true, features = ["std"] }
 # mostly to have access to `PReg`s and the calling convention.
 # In the next iteration we'll factor out the common bits so that they can be consumed
 # by Cranelift and Winch.
-cranelift-codegen = { workspace = true }
+cranelift-codegen = { workspace = true, features = ["unwind"] }
 regalloc2 = { workspace = true }
 gimli = { workspace = true }
 wasmtime-environ = { workspace = true }
diff --git a/winch/codegen/src/isa/aarch64/mod.rs b/winch/codegen/src/isa/aarch64/mod.rs
index 15d6b2188..a17e8fbdd 100644
--- a/winch/codegen/src/isa/aarch64/mod.rs
+++ b/winch/codegen/src/isa/aarch64/mod.rs
@@ -134,4 +134,12 @@ impl TargetIsa for Aarch64 {
     ) -> Result<MachBufferFinalized<Final>> {
         todo!()
     }
+
+    fn emit_unwind_info(
+        &self,
+        _result: &MachBufferFinalized<Final>,
+        _kind: cranelift_codegen::isa::unwind::UnwindInfoKind,
+    ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>> {
+        todo!()
+    }
 }
diff --git a/winch/codegen/src/isa/mod.rs b/winch/codegen/src/isa/mod.rs
index 7ccf621f5..2579840d9 100644
--- a/winch/codegen/src/isa/mod.rs
+++ b/winch/codegen/src/isa/mod.rs
@@ -1,6 +1,7 @@
 use crate::{BuiltinFunctions, TrampolineKind};
 use anyhow::{anyhow, Result};
 use core::fmt::Formatter;
+use cranelift_codegen::isa::unwind::{UnwindInfo, UnwindInfoKind};
 use cranelift_codegen::isa::{CallConv, IsaBuilder};
 use cranelift_codegen::settings;
 use cranelift_codegen::{Final, MachBufferFinalized, TextSectionBuilder};
@@ -184,6 +185,12 @@ pub trait TargetIsa: Send + Sync {
         self.triple().endianness().unwrap()
     }
 
+    fn emit_unwind_info(
+        &self,
+        _result: &MachBufferFinalized<Final>,
+        _kind: UnwindInfoKind,
+    ) -> Result<Option<UnwindInfo>>;
+
     /// See `cranelift_codegen::isa::TargetIsa::create_systemv_cie`.
     fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
         // By default, an ISA cannot create a System V CIE.
diff --git a/winch/codegen/src/isa/reg.rs b/winch/codegen/src/isa/reg.rs
index 0a96df329..bfdcdb8fc 100644
--- a/winch/codegen/src/isa/reg.rs
+++ b/winch/codegen/src/isa/reg.rs
@@ -1,5 +1,6 @@
-use regalloc2::PReg;
+use cranelift_codegen::RealReg;
 pub use regalloc2::RegClass;
+use regalloc2::{PReg, VReg};
 
 /// A newtype abstraction on top of a physical register.
 //
@@ -71,3 +72,15 @@ impl std::fmt::Debug for Reg {
         write!(f, "{}", self.0)
     }
 }
+
+impl Into<VReg> for Reg {
+    fn into(self) -> VReg {
+        VReg::new(self.inner().index(), self.class())
+    }
+}
+
+impl Into<RealReg> for Reg {
+    fn into(self) -> RealReg {
+        Into::<VReg>::into(self).into()
+    }
+}
diff --git a/winch/codegen/src/isa/x64/asm.rs b/winch/codegen/src/isa/x64/asm.rs
index 256d4fb9f..27acea761 100644
--- a/winch/codegen/src/isa/x64/asm.rs
+++ b/winch/codegen/src/isa/x64/asm.rs
@@ -8,6 +8,7 @@ use cranelift_codegen::{
     entity::EntityRef,
     ir::{types, ConstantPool, ExternalName, LibCall, Opcode, TrapCode, UserExternalNameRef},
     isa::{
+        unwind::UnwindInst,
         x64::{
             args::{
                 self, AluRmiROpcode, Amode, CmpOpcode, DivSignedness, ExtMode, FromWritableReg,
@@ -229,6 +230,11 @@ impl Assembler {
         }
     }
 
+    /// Emit an unwind instruction.
+    pub fn emit_unwind_inst(&mut self, inst: UnwindInst) {
+        self.emit(Inst::Unwind { inst })
+    }
+
     /// Push register.
     pub fn push_r(&mut self, reg: Reg) {
         self.emit(Inst::Push64 { src: reg.into() });
@@ -627,9 +633,10 @@ impl Assembler {
             _ => unimplemented!(),
         };
 
-        self.emit(Inst::XmmUnaryRmRUnaligned {
+        self.emit(Inst::XmmRmRUnaligned {
             op,
-            src: Xmm::new(src.into()).expect("valid xmm unaligned").into(),
+            src2: Xmm::new(src.into()).expect("valid xmm unaligned").into(),
+            src1: dst.into(),
             dst: dst.into(),
         });
     }
@@ -1158,9 +1165,10 @@ impl Assembler {
             OperandSize::S128 => unreachable!(),
         };
 
-        self.emit(Inst::XmmUnaryRmR {
+        self.emit(Inst::XmmRmR {
             op,
-            src: Xmm::from(src).into(),
+            src2: Xmm::from(src).into(),
+            src1: dst.into(),
             dst: dst.into(),
         })
     }
diff --git a/winch/codegen/src/isa/x64/masm.rs b/winch/codegen/src/isa/x64/masm.rs
index 7000dacdd..680adb481 100644
--- a/winch/codegen/src/isa/x64/masm.rs
+++ b/winch/codegen/src/isa/x64/masm.rs
@@ -24,7 +24,8 @@ use crate::{
     masm::CalleeKind,
 };
 use cranelift_codegen::{
-    isa::x64::settings as x64_settings, settings, Final, MachBufferFinalized, MachLabel,
+    isa::unwind::UnwindInst, isa::x64::settings as x64_settings, settings, Final,
+    MachBufferFinalized, MachLabel,
 };
 
 use wasmtime_environ::{PtrSize, WasmType, WASM_PAGE_SIZE};
@@ -53,8 +54,25 @@ impl Masm for MacroAssembler {
         let stack_pointer = rsp();
 
         self.asm.push_r(frame_pointer);
+
+        if self.shared_flags.unwind_info() {
+            self.asm.emit_unwind_inst(UnwindInst::PushFrameRegs {
+                offset_upward_to_caller_sp: Self::ABI::arg_base_offset().try_into().unwrap(),
+            })
+        }
+
         self.asm
             .mov_rr(stack_pointer, frame_pointer, OperandSize::S64);
+
+        if self.shared_flags.unwind_info() {
+            self.asm.emit_unwind_inst(UnwindInst::DefineNewFrame {
+                offset_upward_to_caller_sp: Self::ABI::arg_base_offset().try_into().unwrap(),
+
+                // Clobbers appear directly after the RET and FP if they're present. As we just
+                // pushed the frame pointer, the offset to the clobbers will be `0`.
+                offset_downward_to_clobbers: 0,
+            })
+        }
     }
 
     fn check_stack(&mut self) {
@@ -107,6 +125,19 @@ impl Masm for MacroAssembler {
         }
     }
 
+    fn save(&mut self, clobber_offset: u32, reg: Reg, size: OperandSize) -> StackSlot {
+        let slot = self.push(reg, size);
+
+        if self.shared_flags.unwind_info() {
+            self.asm.emit_unwind_inst(UnwindInst::SaveReg {
+                clobber_offset,
+                reg: reg.into(),
+            });
+        }
+
+        slot
+    }
+
     fn reserve_stack(&mut self, bytes: u32) {
         if bytes == 0 {
             return;
diff --git a/winch/codegen/src/isa/x64/mod.rs b/winch/codegen/src/isa/x64/mod.rs
index 7e56d933f..e14baae00 100644
--- a/winch/codegen/src/isa/x64/mod.rs
+++ b/winch/codegen/src/isa/x64/mod.rs
@@ -169,4 +169,16 @@ impl TargetIsa for X64 {
 
         Ok(masm.finalize())
     }
+
+    fn emit_unwind_info(
+        &self,
+        buffer: &MachBufferFinalized<Final>,
+        kind: cranelift_codegen::isa::unwind::UnwindInfoKind,
+    ) -> Result<Option<cranelift_codegen::isa::unwind::UnwindInfo>> {
+        Ok(cranelift_codegen::isa::x64::emit_unwind_info(buffer, kind)?)
+    }
+
+    fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
+        Some(cranelift_codegen::isa::x64::create_cie())
+    }
 }
diff --git a/winch/codegen/src/masm.rs b/winch/codegen/src/masm.rs
index f12d284ec..3ea75a40e 100644
--- a/winch/codegen/src/masm.rs
+++ b/winch/codegen/src/masm.rs
@@ -766,4 +766,11 @@ pub(crate) trait MacroAssembler {
             self.free_stack(bytes);
         }
     }
+
+    /// Save the value of this register to the stack. By default this is the same as pushing the
+    /// register, however it's present in the [`MacroAssembler`] trait to ensure that it's possible
+    /// to add unwind info for register saves in backends.
+    fn save(&mut self, _off: u32, src: Reg, size: OperandSize) -> StackSlot {
+        self.push(src, size)
+    }
 }
diff --git a/winch/codegen/src/trampoline.rs b/winch/codegen/src/trampoline.rs
index 6d3e4bcfd..bd651ad63 100644
--- a/winch/codegen/src/trampoline.rs
+++ b/winch/codegen/src/trampoline.rs
@@ -705,8 +705,10 @@ where
     fn prologue_with_callee_saved(&mut self) {
         self.masm.prologue();
         // Save any callee-saved registers.
+        let mut off = 0;
         for (r, s) in &self.callee_saved_regs {
-            self.masm.push(*r, *s);
+            let slot = self.masm.save(off, *r, *s);
+            off += slot.size;
         }
     }
 


Test patch:
diff --git a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs
index 147f61deb..b340f6e2a 100644
--- a/cranelift/codegen/src/isa/x64/inst/emit_tests.rs
+++ b/cranelift/codegen/src/isa/x64/inst/emit_tests.rs
@@ -4889,25 +4889,25 @@ fn test_x64_emit() {
     ));
 
     insns.push((
-        Inst::xmm_unary_rm_r(SseOpcode::Sqrtss, RegMem::reg(xmm7), w_xmm8),
+        Inst::xmm_rm_r(SseOpcode::Sqrtss, RegMem::reg(xmm7), w_xmm8),
         "F3440F51C7",
-        "sqrtss  %xmm7, %xmm8",
+        "sqrtss  %xmm8, %xmm7, %xmm8",
     ));
     insns.push((
-        Inst::xmm_unary_rm_r(SseOpcode::Sqrtsd, RegMem::reg(xmm1), w_xmm2),
+        Inst::xmm_rm_r(SseOpcode::Sqrtsd, RegMem::reg(xmm1), w_xmm2),
         "F20F51D1",
-        "sqrtsd  %xmm1, %xmm2",
+        "sqrtsd  %xmm2, %xmm1, %xmm2",
     ));
 
     insns.push((
-        Inst::xmm_unary_rm_r(SseOpcode::Cvtss2sd, RegMem::reg(xmm0), w_xmm1),
+        Inst::xmm_rm_r(SseOpcode::Cvtss2sd, RegMem::reg(xmm0), w_xmm1),
         "F30F5AC8",
-        "cvtss2sd %xmm0, %xmm1",
+        "cvtss2sd %xmm1, %xmm0, %xmm1",
     ));
     insns.push((
-        Inst::xmm_unary_rm_r(SseOpcode::Cvtsd2ss, RegMem::reg(xmm1), w_xmm0),
+        Inst::xmm_rm_r(SseOpcode::Cvtsd2ss, RegMem::reg(xmm1), w_xmm0),
         "F20F5AC1",
-        "cvtsd2ss %xmm1, %xmm0",
+        "cvtsd2ss %xmm0, %xmm1, %xmm0",
     ));
 
     insns.push((
diff --git a/cranelift/filetests/filetests/isa/x64/fpromote-demote-avx.clif b/cranelift/filetests/filetests/isa/x64/fpromote-demote-avx.clif
index 4b07ebfa4..3feb3e07e 100644
--- a/cranelift/filetests/filetests/isa/x64/fpromote-demote-avx.clif
+++ b/cranelift/filetests/filetests/isa/x64/fpromote-demote-avx.clif
@@ -11,7 +11,9 @@ block0(v0: f32):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   vcvtss2sd %xmm0, %xmm0
+;   uninit  %xmm2
+;   vxorpd  %xmm2, %xmm2, %xmm4
+;   vcvtss2sd %xmm4, %xmm0, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -21,7 +23,8 @@ block0(v0: f32):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   vcvtss2sd %xmm0, %xmm0, %xmm0
+;   vxorpd %xmm2, %xmm2, %xmm4
+;   vcvtss2sd %xmm0, %xmm4, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -42,9 +45,11 @@ block0(v1: i64, v2: f32):
 ;   movq    %rsp, %rbp
 ;   subq    %rsp, $16, %rsp
 ; block0:
-;   lea     rsp(0 + virtual offset), %rdx
-;   vmovss  %xmm0, 0(%rdx)
-;   vcvtss2sd 0(%rdx), %xmm0
+;   lea     rsp(0 + virtual offset), %r9
+;   vmovss  %xmm0, 0(%r9)
+;   uninit  %xmm5
+;   vxorpd  %xmm5, %xmm5, %xmm7
+;   vcvtss2sd %xmm7, 0(%r9), %xmm0
 ;   addq    %rsp, $16, %rsp
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
@@ -56,9 +61,10 @@ block0(v1: i64, v2: f32):
 ;   movq %rsp, %rbp
 ;   subq $0x10, %rsp
 ; block1: ; offset 0x8
-;   leaq (%rsp), %rdx
-;   vmovss %xmm0, (%rdx) ; trap: heap_oob
-;   vcvtss2sd (%rdx), %xmm0, %xmm0 ; trap: heap_oob
+;   leaq (%rsp), %r9
+;   vmovss %xmm0, (%r9) ; trap: heap_oob
+;   vxorpd %xmm5, %xmm5, %xmm7
+;   vcvtss2sd (%r9), %xmm7, %xmm0 ; trap: heap_oob
 ;   addq $0x10, %rsp
 ;   movq %rbp, %rsp
 ;   popq %rbp
@@ -74,7 +80,9 @@ block0(v0: f64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   vcvtsd2ss %xmm0, %xmm0
+;   uninit  %xmm2
+;   vxorps  %xmm2, %xmm2, %xmm4
+;   vcvtsd2ss %xmm4, %xmm0, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -84,7 +92,8 @@ block0(v0: f64):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   vcvtsd2ss %xmm0, %xmm0, %xmm0
+;   vxorps %xmm2, %xmm2, %xmm4
+;   vcvtsd2ss %xmm0, %xmm4, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -105,9 +114,11 @@ block0(v1: i64, v2: f64):
 ;   movq    %rsp, %rbp
 ;   subq    %rsp, $16, %rsp
 ; block0:
-;   lea     rsp(0 + virtual offset), %rdx
-;   vmovsd  %xmm0, 0(%rdx)
-;   vcvtsd2ss 0(%rdx), %xmm0
+;   lea     rsp(0 + virtual offset), %r9
+;   vmovsd  %xmm0, 0(%r9)
+;   uninit  %xmm5
+;   vxorps  %xmm5, %xmm5, %xmm7
+;   vcvtsd2ss %xmm7, 0(%r9), %xmm0
 ;   addq    %rsp, $16, %rsp
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
@@ -119,9 +130,10 @@ block0(v1: i64, v2: f64):
 ;   movq %rsp, %rbp
 ;   subq $0x10, %rsp
 ; block1: ; offset 0x8
-;   leaq (%rsp), %rdx
-;   vmovsd %xmm0, (%rdx) ; trap: heap_oob
-;   vcvtsd2ss (%rdx), %xmm0, %xmm0 ; trap: heap_oob
+;   leaq (%rsp), %r9
+;   vmovsd %xmm0, (%r9) ; trap: heap_oob
+;   vxorps %xmm5, %xmm5, %xmm7
+;   vcvtsd2ss (%r9), %xmm7, %xmm0 ; trap: heap_oob
 ;   addq $0x10, %rsp
 ;   movq %rbp, %rsp
 ;   popq %rbp
diff --git a/cranelift/filetests/filetests/isa/x64/fpromote-demote.clif b/cranelift/filetests/filetests/isa/x64/fpromote-demote.clif
index 465460962..c7dc0db58 100644
--- a/cranelift/filetests/filetests/isa/x64/fpromote-demote.clif
+++ b/cranelift/filetests/filetests/isa/x64/fpromote-demote.clif
@@ -11,7 +11,11 @@ block0(v0: f32):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   cvtss2sd %xmm0, %xmm0
+;   movdqa  %xmm0, %xmm5
+;   uninit  %xmm0
+;   xorpd   %xmm0, %xmm0, %xmm0
+;   movdqa  %xmm5, %xmm7
+;   cvtss2sd %xmm0, %xmm7, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -21,7 +25,10 @@ block0(v0: f32):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   cvtss2sd %xmm0, %xmm0
+;   movdqa %xmm0, %xmm5
+;   xorpd %xmm0, %xmm0
+;   movdqa %xmm5, %xmm7
+;   cvtss2sd %xmm7, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -42,9 +49,11 @@ block0(v1: i64, v2: f32):
 ;   movq    %rsp, %rbp
 ;   subq    %rsp, $16, %rsp
 ; block0:
-;   lea     rsp(0 + virtual offset), %rdx
-;   movss   %xmm0, 0(%rdx)
-;   cvtss2sd 0(%rdx), %xmm0
+;   lea     rsp(0 + virtual offset), %r9
+;   movss   %xmm0, 0(%r9)
+;   uninit  %xmm0
+;   xorpd   %xmm0, %xmm0, %xmm0
+;   cvtss2sd %xmm0, 0(%r9), %xmm0
 ;   addq    %rsp, $16, %rsp
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
@@ -56,9 +65,10 @@ block0(v1: i64, v2: f32):
 ;   movq %rsp, %rbp
 ;   subq $0x10, %rsp
 ; block1: ; offset 0x8
-;   leaq (%rsp), %rdx
-;   movss %xmm0, (%rdx) ; trap: heap_oob
-;   cvtss2sd (%rdx), %xmm0 ; trap: heap_oob
+;   leaq (%rsp), %r9
+;   movss %xmm0, (%r9) ; trap: heap_oob
+;   xorpd %xmm0, %xmm0
+;   cvtss2sd (%r9), %xmm0 ; trap: heap_oob
 ;   addq $0x10, %rsp
 ;   movq %rbp, %rsp
 ;   popq %rbp
@@ -74,7 +84,11 @@ block0(v0: f64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   cvtsd2ss %xmm0, %xmm0
+;   movdqa  %xmm0, %xmm5
+;   uninit  %xmm0
+;   xorps   %xmm0, %xmm0, %xmm0
+;   movdqa  %xmm5, %xmm7
+;   cvtsd2ss %xmm0, %xmm7, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -84,7 +98,10 @@ block0(v0: f64):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   cvtsd2ss %xmm0, %xmm0
+;   movdqa %xmm0, %xmm5
+;   xorps %xmm0, %xmm0
+;   movdqa %xmm5, %xmm7
+;   cvtsd2ss %xmm7, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -105,9 +122,11 @@ block0(v1: i64, v2: f64):
 ;   movq    %rsp, %rbp
 ;   subq    %rsp, $16, %rsp
 ; block0:
-;   lea     rsp(0 + virtual offset), %rdx
-;   movsd   %xmm0, 0(%rdx)
-;   cvtsd2ss 0(%rdx), %xmm0
+;   lea     rsp(0 + virtual offset), %r9
+;   movsd   %xmm0, 0(%r9)
+;   uninit  %xmm0
+;   xorps   %xmm0, %xmm0, %xmm0
+;   cvtsd2ss %xmm0, 0(%r9), %xmm0
 ;   addq    %rsp, $16, %rsp
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
@@ -119,9 +138,10 @@ block0(v1: i64, v2: f64):
 ;   movq %rsp, %rbp
 ;   subq $0x10, %rsp
 ; block1: ; offset 0x8
-;   leaq (%rsp), %rdx
-;   movsd %xmm0, (%rdx) ; trap: heap_oob
-;   cvtsd2ss (%rdx), %xmm0 ; trap: heap_oob
+;   leaq (%rsp), %r9
+;   movsd %xmm0, (%r9) ; trap: heap_oob
+;   xorps %xmm0, %xmm0
+;   cvtsd2ss (%r9), %xmm0 ; trap: heap_oob
 ;   addq $0x10, %rsp
 ;   movq %rbp, %rsp
 ;   popq %rbp
diff --git a/cranelift/filetests/filetests/isa/x64/fsqrt-avx.clif b/cranelift/filetests/filetests/isa/x64/fsqrt-avx.clif
index 1e87a00a2..7740c538c 100644
--- a/cranelift/filetests/filetests/isa/x64/fsqrt-avx.clif
+++ b/cranelift/filetests/filetests/isa/x64/fsqrt-avx.clif
@@ -11,7 +11,9 @@ block0(v0: f32):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   vsqrtss %xmm0, %xmm0
+;   uninit  %xmm2
+;   vxorps  %xmm2, %xmm2, %xmm4
+;   vsqrtss %xmm4, %xmm0, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -21,7 +23,8 @@ block0(v0: f32):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   vsqrtss %xmm0, %xmm0, %xmm0
+;   vxorps %xmm2, %xmm2, %xmm4
+;   vsqrtss %xmm0, %xmm4, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -36,7 +39,9 @@ block0(v0: f64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   vsqrtsd %xmm0, %xmm0
+;   uninit  %xmm2
+;   vxorpd  %xmm2, %xmm2, %xmm4
+;   vsqrtsd %xmm4, %xmm0, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -46,7 +51,8 @@ block0(v0: f64):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   vsqrtsd %xmm0, %xmm0, %xmm0
+;   vxorpd %xmm2, %xmm2, %xmm4
+;   vsqrtsd %xmm0, %xmm4, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
diff --git a/cranelift/filetests/filetests/isa/x64/fsqrt.clif b/cranelift/filetests/filetests/isa/x64/fsqrt.clif
index ec4c3f742..be10b19ac 100644
--- a/cranelift/filetests/filetests/isa/x64/fsqrt.clif
+++ b/cranelift/filetests/filetests/isa/x64/fsqrt.clif
@@ -11,7 +11,11 @@ block0(v0: f32):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   sqrtss  %xmm0, %xmm0
+;   movdqa  %xmm0, %xmm5
+;   uninit  %xmm0
+;   xorps   %xmm0, %xmm0, %xmm0
+;   movdqa  %xmm5, %xmm7
+;   sqrtss  %xmm0, %xmm7, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -21,7 +25,10 @@ block0(v0: f32):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   sqrtss %xmm0, %xmm0
+;   movdqa %xmm0, %xmm5
+;   xorps %xmm0, %xmm0
+;   movdqa %xmm5, %xmm7
+;   sqrtss %xmm7, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -36,7 +43,11 @@ block0(v0: f64):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   sqrtsd  %xmm0, %xmm0
+;   movdqa  %xmm0, %xmm5
+;   uninit  %xmm0
+;   xorpd   %xmm0, %xmm0, %xmm0
+;   movdqa  %xmm5, %xmm7
+;   sqrtsd  %xmm0, %xmm7, %xmm0
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -46,7 +57,10 @@ block0(v0: f64):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   sqrtsd %xmm0, %xmm0
+;   movdqa %xmm0, %xmm5
+;   xorpd %xmm0, %xmm0
+;   movdqa %xmm5, %xmm7
+;   sqrtsd %xmm7, %xmm0
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
diff --git a/crates/test-programs/src/bin/preview1_path_open_lots.rs b/crates/test-programs/src/bin/preview1_path_open_lots.rs
new file mode 100644
index 000000000..df163f95c
--- /dev/null
+++ b/crates/test-programs/src/bin/preview1_path_open_lots.rs
@@ -0,0 +1,107 @@
+use std::{env, process};
+use test_programs::preview1::{create_file, open_scratch_directory};
+
+unsafe fn test_path_open_lots(dir_fd: wasi::Fd) {
+    create_file(dir_fd, "file");
+
+    for _ in 0..2000 {
+        let f_readonly = wasi::path_open(dir_fd, 0, "file", 0, wasi::RIGHTS_FD_READ, 0, 0)
+            .expect("open file readonly");
+
+        let buffer = &mut [0u8; 100];
+        let iovec = wasi::Iovec {
+            buf: buffer.as_mut_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nread = wasi::fd_read(f_readonly, &[iovec]).expect("reading readonly file");
+        assert_eq!(nread, 0, "readonly file is empty");
+
+        wasi::fd_close(f_readonly).expect("close readonly");
+    }
+
+    for _ in 0..2000 {
+        let f_readonly = wasi::path_open(dir_fd, 0, "file", 0, wasi::RIGHTS_FD_READ, 0, 0)
+            .expect("open file readonly");
+
+        let buffer = &mut [0u8; 100];
+        let iovec = wasi::Iovec {
+            buf: buffer.as_mut_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nread = wasi::fd_pread(f_readonly, &[iovec], 0).expect("reading readonly file");
+        assert_eq!(nread, 0, "readonly file is empty");
+
+        wasi::fd_close(f_readonly).expect("close readonly");
+    }
+
+    for _ in 0..2000 {
+        let f = wasi::path_open(
+            dir_fd,
+            0,
+            "file",
+            0,
+            wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
+            0,
+            0,
+        )
+        .unwrap();
+
+        let buffer = &[0u8; 100];
+        let ciovec = wasi::Ciovec {
+            buf: buffer.as_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nwritten = wasi::fd_write(f, &[ciovec]).expect("write failed");
+        assert_eq!(nwritten, 100);
+
+        wasi::fd_close(f).unwrap();
+    }
+
+    for _ in 0..2000 {
+        let f = wasi::path_open(
+            dir_fd,
+            0,
+            "file",
+            0,
+            wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
+            0,
+            0,
+        )
+        .unwrap();
+
+        let buffer = &[0u8; 100];
+        let ciovec = wasi::Ciovec {
+            buf: buffer.as_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nwritten = wasi::fd_pwrite(f, &[ciovec], 0).expect("write failed");
+        assert_eq!(nwritten, 100);
+
+        wasi::fd_close(f).unwrap();
+    }
+
+    wasi::path_unlink_file(dir_fd, "file").expect("removing a file");
+}
+
+fn main() {
+    let mut args = env::args();
+    let prog = args.next().unwrap();
+    let arg = if let Some(arg) = args.next() {
+        arg
+    } else {
+        eprintln!("usage: {} <scratch directory>", prog);
+        process::exit(1);
+    };
+
+    // Open scratch directory
+    let dir_fd = match open_scratch_directory(&arg) {
+        Ok(dir_fd) => dir_fd,
+        Err(err) => {
+            eprintln!("{}", err);
+            process::exit(1)
+        }
+    };
+
+    // Run the tests.
+    unsafe { test_path_open_lots(dir_fd) }
+}
diff --git a/crates/wasi-common/tests/all/async_.rs b/crates/wasi-common/tests/all/async_.rs
index c7fd0df5e..4622da8fa 100644
--- a/crates/wasi-common/tests/all/async_.rs
+++ b/crates/wasi-common/tests/all/async_.rs
@@ -283,3 +283,7 @@ async fn preview1_unicode_output() {
 async fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE, true).await.unwrap()
 }
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS, true).await.unwrap()
+}
diff --git a/crates/wasi-common/tests/all/sync.rs b/crates/wasi-common/tests/all/sync.rs
index caa6cd21b..ce4d37c11 100644
--- a/crates/wasi-common/tests/all/sync.rs
+++ b/crates/wasi-common/tests/all/sync.rs
@@ -269,3 +269,7 @@ fn preview1_unicode_output() {
 fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE, true).unwrap()
 }
+#[test_log::test]
+fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS, true).unwrap()
+}
diff --git a/crates/wasi-http/wit/test.wit b/crates/wasi-http/wit/test.wit
index 15294b4aa..f59039103 100644
--- a/crates/wasi-http/wit/test.wit
+++ b/crates/wasi-http/wit/test.wit
@@ -2,21 +2,21 @@ package wasmtime:wasi;
 
 // only used as part of `test-programs`
 world test-reactor {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
 
   export add-strings: func(s: list<string>) -> u32;
   export get-strings: func() -> list<string>;
 
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   export write-strings-to: func(o: output-stream) -> result;
 
-  use wasi:filesystem/types@0.2.0-rc-2023-11-10.{descriptor-stat};
+  use wasi:filesystem/types@0.2.0.{descriptor-stat};
   export pass-an-imported-record: func(d: descriptor-stat) -> string;
 }
 
 world test-command {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
-  import wasi:http/types@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
+  import wasi:http/types@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/crates/wasi/tests/all/async_.rs b/crates/wasi/tests/all/async_.rs
index f47997e0e..1aaabe0d5 100644
--- a/crates/wasi/tests/all/async_.rs
+++ b/crates/wasi/tests/all/async_.rs
@@ -281,6 +281,10 @@ async fn preview1_unicode_output() {
 async fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE_COMPONENT, false).await.unwrap()
 }
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS_COMPONENT, false).await.unwrap()
+}
 
 #[test_log::test(tokio::test(flavor = "multi_thread"))]
 async fn preview2_sleep() {
diff --git a/crates/wasi/tests/all/preview1.rs b/crates/wasi/tests/all/preview1.rs
index 7acde9dd4..dcfcb0041 100644
--- a/crates/wasi/tests/all/preview1.rs
+++ b/crates/wasi/tests/all/preview1.rs
@@ -237,3 +237,7 @@ async fn preview1_unicode_output() {
 async fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE, true).await.unwrap()
 }
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS, true).await.unwrap()
+}
diff --git a/crates/wasi/tests/all/sync.rs b/crates/wasi/tests/all/sync.rs
index ce0c2e161..c12454643 100644
--- a/crates/wasi/tests/all/sync.rs
+++ b/crates/wasi/tests/all/sync.rs
@@ -228,6 +228,10 @@ fn preview1_unicode_output() {
 fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE_COMPONENT, false).unwrap()
 }
+#[test_log::test]
+fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS_COMPONENT, false).unwrap()
+}
 
 #[test_log::test]
 fn preview2_sleep() {
diff --git a/crates/wasi/wit/test.wit b/crates/wasi/wit/test.wit
index 15294b4aa..f59039103 100644
--- a/crates/wasi/wit/test.wit
+++ b/crates/wasi/wit/test.wit
@@ -2,21 +2,21 @@ package wasmtime:wasi;
 
 // only used as part of `test-programs`
 world test-reactor {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
 
   export add-strings: func(s: list<string>) -> u32;
   export get-strings: func() -> list<string>;
 
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   export write-strings-to: func(o: output-stream) -> result;
 
-  use wasi:filesystem/types@0.2.0-rc-2023-11-10.{descriptor-stat};
+  use wasi:filesystem/types@0.2.0.{descriptor-stat};
   export pass-an-imported-record: func(d: descriptor-stat) -> string;
 }
 
 world test-command {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
-  import wasi:http/types@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
+  import wasi:http/types@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/tests/all/cli_tests.rs b/tests/all/cli_tests.rs
index 478c25830..f5fcc6a5e 100644
--- a/tests/all/cli_tests.rs
+++ b/tests/all/cli_tests.rs
@@ -760,6 +760,7 @@ fn component_missing_feature() -> Result<()> {
     let wasm = build_wasm(path)?;
     let output = get_wasmtime_command()?
         .arg("-Ccache=n")
+        .arg("-Wcomponent-model=n")
         .arg(wasm.path())
         .output()?;
     assert!(!output.status.success());
@@ -772,6 +773,7 @@ fn component_missing_feature() -> Result<()> {
     // also tests with raw *.wat input
     let output = get_wasmtime_command()?
         .arg("-Ccache=n")
+        .arg("-Wcomponent-model=n")
         .arg(path)
         .output()?;
     assert!(!output.status.success());
@@ -784,6 +786,27 @@ fn component_missing_feature() -> Result<()> {
     Ok(())
 }
 
+#[test]
+#[cfg_attr(not(feature = "component-model"), ignore)]
+fn component_enabled_by_default() -> Result<()> {
+    let path = "tests/all/cli_tests/component-basic.wat";
+    let wasm = build_wasm(path)?;
+    let output = get_wasmtime_command()?
+        .arg("-Ccache=n")
+        .arg(wasm.path())
+        .output()?;
+    assert!(output.status.success());
+
+    // also tests with raw *.wat input
+    let output = get_wasmtime_command()?
+        .arg("-Ccache=n")
+        .arg(path)
+        .output()?;
+    assert!(output.status.success());
+
+    Ok(())
+}
+
 // If the text format is invalid then the filename should be mentioned in the
 // error message.
 #[test]
diff --git a/tests/all/cli_tests/component-basic.wat b/tests/all/cli_tests/component-basic.wat
index 99600f1f0..057ee944a 100644
--- a/tests/all/cli_tests/component-basic.wat
+++ b/tests/all/cli_tests/component-basic.wat
@@ -7,6 +7,6 @@
   (func $run (result (result))
     (canon lift (core func $i "run")))
 
-  (instance (export (interface "wasi:cli/run@0.2.0-rc-2024-01-16"))
+  (instance (export (interface "wasi:cli/run@0.2.0"))
     (export "run" (func $run)))
 )