Repository: bytecodealliance/wasmtime
Pull request #7678 (2023-12-12 23:30:47)

Add release notes for Wasmtime 16
<!--
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/RELEASES.md b/RELEASES.md
index 8c60992f1..03f2b857f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -16,8 +16,69 @@ Unreleased.
 
 ### Added
 
+* Add yielding support in `wasmtime_store_epoch_deadline_callback` in the C API.
+  [#7476](https://github.com/bytecodealliance/wasmtime/pull/7476)
+
+* Support for the `wasi_unstable` module ("wasi preview0" canonically) has been
+  added to the `-Spreview2` support in the CLI.
+  [#7548](https://github.com/bytecodealliance/wasmtime/pull/7548)
+
+* The original module can now be obtained from an "instance pre" in the C API.
+  [#7572](https://github.com/bytecodealliance/wasmtime/pull/7572)
+
+* Usage of Mach ports on macOS can now be disabled in the C API.
+  [#7595](https://github.com/bytecodealliance/wasmtime/pull/7595)
+
 ### Changed
 
+* The preview1-to-preview2 component adapters now import a smaller number of
+  interfaces by default.
+  [#7543](https://github.com/bytecodealliance/wasmtime/pull/7543)
+  [#7544](https://github.com/bytecodealliance/wasmtime/pull/7544)
+
+* Wasmtime and Cranelift now require Rust 1.72.0 to build.
+  [#7554](https://github.com/bytecodealliance/wasmtime/pull/7554)
+
+* The default `world` supported by `wasmtime serve` has been slimmed down to
+  exactly what `wasi:http/proxy` specifies by default. Support for other WASI
+  APIs can be included with the `-S common` command-line flag.
+  [#7597](https://github.com/bytecodealliance/wasmtime/pull/7597)
+
+* The `wasmtime --version` CLI output will now include date/commit information
+  when Wasmtime is built from a git checkout.
+  [#7610](https://github.com/bytecodealliance/wasmtime/pull/7610)
+
+### Fixed
+
+* MPK support is now explicitly disabled on AMD-based CPUs since the
+  implementation does not currently support it.
+  [#7513](https://github.com/bytecodealliance/wasmtime/pull/7513)
+
+* Initialization of a WebAssembly data segment with a negative offset is fixed
+  to zero-extend the offset instead of sign-extend.
+  [#7559](https://github.com/bytecodealliance/wasmtime/pull/7559)
+
+* The reported offset of `O_APPEND` files in preview1 has been fixed.
+  [#7586](https://github.com/bytecodealliance/wasmtime/pull/7586)
+
+* MPK support does a better job of compacting memories to minimize virtual
+  memory used.
+  [#7622](https://github.com/bytecodealliance/wasmtime/pull/7622)
+
+### Cranelift
+
+* Union node bitpacking has been fixed with egraph optimizations to ensure the
+  minimal cost node is selected.
+  [#7465](https://github.com/bytecodealliance/wasmtime/pull/7465)
+
+* Equivalent-cost expressions now have ties broken with expression depth in
+  egraphs to prefer "shallow" expression trees.
+  [#7456](https://github.com/bytecodealliance/wasmtime/pull/7456)
+
+* Long-and-narrow chains of expressions are now optimized into shallow-and-wide
+  trees.
+  [#7466](https://github.com/bytecodealliance/wasmtime/pull/7466)
+
 --------------------------------------------------------------------------------
 
 ## 15.0.1
diff --git a/crates/wasi/src/preview2/ctx.rs b/crates/wasi/src/preview2/ctx.rs
index d3d52408d..a0447711a 100644
--- a/crates/wasi/src/preview2/ctx.rs
+++ b/crates/wasi/src/preview2/ctx.rs
@@ -1,18 +1,17 @@
-use super::clocks::host::{monotonic_clock, wall_clock};
 use crate::preview2::{
-    clocks::{self, HostMonotonicClock, HostWallClock},
+    clocks::{
+        host::{monotonic_clock, wall_clock},
+        HostMonotonicClock, HostWallClock,
+    },
     filesystem::Dir,
+    network::{SocketAddrCheck, SocketAddrUse},
     pipe, random, stdio,
     stdio::{StdinStream, StdoutStream},
     DirPerms, FilePerms,
 };
 use cap_rand::{Rng, RngCore, SeedableRng};
-use cap_std::ipnet::{self, IpNet};
-use cap_std::net::Pool;
-use cap_std::{ambient_authority, AmbientAuthority};
-use std::mem;
-use std::net::{Ipv4Addr, Ipv6Addr};
 use std::sync::Arc;
+use std::{mem, net::SocketAddr};
 use wasmtime::component::ResourceTable;
 
 pub struct WasiCtxBuilder {
@@ -22,8 +21,7 @@ pub struct WasiCtxBuilder {
     env: Vec<(String, String)>,
     args: Vec<String>,
     preopens: Vec<(Dir, String)>,
-
-    pool: Pool,
+    socket_addr_check: SocketAddrCheck,
     random: Box<dyn RngCore + Send + Sync>,
     insecure_random: Box<dyn RngCore + Send + Sync>,
     insecure_random_seed: u128,
@@ -73,7 +71,7 @@ impl WasiCtxBuilder {
             env: Vec::new(),
             args: Vec::new(),
             preopens: Vec::new(),
-            pool: Pool::new(),
+            socket_addr_check: SocketAddrCheck::default(),
             random: random::thread_rng(),
             insecure_random,
             insecure_random_seed,
@@ -173,80 +171,36 @@ impl WasiCtxBuilder {
         self.insecure_random = Box::new(insecure_random);
         self
     }
+
     pub fn insecure_random_seed(&mut self, insecure_random_seed: u128) -> &mut Self {
         self.insecure_random_seed = insecure_random_seed;
         self
     }
 
-    pub fn wall_clock(&mut self, clock: impl clocks::HostWallClock + 'static) -> &mut Self {
+    pub fn wall_clock(&mut self, clock: impl HostWallClock + 'static) -> &mut Self {
         self.wall_clock = Box::new(clock);
         self
     }
 
-    pub fn monotonic_clock(
-        &mut self,
-        clock: impl clocks::HostMonotonicClock + 'static,
-    ) -> &mut Self {
+    pub fn monotonic_clock(&mut self, clock: impl HostMonotonicClock + 'static) -> &mut Self {
         self.monotonic_clock = Box::new(clock);
         self
     }
 
-    /// Add all network addresses accessable to the host to the pool.
-    pub fn inherit_network(&mut self, ambient_authority: AmbientAuthority) -> &mut Self {
-        self.pool.insert_ip_net_port_any(
-            IpNet::new(Ipv4Addr::UNSPECIFIED.into(), 0).unwrap(),
-            ambient_authority,
-        );
-        self.pool.insert_ip_net_port_any(
-            IpNet::new(Ipv6Addr::UNSPECIFIED.into(), 0).unwrap(),
-            ambient_authority,
-        );
-        self
-    }
-
-    /// Add network addresses to the pool.
-    pub fn insert_addr<A: cap_std::net::ToSocketAddrs>(
-        &mut self,
-        addrs: A,
-    ) -> std::io::Result<&mut Self> {
-        self.pool.insert(addrs, ambient_authority())?;
-        Ok(self)
-    }
-
-    /// Add a specific [`cap_std::net::SocketAddr`] to the pool.
-    pub fn insert_socket_addr(&mut self, addr: cap_std::net::SocketAddr) -> &mut Self {
-        self.pool.insert_socket_addr(addr, ambient_authority());
-        self
-    }
-
-    /// Add a range of network addresses, accepting any port, to the pool.
-    ///
-    /// Unlike `insert_ip_net`, this function grants access to any requested port.
-    pub fn insert_ip_net_port_any(&mut self, ip_net: ipnet::IpNet) -> &mut Self {
-        self.pool
-            .insert_ip_net_port_any(ip_net, ambient_authority());
-        self
+    /// Allow all network addresses accessible to the host
+    pub fn inherit_network(&mut self) -> &mut Self {
+        self.socket_addr_check(|_, _| true)
     }
 
-    /// Add a range of network addresses, accepting a range of ports, to
-    /// per-instance networks.
+    /// A check that will be called for each socket address that is used.
     ///
-    /// This grants access to the port range starting at `ports_start` and, if
-    /// `ports_end` is provided, ending before `ports_end`.
-    pub fn insert_ip_net_port_range(
-        &mut self,
-        ip_net: ipnet::IpNet,
-        ports_start: u16,
-        ports_end: Option<u16>,
-    ) -> &mut Self {
-        self.pool
-            .insert_ip_net_port_range(ip_net, ports_start, ports_end, ambient_authority());
-        self
-    }
-
-    /// Add a range of network addresses with a specific port to the pool.
-    pub fn insert_ip_net(&mut self, ip_net: ipnet::IpNet, port: u16) -> &mut Self {
-        self.pool.insert_ip_net(ip_net, port, ambient_authority());
+    /// Returning `true` will permit socket connections to the `SocketAddr`,
+    /// while returning `false` will reject the connection.
+    pub fn socket_addr_check<F>(&mut self, check: F) -> &mut Self
+    where
+        F: Fn(&SocketAddr, SocketAddrUse) -> bool + Send + Sync + 'static,
+    {
+        self.socket_addr_check = SocketAddrCheck(Arc::new(check));
         self
     }
 
@@ -286,7 +240,7 @@ impl WasiCtxBuilder {
             env,
             args,
             preopens,
-            pool,
+            socket_addr_check,
             random,
             insecure_random,
             insecure_random_seed,
@@ -304,7 +258,7 @@ impl WasiCtxBuilder {
             env,
             args,
             preopens,
-            pool: Arc::new(pool),
+            socket_addr_check,
             random,
             insecure_random,
             insecure_random_seed,
@@ -334,7 +288,7 @@ pub struct WasiCtx {
     pub(crate) stdin: Box<dyn StdinStream>,
     pub(crate) stdout: Box<dyn StdoutStream>,
     pub(crate) stderr: Box<dyn StdoutStream>,
-    pub(crate) pool: Arc<Pool>,
+    pub(crate) socket_addr_check: SocketAddrCheck,
     pub(crate) allowed_network_uses: AllowedNetworkUses,
 }
 
@@ -360,8 +314,7 @@ impl AllowedNetworkUses {
             return Err(std::io::Error::new(
                 std::io::ErrorKind::PermissionDenied,
                 "UDP is not allowed",
-            )
-            .into());
+            ));
         }
 
         Ok(())
@@ -372,8 +325,7 @@ impl AllowedNetworkUses {
             return Err(std::io::Error::new(
                 std::io::ErrorKind::PermissionDenied,
                 "TCP is not allowed",
-            )
-            .into());
+            ));
         }
 
         Ok(())
diff --git a/crates/wasi/src/preview2/host/instance_network.rs b/crates/wasi/src/preview2/host/instance_network.rs
index 428151dcc..382bae913 100644
--- a/crates/wasi/src/preview2/host/instance_network.rs
+++ b/crates/wasi/src/preview2/host/instance_network.rs
@@ -6,7 +6,7 @@ use wasmtime::component::Resource;
 impl<T: WasiView> instance_network::Host for T {
     fn instance_network(&mut self) -> Result<Resource<Network>, anyhow::Error> {
         let network = Network {
-            pool: self.ctx().pool.clone(),
+            socket_addr_check: self.ctx().socket_addr_check.clone(),
             allow_ip_name_lookup: self.ctx().allowed_network_uses.ip_name_lookup,
         };
         let network = self.table_mut().push(network)?;
diff --git a/crates/wasi/src/preview2/host/network.rs b/crates/wasi/src/preview2/host/network.rs
index ddb4b7d63..55dedb1b1 100644
--- a/crates/wasi/src/preview2/host/network.rs
+++ b/crates/wasi/src/preview2/host/network.rs
@@ -218,7 +218,7 @@ pub(crate) mod util {
     use crate::preview2::bindings::sockets::network::ErrorCode;
     use crate::preview2::network::SocketAddressFamily;
     use crate::preview2::SocketResult;
-    use cap_net_ext::{Blocking, TcpBinder, TcpConnecter, TcpListenerExt, UdpBinder};
+    use cap_net_ext::{Blocking, TcpListenerExt};
     use cap_std::net::{TcpListener, TcpStream, UdpSocket};
     use rustix::fd::AsFd;
     use rustix::io::Errno;
@@ -302,42 +302,38 @@ pub(crate) mod util {
      * Syscalls wrappers with (opinionated) portability fixes.
      */
 
-    pub fn tcp_bind(listener: &TcpListener, binder: &TcpBinder) -> std::io::Result<()> {
-        binder
-            .bind_existing_tcp_listener(listener)
-            .map_err(|error| match Errno::from_io_error(&error) {
-                // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind#:~:text=WSAENOBUFS
-                // Windows returns WSAENOBUFS when the ephemeral ports have been exhausted.
-                #[cfg(windows)]
-                Some(Errno::NOBUFS) => Errno::ADDRINUSE.into(),
-                _ => error,
-            })
+    pub fn tcp_bind(listener: &TcpListener, addr: &SocketAddr) -> std::io::Result<()> {
+        rustix::net::bind(listener, addr).map_err(|error| match error {
+            // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind#:~:text=WSAENOBUFS
+            // Windows returns WSAENOBUFS when the ephemeral ports have been exhausted.
+            #[cfg(windows)]
+            Errno::NOBUFS => Errno::ADDRINUSE.into(),
+            _ => error.into(),
+        })
     }
 
-    pub fn udp_bind(socket: &UdpSocket, binder: &UdpBinder) -> std::io::Result<()> {
-        binder.bind_existing_udp_socket(socket).map_err(|error| {
-            match Errno::from_io_error(&error) {
+    pub fn udp_bind(socket: &UdpSocket, addr: &SocketAddr) -> std::io::Result<()> {
+        rustix::net::bind(socket, addr).map_err(|error| {
+            match error {
                 // See: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind#:~:text=WSAENOBUFS
                 // Windows returns WSAENOBUFS when the ephemeral ports have been exhausted.
                 #[cfg(windows)]
-                Some(Errno::NOBUFS) => Errno::ADDRINUSE.into(),
-                _ => error,
+                Errno::NOBUFS => Errno::ADDRINUSE.into(),
+                _ => error.into(),
             }
         })
     }
 
-    pub fn tcp_connect(listener: &TcpListener, connecter: &TcpConnecter) -> std::io::Result<()> {
-        connecter.connect_existing_tcp_listener(listener).map_err(
-            |error| match Errno::from_io_error(&error) {
-                // On POSIX, non-blocking `connect` returns `EINPROGRESS`.
-                // Windows returns `WSAEWOULDBLOCK`.
-                //
-                // This normalized error code is depended upon by: tcp.rs
-                #[cfg(windows)]
-                Some(Errno::WOULDBLOCK) => Errno::INPROGRESS.into(),
-                _ => error,
-            },
-        )
+    pub fn tcp_connect(listener: &TcpListener, addr: &SocketAddr) -> std::io::Result<()> {
+        rustix::net::connect(listener, addr).map_err(|error| match error {
+            // On POSIX, non-blocking `connect` returns `EINPROGRESS`.
+            // Windows returns `WSAEWOULDBLOCK`.
+            //
+            // This normalized error code is depended upon by: tcp.rs
+            #[cfg(windows)]
+            Errno::WOULDBLOCK => Errno::INPROGRESS.into(),
+            _ => error.into(),
+        })
     }
 
     pub fn tcp_listen(listener: &TcpListener, backlog: Option<i32>) -> std::io::Result<()> {
diff --git a/crates/wasi/src/preview2/host/tcp.rs b/crates/wasi/src/preview2/host/tcp.rs
index 436a92367..b1d4ba31f 100644
--- a/crates/wasi/src/preview2/host/tcp.rs
+++ b/crates/wasi/src/preview2/host/tcp.rs
@@ -1,4 +1,5 @@
 use crate::preview2::host::network::util;
+use crate::preview2::network::SocketAddrUse;
 use crate::preview2::tcp::{TcpSocket, TcpState};
 use crate::preview2::{
     bindings::{
@@ -9,7 +10,7 @@ use crate::preview2::{
     network::SocketAddressFamily,
 };
 use crate::preview2::{Pollable, SocketResult, WasiView};
-use cap_net_ext::{Blocking, PoolExt};
+use cap_net_ext::Blocking;
 use cap_std::net::TcpListener;
 use io_lifetimes::AsSocketlike;
 use rustix::io::Errno;
@@ -44,11 +45,12 @@ impl<T: WasiView> crate::preview2::host::tcp::tcp::HostTcpSocket for T {
         util::validate_address_family(&local_address, &socket.family)?;
 
         {
-            let binder = network.pool.tcp_binder(local_address)?;
+            // Ensure that we're allowed to connect to this address.
+            network.check_socket_addr(&local_address, SocketAddrUse::TcpBind)?;
             let listener = &*socket.tcp_socket().as_socketlike_view::<TcpListener>();
 
             // Perform the OS bind call.
-            util::tcp_bind(listener, &binder).map_err(|error| {
+            util::tcp_bind(listener, &local_address).map_err(|error| {
                 match Errno::from_io_error(&error) {
                     // From https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html:
                     // > [EAFNOSUPPORT] The specified address is not a valid address for the address family of the specified socket
@@ -112,11 +114,12 @@ impl<T: WasiView> crate::preview2::host::tcp::tcp::HostTcpSocket for T {
             util::validate_remote_address(&remote_address)?;
             util::validate_address_family(&remote_address, &socket.family)?;
 
-            let connecter = network.pool.tcp_connecter(remote_address)?;
+            // Ensure that we're allowed to connect to this address.
+            network.check_socket_addr(&remote_address, SocketAddrUse::TcpConnect)?;
             let listener = &*socket.tcp_socket().as_socketlike_view::<TcpListener>();
 
             // Do an OS `connect`. Our socket is non-blocking, so it'll either...
-            util::tcp_connect(listener, &connecter)
+            util::tcp_connect(listener, &remote_address)
         };
 
         match r {
diff --git a/crates/wasi/src/preview2/host/udp.rs b/crates/wasi/src/preview2/host/udp.rs
index cd6dd62c3..09ca8b5b9 100644
--- a/crates/wasi/src/preview2/host/udp.rs
+++ b/crates/wasi/src/preview2/host/udp.rs
@@ -1,5 +1,5 @@
 use crate::preview2::host::network::util;
-use crate::preview2::network::SocketAddressFamily;
+use crate::preview2::network::{SocketAddrUse, SocketAddressFamily};
 use crate::preview2::{
     bindings::{
         sockets::network::{ErrorCode, IpAddressFamily, IpSocketAddress, Network},
@@ -11,7 +11,6 @@ use crate::preview2::{
 use crate::preview2::{Pollable, SocketError, SocketResult, WasiView};
 use anyhow::anyhow;
 use async_trait::async_trait;
-use cap_net_ext::PoolExt;
 use io_lifetimes::AsSocketlike;
 use rustix::io::Errno;
 use rustix::net::sockopt;
@@ -42,9 +41,12 @@ impl<T: WasiView> udp::HostUdpSocket for T {
             UdpState::Bound | UdpState::Connected => return Err(ErrorCode::InvalidState.into()),
         }
 
-        // Set the pool on the socket so later functions have access to it through the socket handle
-        let pool = table.get(&network)?.pool.clone();
-        table.get_mut(&this)?.pool.replace(pool.clone());
+        // Set the socket addr check on the socket so later functions have access to it through the socket handle
+        let check = table.get(&network)?.socket_addr_check.clone();
+        table
+            .get_mut(&this)?
+            .socket_addr_check
+            .replace(check.clone());
 
         let socket = table.get(&this)?;
         let local_address: SocketAddr = local_address.into();
@@ -52,13 +54,13 @@ impl<T: WasiView> udp::HostUdpSocket for T {
         util::validate_address_family(&local_address, &socket.family)?;
 
         {
-            let binder = pool.udp_binder(local_address)?;
+            check.check(&local_address, SocketAddrUse::UdpBind)?;
             let udp_socket = &*socket
                 .udp_socket()
                 .as_socketlike_view::<cap_std::net::UdpSocket>();
 
             // Perform the OS bind call.
-            util::udp_bind(udp_socket, &binder).map_err(|error| {
+            util::udp_bind(udp_socket, &local_address).map_err(|error| {
                 match Errno::from_io_error(&error) {
                     // From https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html:
                     // > [EAFNOSUPPORT] The specified address is not a valid address for the address family of the specified socket
@@ -132,13 +134,12 @@ impl<T: WasiView> udp::HostUdpSocket for T {
 
         // Step #2: (Re)connect
         if let Some(connect_addr) = remote_address {
-            let Some(pool) = socket.pool.as_ref() else {
+            let Some(check) = socket.socket_addr_check.as_ref() else {
                 return Err(ErrorCode::InvalidState.into());
             };
             util::validate_remote_address(&connect_addr)?;
             util::validate_address_family(&connect_addr, &socket.family)?;
-            // We don't actually use the connecter, we just use it to verify that `connect_addr` is allowed
-            let _ = pool.udp_connecter(connect_addr)?;
+            check.check(&connect_addr, SocketAddrUse::UdpConnect)?;
 
             rustix::net::connect(socket.udp_socket(), &connect_addr).map_err(
                 |error| match error {
@@ -162,7 +163,7 @@ impl<T: WasiView> udp::HostUdpSocket for T {
             remote_address,
             family: socket.family,
             send_state: SendState::Idle,
-            pool: socket.pool.clone(),
+            socket_addr_check: socket.socket_addr_check.clone(),
         };
 
         Ok((
@@ -458,13 +459,10 @@ impl<T: WasiView> udp::HostOutgoingDatagramStream for T {
             let provided_addr = datagram.remote_address.map(SocketAddr::from);
             let addr = match (stream.remote_address, provided_addr) {
                 (None, Some(addr)) => {
-                    let Some(pool) = stream.pool.as_ref() else {
+                    let Some(check) = stream.socket_addr_check.as_ref() else {
                         return Err(ErrorCode::InvalidState.into());
                     };
-                    // We don't actually use the connecter, we just use it to verify that `addr`
-                    // is allowed. We only need to check the provided addr as the stream's remote
-                    // address was checked when the stream was created.
-                    let _ = pool.udp_connecter(addr)?;
+                    check.check(&addr, SocketAddrUse::UdpOutgoingDatagram)?;
                     addr
                 }
                 (Some(addr), None) => addr,
diff --git a/crates/wasi/src/preview2/network.rs b/crates/wasi/src/preview2/network.rs
index 6384b1803..0cd86cba8 100644
--- a/crates/wasi/src/preview2/network.rs
+++ b/crates/wasi/src/preview2/network.rs
@@ -1,14 +1,64 @@
 use crate::preview2::bindings::sockets::network::{Ipv4Address, Ipv6Address};
 use crate::preview2::bindings::wasi::sockets::network::ErrorCode;
 use crate::preview2::TrappableError;
-use cap_std::net::Pool;
+use std::net::SocketAddr;
 use std::sync::Arc;
 
 pub struct Network {
-    pub pool: Arc<Pool>,
+    pub socket_addr_check: SocketAddrCheck,
     pub allow_ip_name_lookup: bool,
 }
 
+impl Network {
+    pub fn check_socket_addr(
+        &self,
+        addr: &SocketAddr,
+        reason: SocketAddrUse,
+    ) -> std::io::Result<()> {
+        self.socket_addr_check.check(addr, reason)
+    }
+}
+
+/// A check that will be called for each socket address that is used of whether the address is permitted.
+#[derive(Clone)]
+pub struct SocketAddrCheck(
+    pub(crate) Arc<dyn Fn(&SocketAddr, SocketAddrUse) -> bool + Send + Sync>,
+);
+
+impl SocketAddrCheck {
+    pub fn check(&self, addr: &SocketAddr, reason: SocketAddrUse) -> std::io::Result<()> {
+        if (self.0)(addr, reason) {
+            Ok(())
+        } else {
+            Err(std::io::Error::new(
+                std::io::ErrorKind::PermissionDenied,
+                "An address was not permitted by the socket address check.",
+            ))
+        }
+    }
+}
+
+impl Default for SocketAddrCheck {
+    fn default() -> Self {
+        Self(Arc::new(|_, _| false))
+    }
+}
+
+/// The reason what a socket address is being used for.
+#[derive(Clone, Copy, Debug)]
+pub enum SocketAddrUse {
+    /// Binding TCP socket
+    TcpBind,
+    /// Connecting TCP socket
+    TcpConnect,
+    /// Binding UDP socket
+    UdpBind,
+    /// Connecting UDP socket
+    UdpConnect,
+    /// Sending datagram on non-connected UDP socket
+    UdpOutgoingDatagram,
+}
+
 pub type SocketResult<T> = Result<T, SocketError>;
 
 pub type SocketError = TrappableError<ErrorCode>;
diff --git a/crates/wasi/src/preview2/udp.rs b/crates/wasi/src/preview2/udp.rs
index 13194c1f5..70e35ba44 100644
--- a/crates/wasi/src/preview2/udp.rs
+++ b/crates/wasi/src/preview2/udp.rs
@@ -2,13 +2,12 @@ use crate::preview2::poll::Subscribe;
 use crate::preview2::with_ambient_tokio_runtime;
 use async_trait::async_trait;
 use cap_net_ext::{AddressFamily, Blocking, UdpSocketExt};
-use cap_std::net::Pool;
 use io_lifetimes::raw::{FromRawSocketlike, IntoRawSocketlike};
 use std::io;
 use std::net::SocketAddr;
 use std::sync::Arc;
 
-use super::network::SocketAddressFamily;
+use super::network::{SocketAddrCheck, SocketAddressFamily};
 
 /// The state of a UDP socket.
 ///
@@ -44,8 +43,8 @@ pub struct UdpSocket {
     /// Socket address family.
     pub(crate) family: SocketAddressFamily,
 
-    /// The pool of allowed addresses
-    pub(crate) pool: Option<Arc<Pool>>,
+    /// The check of allowed addresses
+    pub(crate) socket_addr_check: Option<SocketAddrCheck>,
 }
 
 #[async_trait]
@@ -71,7 +70,7 @@ impl UdpSocket {
             inner: Arc::new(socket),
             udp_state: UdpState::Default,
             family: socket_address_family,
-            pool: None,
+            socket_addr_check: None,
         })
     }
 
@@ -110,8 +109,8 @@ pub struct OutgoingDatagramStream {
 
     pub(crate) send_state: SendState,
 
-    /// The pool of allowed addresses
-    pub(crate) pool: Option<Arc<Pool>>,
+    /// The check of allowed addresses
+    pub(crate) socket_addr_check: Option<SocketAddrCheck>,
 }
 
 pub(crate) enum SendState {
diff --git a/crates/wasmtime/src/component/linker.rs b/crates/wasmtime/src/component/linker.rs
index 5e490fa9a..58e660044 100644
--- a/crates/wasmtime/src/component/linker.rs
+++ b/crates/wasmtime/src/component/linker.rs
@@ -417,12 +417,9 @@ impl<T> LinkerInstance<'_, T> {
         self.insert(name, Definition::Module(module.clone()))
     }
 
-    /// Defines a new host [`ResourceType`] in this linker.
+    /// Defines a new resource of a given [`ResourceType`] in this linker.
     ///
-    /// This function is used to specify resources defined in the host. The `U`
-    /// type parameter here is the type parameter to [`Resource<U>`]. This means
-    /// that component types using this resource type will be visible in
-    /// Wasmtime as [`Resource<U>`].
+    /// This function is used to specify resources defined in the host.
     ///
     /// The `name` argument is the name to define the resource within this
     /// linker.
@@ -442,9 +439,10 @@ impl<T> LinkerInstance<'_, T> {
     /// The provided `dtor` closure returns an error if something goes wrong
     /// when a guest calls the `dtor` to drop a `Resource<T>` such as
     /// a runtime trap or a runtime limit being exceeded.
-    pub fn resource<U: 'static>(
+    pub fn resource(
         &mut self,
         name: &str,
+        ty: ResourceType,
         dtor: impl Fn(StoreContextMut<'_, T>, u32) -> Result<()> + Send + Sync + 'static,
     ) -> Result<()> {
         let name = self.strings.intern(name);
@@ -452,7 +450,7 @@ impl<T> LinkerInstance<'_, T> {
             &self.engine,
             move |mut cx: crate::Caller<'_, T>, param: u32| dtor(cx.as_context_mut(), param),
         ));
-        self.insert(name, Definition::Resource(ResourceType::host::<U>(), dtor))
+        self.insert(name, Definition::Resource(ty, dtor))
     }
 
     /// Defines a nested instance within this instance.
diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs
index 2c1422f59..a73f6bcca 100644
--- a/crates/wit-bindgen/src/lib.rs
+++ b/crates/wit-bindgen/src/lib.rs
@@ -807,8 +807,9 @@ impl Wasmtime {
             let camel = name.to_upper_camel_case();
             uwriteln!(
                 self.src,
-                "linker.resource::<{camel}>(
+                "linker.resource(
                     \"{name}\",
+                    wasmtime::component::ResourceType::host::<{camel}>(),
                     move |mut store, rep| -> wasmtime::Result<()> {{
                         Host{camel}::drop(get(store.data_mut()), wasmtime::component::Resource::new_own(rep))
                     }},
@@ -1604,8 +1605,9 @@ impl<'a> InterfaceGenerator<'a> {
             let camel = name.to_upper_camel_case();
             uwriteln!(
                 self.src,
-                "inst.resource::<{camel}>(
+                "inst.resource(
                     \"{name}\",
+                    wasmtime::component::ResourceType::host::<{camel}>(),
                     move |mut store, rep| -> wasmtime::Result<()> {{
                         Host{camel}::drop(get(store.data_mut()), wasmtime::component::Resource::new_own(rep))
                     }},
diff --git a/src/commands/run.rs b/src/commands/run.rs
index 964a50bde..81c724bd7 100644
--- a/src/commands/run.rs
+++ b/src/commands/run.rs
@@ -772,7 +772,7 @@ impl RunCommand {
         }
 
         if self.run.common.wasi.inherit_network == Some(true) {
-            builder.inherit_network(ambient_authority());
+            builder.inherit_network();
         }
         if let Some(enable) = self.run.common.wasi.allow_ip_name_lookup {
             builder.allow_ip_name_lookup(enable);
diff --git a/winch/codegen/src/codegen/context.rs b/winch/codegen/src/codegen/context.rs
index 28b4a25da..7bcedf089 100644
--- a/winch/codegen/src/codegen/context.rs
+++ b/winch/codegen/src/codegen/context.rs
@@ -225,25 +225,29 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> {
     }
 
     /// Prepares arguments for emitting a unary operation.
+    ///
+    /// The `emit` function returns the `TypedReg` to put on the value stack.
     pub fn unop<F, M>(&mut self, masm: &mut M, size: OperandSize, emit: &mut F)
     where
-        F: FnMut(&mut M, Reg, OperandSize),
+        F: FnMut(&mut M, Reg, OperandSize) -> TypedReg,
         M: MacroAssembler,
     {
         let typed_reg = self.pop_to_reg(masm, None);
-        emit(masm, typed_reg.reg, size);
-        self.stack.push(typed_reg.into());
+        let dst = emit(masm, typed_reg.reg, size);
+        self.stack.push(dst.into());
     }
 
     /// Prepares arguments for emitting a binary operation.
+    ///
+    /// The `emit` function returns the `TypedReg` to put on the value stack.
     pub fn binop<F, M>(&mut self, masm: &mut M, size: OperandSize, mut emit: F)
     where
-        F: FnMut(&mut M, Reg, Reg, OperandSize),
+        F: FnMut(&mut M, Reg, Reg, OperandSize) -> TypedReg,
         M: MacroAssembler,
     {
         let src = self.pop_to_reg(masm, None);
         let dst = self.pop_to_reg(masm, None);
-        emit(masm, dst.reg, src.reg.into(), size);
+        let dst = emit(masm, dst.reg, src.reg.into(), size);
         self.free_reg(src);
         self.stack.push(dst.into());
     }
@@ -270,9 +274,11 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> {
     }
 
     /// Prepares arguments for emitting an i32 binary operation.
+    ///
+    /// The `emit` function returns the `TypedReg` to put on the value stack.
     pub fn i32_binop<F, M>(&mut self, masm: &mut M, mut emit: F)
     where
-        F: FnMut(&mut M, Reg, RegImm, OperandSize),
+        F: FnMut(&mut M, Reg, RegImm, OperandSize) -> TypedReg,
         M: MacroAssembler,
     {
         let top = self.stack.peek().expect("value at stack top");
@@ -283,8 +289,8 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> {
                 .pop_i32_const()
                 .expect("i32 const value at stack top");
             let typed_reg = self.pop_to_reg(masm, None);
-            emit(masm, typed_reg.reg, RegImm::i32(val), OperandSize::S32);
-            self.stack.push(typed_reg.into());
+            let dst = emit(masm, typed_reg.reg, RegImm::i32(val), OperandSize::S32);
+            self.stack.push(dst.into());
         } else {
             self.binop(masm, OperandSize::S32, |masm, dst, src, size| {
                 emit(masm, dst, src.into(), size)
@@ -293,9 +299,11 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> {
     }
 
     /// Prepares arguments for emitting an i64 binary operation.
+    ///
+    /// The `emit` function returns the `TypedReg` to put on the value stack.
     pub fn i64_binop<F, M>(&mut self, masm: &mut M, mut emit: F)
     where
-        F: FnMut(&mut M, Reg, RegImm, OperandSize),
+        F: FnMut(&mut M, Reg, RegImm, OperandSize) -> TypedReg,
         M: MacroAssembler,
     {
         let top = self.stack.peek().expect("value at stack top");
@@ -305,13 +313,13 @@ impl<'a, 'builtins> CodeGenContext<'a, 'builtins> {
                 .pop_i64_const()
                 .expect("i64 const value at stack top");
             let typed_reg = self.pop_to_reg(masm, None);
-            emit(masm, typed_reg.reg, RegImm::i64(val), OperandSize::S64);
-            self.stack.push(typed_reg.into());
+            let dst = emit(masm, typed_reg.reg, RegImm::i64(val), OperandSize::S64);
+            self.stack.push(dst.into());
         } else {
             self.binop(masm, OperandSize::S64, |masm, dst, src, size| {
                 emit(masm, dst, src.into(), size)
             });
-        }
+        };
     }
 
     /// Drops the last `n` elements of the stack, calling the provided
diff --git a/winch/codegen/src/stack.rs b/winch/codegen/src/stack.rs
index ffdfac397..a8491882b 100644
--- a/winch/codegen/src/stack.rs
+++ b/winch/codegen/src/stack.rs
@@ -34,6 +34,22 @@ impl TypedReg {
             reg,
         }
     }
+
+    /// Create an f64 [`TypedReg`].
+    pub fn f64(reg: Reg) -> Self {
+        Self {
+            ty: WasmType::F64,
+            reg,
+        }
+    }
+
+    /// Create an f32 [`TypedReg`].
+    pub fn f32(reg: Reg) -> Self {
+        Self {
+            ty: WasmType::F32,
+            reg,
+        }
+    }
 }
 
 impl From<TypedReg> for Reg {
diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs
index 4db1150e2..ca74d0ffc 100644
--- a/winch/codegen/src/visitor.rs
+++ b/winch/codegen/src/visitor.rs
@@ -203,6 +203,7 @@ where
             OperandSize::S32,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_add(dst, dst, src, size);
+                TypedReg::f32(dst)
             },
         );
     }
@@ -213,6 +214,7 @@ where
             OperandSize::S64,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_add(dst, dst, src, size);
+                TypedReg::f64(dst)
             },
         );
     }
@@ -223,6 +225,7 @@ where
             OperandSize::S32,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_sub(dst, dst, src, size);
+                TypedReg::f32(dst)
             },
         );
     }
@@ -233,6 +236,7 @@ where
             OperandSize::S64,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_sub(dst, dst, src, size);
+                TypedReg::f64(dst)
             },
         );
     }
@@ -243,6 +247,7 @@ where
             OperandSize::S32,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_mul(dst, dst, src, size);
+                TypedReg::f32(dst)
             },
         );
     }
@@ -253,6 +258,7 @@ where
             OperandSize::S64,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_mul(dst, dst, src, size);
+                TypedReg::f64(dst)
             },
         );
     }
@@ -263,6 +269,7 @@ where
             OperandSize::S32,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_div(dst, dst, src, size);
+                TypedReg::f32(dst)
             },
         );
     }
@@ -273,6 +280,7 @@ where
             OperandSize::S64,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_div(dst, dst, src, size);
+                TypedReg::f64(dst)
             },
         );
     }
@@ -283,6 +291,7 @@ where
             OperandSize::S32,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_min(dst, dst, src, size);
+                TypedReg::f32(dst)
             },
         );
     }
@@ -293,6 +302,7 @@ where
             OperandSize::S64,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_min(dst, dst, src, size);
+                TypedReg::f64(dst)
             },
         );
     }
@@ -303,6 +313,7 @@ where
             OperandSize::S32,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_max(dst, dst, src, size);
+                TypedReg::f32(dst)
             },
         );
     }
@@ -313,6 +324,7 @@ where
             OperandSize::S64,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_max(dst, dst, src, size);
+                TypedReg::f64(dst)
             },
         );
     }
@@ -323,6 +335,7 @@ where
             OperandSize::S32,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_copysign(dst, dst, src, size);
+                TypedReg::f32(dst)
             },
         );
     }
@@ -333,6 +346,7 @@ where
             OperandSize::S64,
             &mut |masm: &mut M, dst, src, size| {
                 masm.float_copysign(dst, dst, src, size);
+                TypedReg::f64(dst)
             },
         );
     }
@@ -341,6 +355,7 @@ where
         self.context
             .unop(self.masm, OperandSize::S32, &mut |masm, reg, size| {
                 masm.float_abs(reg, size);
+                TypedReg::f32(reg)
             });
     }
 
@@ -348,6 +363,7 @@ where
         self.context
             .unop(self.masm, OperandSize::S64, &mut |masm, reg, size| {
                 masm.float_abs(reg, size);
+                TypedReg::f64(reg)
             });
     }
 
@@ -355,6 +371,7 @@ where
         self.context
             .unop(self.masm, OperandSize::S32, &mut |masm, reg, size| {
                 masm.float_neg(reg, size);
+                TypedReg::f32(reg)
             });
     }
 
@@ -362,6 +379,7 @@ where
         self.context
             .unop(self.masm, OperandSize::S64, &mut |masm, reg, size| {
                 masm.float_neg(reg, size);
+                TypedReg::f64(reg)
             });
     }
 
@@ -409,6 +427,7 @@ where
         self.context
             .unop(self.masm, OperandSize::S32, &mut |masm, reg, size| {
                 masm.float_sqrt(reg, reg, size);
+                TypedReg::f32(reg)
             });
     }
 
@@ -416,6 +435,7 @@ where
         self.context
             .unop(self.masm, OperandSize::S64, &mut |masm, reg, size| {
                 masm.float_sqrt(reg, reg, size);
+                TypedReg::f64(reg)
             });
     }
 
@@ -542,36 +562,42 @@ where
     fn visit_i32_add(&mut self) {
         self.context.i32_binop(self.masm, |masm, dst, src, size| {
             masm.add(dst, dst, src, size);
+            TypedReg::i32(dst)
         });
     }
 
     fn visit_i64_add(&mut self) {
         self.context.i64_binop(self.masm, |masm, dst, src, size| {
             masm.add(dst, dst, src, size);
+            TypedReg::i64(dst)
         });
     }
 
     fn visit_i32_sub(&mut self) {
         self.context.i32_binop(self.masm, |masm, dst, src, size| {
             masm.sub(dst, dst, src, size);
+            TypedReg::i32(dst)
         });
     }
 
     fn visit_i64_sub(&mut self) {
         self.context.i64_binop(self.masm, |masm, dst, src, size| {
             masm.sub(dst, dst, src, size);
+            TypedReg::i64(dst)
         });
     }
 
     fn visit_i32_mul(&mut self) {
         self.context.i32_binop(self.masm, |masm, dst, src, size| {
             masm.mul(dst, dst, src, size);
+            TypedReg::i32(dst)
         });
     }
 
     fn visit_i64_mul(&mut self) {
         self.context.i64_binop(self.masm, |masm, dst, src, size| {
             masm.mul(dst, dst, src, size);
+            TypedReg::i64(dst)
         });
     }
 
@@ -716,6 +742,7 @@ where
 
         self.context.unop(self.masm, S32, &mut |masm, reg, size| {
             masm.cmp_with_set(RegImm::i32(0), reg.into(), IntCmpKind::Eq, size);
+            TypedReg::i32(reg)
         });
     }
 
@@ -724,6 +751,7 @@ where
 
         self.context.unop(self.masm, S64, &mut |masm, reg, size| {
             masm.cmp_with_set(RegImm::i64(0), reg.into(), IntCmpKind::Eq, size);
+            TypedReg::i32(reg) // Return value for `i64.eqz` is an `i32`.
         });
     }
 
@@ -732,6 +760,7 @@ where
 
         self.context.unop(self.masm, S32, &mut |masm, reg, size| {
             masm.clz(reg, reg, size);
+            TypedReg::i32(reg)
         });
     }
 
@@ -740,6 +769,7 @@ where
 
         self.context.unop(self.masm, S64, &mut |masm, reg, size| {
             masm.clz(reg, reg, size);
+            TypedReg::i64(reg)
         });
     }
 
@@ -748,6 +778,7 @@ where
 
         self.context.unop(self.masm, S32, &mut |masm, reg, size| {
             masm.ctz(reg, reg, size);
+            TypedReg::i32(reg)
         });
     }
 
@@ -756,42 +787,49 @@ where
 
         self.context.unop(self.masm, S64, &mut |masm, reg, size| {
             masm.ctz(reg, reg, size);
+            TypedReg::i64(reg)
         });
     }
 
     fn visit_i32_and(&mut self) {
         self.context.i32_binop(self.masm, |masm, dst, src, size| {
             masm.and(dst, dst, src, size);
+            TypedReg::i32(dst)
         });
     }
 
     fn visit_i64_and(&mut self) {
         self.context.i64_binop(self.masm, |masm, dst, src, size| {
             masm.and(dst, dst, src, size);
+            TypedReg::i64(dst)
         });
     }
 
     fn visit_i32_or(&mut self) {
         self.context.i32_binop(self.masm, |masm, dst, src, size| {
             masm.or(dst, dst, src, size);
+            TypedReg::i32(dst)
         });
     }
 
     fn visit_i64_or(&mut self) {
         self.context.i64_binop(self.masm, |masm, dst, src, size| {
             masm.or(dst, dst, src, size);
+            TypedReg::i64(dst)
         });
     }
 
     fn visit_i32_xor(&mut self) {
         self.context.i32_binop(self.masm, |masm, dst, src, size| {
             masm.xor(dst, dst, src, size);
+            TypedReg::i32(dst)
         });
     }
 
     fn visit_i64_xor(&mut self) {
         self.context.i64_binop(self.masm, |masm, dst, src, size| {
             masm.xor(dst, dst, src, size);
+            TypedReg::i64(dst)
         });
     }
 
@@ -1368,6 +1406,7 @@ where
     fn cmp_i32s(&mut self, kind: IntCmpKind) {
         self.context.i32_binop(self.masm, |masm, dst, src, size| {
             masm.cmp_with_set(src, dst, kind, size);
+            TypedReg::i32(dst)
         });
     }
 
@@ -1375,6 +1414,7 @@ where
         self.context
             .i64_binop(self.masm, move |masm, dst, src, size| {
                 masm.cmp_with_set(src, dst, kind, size);
+                TypedReg::i32(dst) // Return value for comparisons is an `i32`.
             });
     }
 }


Test patch:
diff --git a/crates/wasi/tests/all/main.rs b/crates/wasi/tests/all/main.rs
index 03cf8031b..eaf9a766e 100644
--- a/crates/wasi/tests/all/main.rs
+++ b/crates/wasi/tests/all/main.rs
@@ -1,5 +1,4 @@
 use anyhow::Result;
-use cap_std::ambient_authority;
 use tempfile::TempDir;
 use wasmtime::{
     component::{Component, Linker, ResourceTable},
@@ -64,7 +63,7 @@ fn store(engine: &Engine, name: &str, inherit_stdio: bool) -> Result<(Store<Ctx>
 
     builder
         .args(&[name, "."])
-        .inherit_network(ambient_authority())
+        .inherit_network()
         .allow_ip_name_lookup(true);
     println!("preopen: {:?}", workspace);
     let preopen_dir =
diff --git a/crates/wast/src/spectest.rs b/crates/wast/src/spectest.rs
index 17d49b7c2..5f00ba73a 100644
--- a/crates/wast/src/spectest.rs
+++ b/crates/wast/src/spectest.rs
@@ -59,7 +59,7 @@ pub fn link_spectest<T>(
 pub fn link_component_spectest<T>(linker: &mut component::Linker<T>) -> Result<()> {
     use std::sync::atomic::{AtomicU32, Ordering::SeqCst};
     use std::sync::Arc;
-    use wasmtime::component::Resource;
+    use wasmtime::component::{Resource, ResourceType};
 
     let engine = linker.engine().clone();
     linker
@@ -92,7 +92,7 @@ pub fn link_component_spectest<T>(linker: &mut component::Linker<T>) -> Result<(
 
     let state = Arc::new(ResourceState::default());
 
-    i.resource::<Resource1>("resource1", {
+    i.resource("resource1", ResourceType::host::<Resource1>(), {
         let state = state.clone();
         move |_, rep| {
             state.drops.fetch_add(1, SeqCst);
@@ -101,13 +101,21 @@ pub fn link_component_spectest<T>(linker: &mut component::Linker<T>) -> Result<(
             Ok(())
         }
     })?;
-    i.resource::<Resource2>("resource2", |_, _| Ok(()))?;
+    i.resource(
+        "resource2",
+        ResourceType::host::<Resource2>(),
+        |_, _| Ok(()),
+    )?;
     // Currently the embedder API requires redefining the resource destructor
     // here despite this being the same type as before, and fixing that is left
     // for a future refactoring.
-    i.resource::<Resource1>("resource1-again", |_, _| {
-        panic!("shouldn't be destroyed");
-    })?;
+    i.resource(
+        "resource1-again",
+        ResourceType::host::<Resource1>(),
+        |_, _| {
+            panic!("shouldn't be destroyed");
+        },
+    )?;
 
     i.func_wrap("[constructor]resource1", |_cx, (rep,): (u32,)| {
         Ok((Resource::<Resource1>::new_own(rep),))
diff --git a/tests/all/component_model/resources.rs b/tests/all/component_model/resources.rs
index ba821251f..ae3893b12 100644
--- a/tests/all/component_model/resources.rs
+++ b/tests/all/component_model/resources.rs
@@ -37,8 +37,12 @@ fn host_resource_types() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<T>("t", |_, _| Ok(()))?;
-    linker.root().resource::<U>("u", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<T>(), |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("u", ResourceType::host::<U>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
     let t1 = i.get_resource(&mut store, "t1").unwrap();
     let t2 = i.get_resource(&mut store, "t2").unwrap();
@@ -367,7 +371,9 @@ fn drop_host_twice() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
     let dtor = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "dtor")?;
 
@@ -431,12 +437,14 @@ fn manually_destroy() -> Result<()> {
 
     let mut store = Store::new(&engine, Data::default());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t1", |mut cx, rep| {
-        let data: &mut Data = cx.data_mut();
-        data.drops += 1;
-        data.last_drop = Some(rep);
-        Ok(())
-    })?;
+    linker
+        .root()
+        .resource("t1", ResourceType::host::<MyType>(), |mut cx, rep| {
+            let data: &mut Data = cx.data_mut();
+            data.drops += 1;
+            data.last_drop = Some(rep);
+            Ok(())
+        })?;
     let i = linker.instantiate(&mut store, &c)?;
     let t2_ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "[constructor]t2")?;
     let t2_drops = i.get_typed_func::<(), (u32,)>(&mut store, "[static]t2.drops")?;
@@ -497,7 +505,9 @@ fn dynamic_type() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t1", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t1", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
 
     let a = i.get_func(&mut store, "a").unwrap();
@@ -548,7 +558,9 @@ fn dynamic_val() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t1", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t1", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
 
     let a = i.get_func(&mut store, "a").unwrap();
@@ -665,7 +677,9 @@ fn active_borrows_at_end_of_call() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
 
     let f = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f")?;
@@ -720,7 +734,9 @@ fn thread_through_borrow() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     linker
         .root()
         .func_wrap("f", |_cx, (r,): (Resource<MyType>,)| {
@@ -764,7 +780,9 @@ fn cannot_use_borrow_for_own() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
 
     let f = i.get_typed_func::<(&Resource<MyType>,), (Resource<MyType>,)>(&mut store, "f")?;
@@ -809,7 +827,9 @@ fn passthrough_wrong_type() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     linker
         .root()
         .func_wrap("f", |_cx, (r,): (Resource<MyType>,)| Ok((r,)))?;
@@ -849,7 +869,9 @@ fn pass_moved_resource() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
 
     let f = i.get_typed_func::<(&Resource<MyType>, &Resource<MyType>), ()>(&mut store, "f")?;
@@ -980,7 +1002,9 @@ fn host_borrow_as_resource_any() -> Result<()> {
     // First test the above component where the host properly drops the argument
     {
         let mut linker = Linker::new(&engine);
-        linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+        linker
+            .root()
+            .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
         linker
             .root()
             .func_wrap("f", |mut cx, (r,): (ResourceAny,)| {
@@ -998,7 +1022,9 @@ fn host_borrow_as_resource_any() -> Result<()> {
     // Then also test the case where the host forgets a drop
     {
         let mut linker = Linker::new(&engine);
-        linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+        linker
+            .root()
+            .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
         linker.root().func_wrap("f", |_cx, (_r,): (ResourceAny,)| {
             // ... no drop here
             Ok(())
@@ -1107,7 +1133,9 @@ fn pass_host_borrow_to_guest() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     let i = linker.instantiate(&mut store, &c)?;
     let take = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "take")?;
 
@@ -1180,7 +1208,9 @@ fn drop_on_owned_resource() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     linker.root().func_wrap("[constructor]t", |_cx, ()| {
         Ok((Resource::<MyType>::new_own(300),))
     })?;
@@ -1257,8 +1287,12 @@ fn guest_different_host_same() -> Result<()> {
 
     let mut store = Store::new(&engine, ());
     let mut linker = Linker::new(&engine);
-    linker.root().resource::<MyType>("t1", |_, _| Ok(()))?;
-    linker.root().resource::<MyType>("t2", |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t1", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
+    linker
+        .root()
+        .resource("t2", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
     linker.root().func_wrap(
         "f",
         |_cx, (r1, r2): (Resource<MyType>, Resource<MyType>)| {
diff --git a/winch/filetests/filetests/x64/i64_eq/locals.wat b/winch/filetests/filetests/x64/i64_eq/locals.wat
index 8884b9d68..6761c2e7f 100644
--- a/winch/filetests/filetests/x64/i64_eq/locals.wat
+++ b/winch/filetests/filetests/x64/i64_eq/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f94c1             	sete	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_eq/params.wat b/winch/filetests/filetests/x64/i64_eq/params.wat
index aed5174e3..27fa74cb6 100644
--- a/winch/filetests/filetests/x64/i64_eq/params.wat
+++ b/winch/filetests/filetests/x64/i64_eq/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f94c1             	sete	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_eqz/spilled.wat b/winch/filetests/filetests/x64/i64_eqz/spilled.wat
new file mode 100644
index 000000000..b2e09645c
--- /dev/null
+++ b/winch/filetests/filetests/x64/i64_eqz/spilled.wat
@@ -0,0 +1,25 @@
+;;! target = "x86_64"
+
+(module
+    (func (result i32)
+        i64.const 1
+        i64.eqz
+        block
+        end
+    )
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec08             	sub	rsp, 8
+;;    8:	 4c893424             	mov	qword ptr [rsp], r14
+;;    c:	 48c7c001000000       	mov	rax, 1
+;;   13:	 4883f800             	cmp	rax, 0
+;;   17:	 b800000000           	mov	eax, 0
+;;   1c:	 400f94c0             	sete	al
+;;   20:	 4883ec04             	sub	rsp, 4
+;;   24:	 890424               	mov	dword ptr [rsp], eax
+;;   27:	 8b0424               	mov	eax, dword ptr [rsp]
+;;   2a:	 4883c404             	add	rsp, 4
+;;   2e:	 4883c408             	add	rsp, 8
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_ge_s/locals.wat b/winch/filetests/filetests/x64/i64_ge_s/locals.wat
index 6339d2f23..6f91547cc 100644
--- a/winch/filetests/filetests/x64/i64_ge_s/locals.wat
+++ b/winch/filetests/filetests/x64/i64_ge_s/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f9dc1             	setge	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_ge_s/params.wat b/winch/filetests/filetests/x64/i64_ge_s/params.wat
index 49a3ab656..f8b849b82 100644
--- a/winch/filetests/filetests/x64/i64_ge_s/params.wat
+++ b/winch/filetests/filetests/x64/i64_ge_s/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f9dc1             	setge	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_ge_u/locals.wat b/winch/filetests/filetests/x64/i64_ge_u/locals.wat
index f8b2d35f9..626a483d2 100644
--- a/winch/filetests/filetests/x64/i64_ge_u/locals.wat
+++ b/winch/filetests/filetests/x64/i64_ge_u/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f93c1             	setae	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_ge_u/params.wat b/winch/filetests/filetests/x64/i64_ge_u/params.wat
index 2ca43e57e..68d707d11 100644
--- a/winch/filetests/filetests/x64/i64_ge_u/params.wat
+++ b/winch/filetests/filetests/x64/i64_ge_u/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f93c1             	setae	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_gt_s/locals.wat b/winch/filetests/filetests/x64/i64_gt_s/locals.wat
index 10c5c4ec3..a8e347eb4 100644
--- a/winch/filetests/filetests/x64/i64_gt_s/locals.wat
+++ b/winch/filetests/filetests/x64/i64_gt_s/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f9fc1             	setg	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_gt_s/params.wat b/winch/filetests/filetests/x64/i64_gt_s/params.wat
index 5e30853e0..ee6fc2953 100644
--- a/winch/filetests/filetests/x64/i64_gt_s/params.wat
+++ b/winch/filetests/filetests/x64/i64_gt_s/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f9fc1             	setg	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_gt_u/locals.wat b/winch/filetests/filetests/x64/i64_gt_u/locals.wat
index 9890d2ca6..203adfe7a 100644
--- a/winch/filetests/filetests/x64/i64_gt_u/locals.wat
+++ b/winch/filetests/filetests/x64/i64_gt_u/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f97c1             	seta	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_gt_u/params.wat b/winch/filetests/filetests/x64/i64_gt_u/params.wat
index e2e9d8654..d2d5e9171 100644
--- a/winch/filetests/filetests/x64/i64_gt_u/params.wat
+++ b/winch/filetests/filetests/x64/i64_gt_u/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f97c1             	seta	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_le_s/locals.wat b/winch/filetests/filetests/x64/i64_le_s/locals.wat
index d363621c3..479cab461 100644
--- a/winch/filetests/filetests/x64/i64_le_s/locals.wat
+++ b/winch/filetests/filetests/x64/i64_le_s/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f9ec1             	setle	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_le_s/params.wat b/winch/filetests/filetests/x64/i64_le_s/params.wat
index 1df814ef2..94ec67536 100644
--- a/winch/filetests/filetests/x64/i64_le_s/params.wat
+++ b/winch/filetests/filetests/x64/i64_le_s/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f9ec1             	setle	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_le_u/locals.wat b/winch/filetests/filetests/x64/i64_le_u/locals.wat
index 85eddc583..fcdcde159 100644
--- a/winch/filetests/filetests/x64/i64_le_u/locals.wat
+++ b/winch/filetests/filetests/x64/i64_le_u/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f96c1             	setbe	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_le_u/params.wat b/winch/filetests/filetests/x64/i64_le_u/params.wat
index 113b16ffa..11dd179ef 100644
--- a/winch/filetests/filetests/x64/i64_le_u/params.wat
+++ b/winch/filetests/filetests/x64/i64_le_u/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f96c1             	setbe	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_lt_s/locals.wat b/winch/filetests/filetests/x64/i64_lt_s/locals.wat
index 0a10518f5..a22f1ff70 100644
--- a/winch/filetests/filetests/x64/i64_lt_s/locals.wat
+++ b/winch/filetests/filetests/x64/i64_lt_s/locals.wat
@@ -32,7 +32,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f9cc1             	setl	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_lt_s/params.wat b/winch/filetests/filetests/x64/i64_lt_s/params.wat
index daafe27aa..2de32038d 100644
--- a/winch/filetests/filetests/x64/i64_lt_s/params.wat
+++ b/winch/filetests/filetests/x64/i64_lt_s/params.wat
@@ -19,7 +19,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f9cc1             	setl	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_lt_u/locals.wat b/winch/filetests/filetests/x64/i64_lt_u/locals.wat
index eb5197430..cd62dc77d 100644
--- a/winch/filetests/filetests/x64/i64_lt_u/locals.wat
+++ b/winch/filetests/filetests/x64/i64_lt_u/locals.wat
@@ -31,7 +31,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f92c1             	setb	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_lt_u/params.wat b/winch/filetests/filetests/x64/i64_lt_u/params.wat
index c0697c661..a24abe412 100644
--- a/winch/filetests/filetests/x64/i64_lt_u/params.wat
+++ b/winch/filetests/filetests/x64/i64_lt_u/params.wat
@@ -18,7 +18,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f92c1             	setb	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_ne/locals.wat b/winch/filetests/filetests/x64/i64_ne/locals.wat
index 49090a56e..23655ea63 100644
--- a/winch/filetests/filetests/x64/i64_ne/locals.wat
+++ b/winch/filetests/filetests/x64/i64_ne/locals.wat
@@ -32,7 +32,7 @@
 ;;   3b:	 4839c1               	cmp	rcx, rax
 ;;   3e:	 b900000000           	mov	ecx, 0
 ;;   43:	 400f95c1             	setne	cl
-;;   47:	 4889c8               	mov	rax, rcx
-;;   4a:	 4883c418             	add	rsp, 0x18
-;;   4e:	 5d                   	pop	rbp
-;;   4f:	 c3                   	ret	
+;;   47:	 89c8                 	mov	eax, ecx
+;;   49:	 4883c418             	add	rsp, 0x18
+;;   4d:	 5d                   	pop	rbp
+;;   4e:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/i64_ne/params.wat b/winch/filetests/filetests/x64/i64_ne/params.wat
index 0d08508c8..a77f74637 100644
--- a/winch/filetests/filetests/x64/i64_ne/params.wat
+++ b/winch/filetests/filetests/x64/i64_ne/params.wat
@@ -19,7 +19,7 @@
 ;;   20:	 4839c1               	cmp	rcx, rax
 ;;   23:	 b900000000           	mov	ecx, 0
 ;;   28:	 400f95c1             	setne	cl
-;;   2c:	 4889c8               	mov	rax, rcx
-;;   2f:	 4883c418             	add	rsp, 0x18
-;;   33:	 5d                   	pop	rbp
-;;   34:	 c3                   	ret	
+;;   2c:	 89c8                 	mov	eax, ecx
+;;   2e:	 4883c418             	add	rsp, 0x18
+;;   32:	 5d                   	pop	rbp
+;;   33:	 c3                   	ret