Repository: bytecodealliance/wasmtime
Pull request #8387 (2024-04-16 20:58:15)

cranelift: Represent RealReg using PReg, not VReg
Semantically, a "real register" is supposed to be a physical register, so let's use the type dedicated for that purpose.

This has the advantage that `PReg` is only one byte while `VReg` is four bytes, so the arrays where we record collections of `RealReg` become smaller.

There was an implementation of `From<VReg> for RealReg` which was not a sensible conversion, because not all `VReg`s are valid `RealReg`s. I could have replaced it with a `TryFrom` implementation but it wasn't used anywhere important, so I'm just deleting it instead.

Winch was using that `VReg`->`RealReg` conversion, but only in the implementation of another conversion that was itself unused, so I'm deleting that conversion as well. It's easy to implement correctly (the Winch `Reg` type is identical to `RealReg`, so all conversions for the latter are readily available) but as far as I can tell Winch doesn't need to use Cranelift's register wrappers or RA2's virtual register type, so it's simpler to just delete those conversions.

The riscv64 backend was relying on quirks of the existing conversions between `RealReg` and `VReg` when emitting clobber saves and restores. Just using the generic conversions between `RealReg` and `Reg` is simpler and works correctly with the rest of these changes.

cc: @elliottt


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index edf2288fe..ea48ab4d5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -849,7 +849,7 @@ dependencies = [
  "serde_derive",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmtime-types",
  "wat",
 ]
@@ -2756,7 +2756,7 @@ dependencies = [
  "cargo_metadata",
  "heck",
  "wasmtime",
- "wit-component 0.203.0",
+ "wit-component 0.204.0",
 ]
 
 [[package]]
@@ -3092,7 +3092,7 @@ name = "verify-component-adapter"
 version = "21.0.0"
 dependencies = [
  "anyhow",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wat",
 ]
 
@@ -3184,7 +3184,7 @@ dependencies = [
  "byte-array-literals",
  "object 0.33.0",
  "wasi",
- "wasm-encoder 0.203.0",
+ "wasm-encoder 0.204.0",
  "wit-bindgen",
 ]
 
@@ -3253,9 +3253,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87e3b46a0d9d9143d57aa926c42e2af284b5cb8f0c7b71079afc7a6fca42db50"
+checksum = "500cbde9b4d8dfc0335ec729d226dbf083e51e47501ac71e6addaed10ccb0a51"
 dependencies = [
  "leb128",
 ]
@@ -3278,9 +3278,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-metadata"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19fbd9b7017bdb3ceb63503a18d1aa7b0d026e18ce659d40b93bd9a15391424f"
+checksum = "f33b61754be27af5abf0fda890badb7c3265f7b634077157b4214704303ebbcc"
 dependencies = [
  "anyhow",
  "indexmap 2.0.0",
@@ -3288,36 +3288,36 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "spdx",
- "wasm-encoder 0.203.0",
- "wasmparser 0.203.0",
+ "wasm-encoder 0.204.0",
+ "wasmparser 0.204.0",
 ]
 
 [[package]]
 name = "wasm-mutate"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1980f4daf79655cc22aa9ba155f47e47efd67f7e628274f3c71c46c3f1d42fb0"
+checksum = "34d24ec979ae72a27f3770a7db426e7f2d459e67ecf26983ca727675e4956037"
 dependencies = [
  "egg",
  "log",
  "rand",
  "thiserror",
- "wasm-encoder 0.203.0",
- "wasmparser 0.203.0",
+ "wasm-encoder 0.204.0",
+ "wasmparser 0.204.0",
 ]
 
 [[package]]
 name = "wasm-smith"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2d2a6692cfc637bd685a8a114f1a4f83b5856725f84cf8163b14ba6024467c5"
+checksum = "e1fe1d435b8a14ebf05c2669cf76d1ca1cef6b632320c8e0b0e703ff0259a328"
 dependencies = [
  "anyhow",
  "arbitrary",
  "flagset",
  "indexmap 2.0.0",
  "leb128",
- "wasm-encoder 0.203.0",
+ "wasm-encoder 0.204.0",
 ]
 
 [[package]]
@@ -3373,9 +3373,9 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b473b35fff082e8c8377f4e2c8d48075e562aa051e48a02229bdcafbf349d37"
+checksum = "1239d539d9b92489cf729d40df694a62b09f5159f2ab058f4de15d4f820d6585"
 dependencies = [
  "bitflags 2.4.1",
  "indexmap 2.0.0",
@@ -3393,12 +3393,12 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74143e920e9f672eda5c40fa1d25a2d6a928e64debc0df90209533a84b1887bd"
+checksum = "ce3e6a3111855bf59cb6a16a95e217c59eff1d30d9f09483039b81b0739c3128"
 dependencies = [
  "anyhow",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
 ]
 
 [[package]]
@@ -3430,8 +3430,8 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "wasi-common",
- "wasm-encoder 0.203.0",
- "wasmparser 0.203.0",
+ "wasm-encoder 0.204.0",
+ "wasmparser 0.204.0",
  "wasmtime-cache",
  "wasmtime-component-macro",
  "wasmtime-component-util",
@@ -3571,7 +3571,7 @@ dependencies = [
  "tracing",
  "walkdir",
  "wasi-common",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmtime",
  "wasmtime-cache",
  "wasmtime-cli-flags",
@@ -3585,10 +3585,10 @@ dependencies = [
  "wasmtime-wasi-nn",
  "wasmtime-wasi-threads",
  "wasmtime-wast",
- "wast 203.0.0",
+ "wast 204.0.0",
  "wat",
  "windows-sys 0.52.0",
- "wit-component 0.203.0",
+ "wit-component 0.204.0",
 ]
 
 [[package]]
@@ -3617,7 +3617,7 @@ dependencies = [
  "wasmtime",
  "wasmtime-component-util",
  "wasmtime-wit-bindgen",
- "wit-parser 0.203.0",
+ "wit-parser 0.204.0",
 ]
 
 [[package]]
@@ -3641,7 +3641,7 @@ dependencies = [
  "object 0.33.0",
  "target-lexicon",
  "thiserror",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmtime-environ",
  "wasmtime-versioned-export-macros",
 ]
@@ -3665,8 +3665,8 @@ dependencies = [
  "serde_derive",
  "target-lexicon",
  "thiserror",
- "wasm-encoder 0.203.0",
- "wasmparser 0.203.0",
+ "wasm-encoder 0.204.0",
+ "wasmparser 0.204.0",
  "wasmprinter",
  "wasmtime-component-util",
  "wasmtime-types",
@@ -3681,7 +3681,7 @@ dependencies = [
  "component-fuzz-util",
  "env_logger",
  "libfuzzer-sys",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmprinter",
  "wasmtime-environ",
  "wat",
@@ -3738,7 +3738,7 @@ dependencies = [
  "rand",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmtime",
  "wasmtime-fuzzing",
 ]
@@ -3758,12 +3758,12 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "v8",
- "wasm-encoder 0.203.0",
+ "wasm-encoder 0.204.0",
  "wasm-mutate",
  "wasm-smith",
  "wasm-spec-interpreter",
  "wasmi",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmprinter",
  "wasmtime",
  "wasmtime-wast",
@@ -3810,7 +3810,7 @@ dependencies = [
  "rand",
  "rustix",
  "sptr",
- "wasm-encoder 0.203.0",
+ "wasm-encoder 0.204.0",
  "wasmtime-asm-macros",
  "wasmtime-environ",
  "wasmtime-fiber",
@@ -3833,7 +3833,7 @@ dependencies = [
  "serde",
  "serde_derive",
  "thiserror",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
 ]
 
 [[package]]
@@ -3940,7 +3940,7 @@ dependencies = [
  "anyhow",
  "log",
  "wasmtime",
- "wast 203.0.0",
+ "wast 204.0.0",
 ]
 
 [[package]]
@@ -3952,7 +3952,7 @@ dependencies = [
  "gimli",
  "object 0.33.0",
  "target-lexicon",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmtime-cranelift",
  "wasmtime-environ",
  "winch-codegen",
@@ -3965,7 +3965,7 @@ dependencies = [
  "anyhow",
  "heck",
  "indexmap 2.0.0",
- "wit-parser 0.203.0",
+ "wit-parser 0.204.0",
 ]
 
 [[package]]
@@ -3983,24 +3983,24 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "203.0.0"
+version = "204.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "872020f79fa7a09aeaec308d0ba60816e2f808d9b402e2f89d2a9c76eda482cd"
+checksum = "a0e3de19692b3d4c2fa13775271a751935decf530ae59c408c9f0b510b4ead62"
 dependencies = [
  "bumpalo",
  "leb128",
  "memchr",
  "unicode-width",
- "wasm-encoder 0.203.0",
+ "wasm-encoder 0.204.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.203.0"
+version = "1.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2913b554125048798744fce03832d5330d87624782f8ec6ad8c9716a1ef7a37"
+checksum = "4280322d523214024d03bc05e25bdda6088d5229d9515aecd78c5914b1f3e734"
 dependencies = [
- "wast 203.0.0",
+ "wast 204.0.0",
 ]
 
 [[package]]
@@ -4130,7 +4130,7 @@ dependencies = [
  "regalloc2",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
  "wasmtime-cranelift",
  "wasmtime-environ",
 ]
@@ -4381,9 +4381,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "379c4e193d37b3e2c808e99515c2a91dc19e7b3b160adfbb374463875375d6ff"
+checksum = "657fab6fd5f9ad3e1b7fd65a76f06ff25cac7f4fd8f885715bed4147095a6c38"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -4392,10 +4392,10 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.203.0",
- "wasm-metadata 0.203.0",
- "wasmparser 0.203.0",
- "wit-parser 0.203.0",
+ "wasm-encoder 0.204.0",
+ "wasm-metadata 0.204.0",
+ "wasmparser 0.204.0",
+ "wit-parser 0.204.0",
 ]
 
 [[package]]
@@ -4418,9 +4418,9 @@ dependencies = [
 
 [[package]]
 name = "wit-parser"
-version = "0.203.0"
+version = "0.204.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f547f9154c0fbd020c81c348d703b549bafd16ea68b15927acb5c890467e734"
+checksum = "bdc20f9284017574e942347e953e82fb3a0dccdfafa3beea7840b0bcbfa4fe00"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -4431,7 +4431,7 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser 0.203.0",
+ "wasmparser 0.204.0",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 2ab862b30..ab812cbc6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -234,15 +234,15 @@ rustix = "0.38.31"
 wit-bindgen = { version = "0.22.0", default-features = false }
 
 # wasm-tools family:
-wasmparser = "0.203.0"
-wat = "1.203.0"
-wast = "203.0.0"
-wasmprinter = "0.203.0"
-wasm-encoder = "0.203.0"
-wasm-smith = "0.203.0"
-wasm-mutate = "0.203.0"
-wit-parser = "0.203.0"
-wit-component = "0.203.0"
+wasmparser = "0.204.0"
+wat = "1.204.0"
+wast = "204.0.0"
+wasmprinter = "0.204.0"
+wasm-encoder = "0.204.0"
+wasm-smith = "0.204.0"
+wasm-mutate = "0.204.0"
+wit-parser = "0.204.0"
+wit-component = "0.204.0"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
diff --git a/cranelift/codegen/src/isa/riscv64/abi.rs b/cranelift/codegen/src/isa/riscv64/abi.rs
index 12ffc9661..9bf3a9b84 100644
--- a/cranelift/codegen/src/isa/riscv64/abi.rs
+++ b/cranelift/codegen/src/isa/riscv64/abi.rs
@@ -491,7 +491,7 @@ impl ABIMachineSpec for Riscv64MachineDeps {
                 }
                 insts.push(Inst::gen_store(
                     AMode::SPOffset(-(cur_offset as i64)),
-                    real_reg_to_reg(reg.to_reg()),
+                    Reg::from(reg.to_reg()),
                     ty,
                     MemFlags::trusted(),
                 ));
@@ -530,7 +530,7 @@ impl ABIMachineSpec for Riscv64MachineDeps {
                 RegClass::Vector => unimplemented!("Vector Clobber Restores"),
             };
             insts.push(Inst::gen_load(
-                Writable::from_reg(real_reg_to_reg(reg.to_reg())),
+                reg.map(Reg::from),
                 AMode::SPOffset(-cur_offset),
                 ty,
                 MemFlags::trusted(),
diff --git a/cranelift/codegen/src/isa/riscv64/inst/regs.rs b/cranelift/codegen/src/isa/riscv64/inst/regs.rs
index d17e19b37..ffdc484a0 100644
--- a/cranelift/codegen/src/isa/riscv64/inst/regs.rs
+++ b/cranelift/codegen/src/isa/riscv64/inst/regs.rs
@@ -3,12 +3,10 @@
 
 use crate::machinst::{Reg, Writable};
 
-use crate::machinst::RealReg;
 use alloc::vec;
 use alloc::vec::Vec;
 
-use regalloc2::VReg;
-use regalloc2::{PReg, RegClass};
+use regalloc2::{PReg, RegClass, VReg};
 
 // first argument of function call
 #[inline]
@@ -155,11 +153,6 @@ pub fn f_reg(enc: usize) -> Reg {
 pub const fn pf_reg(enc: usize) -> PReg {
     PReg::new(enc, RegClass::Float)
 }
-#[inline]
-pub(crate) fn real_reg_to_reg(x: RealReg) -> Reg {
-    let v_reg = VReg::new(x.hw_enc() as usize, x.class());
-    Reg::from(v_reg)
-}
 
 #[allow(dead_code)]
 pub(crate) fn x_reg_range(start: usize, end: usize) -> Vec<Writable<Reg>> {
diff --git a/cranelift/codegen/src/machinst/reg.rs b/cranelift/codegen/src/machinst/reg.rs
index 4e21377d2..cd5e5f11c 100644
--- a/cranelift/codegen/src/machinst/reg.rs
+++ b/cranelift/codegen/src/machinst/reg.rs
@@ -53,11 +53,7 @@ impl Reg {
     /// Get the physical register (`RealReg`), if this register is
     /// one.
     pub fn to_real_reg(self) -> Option<RealReg> {
-        if pinned_vreg_to_preg(self.0).is_some() {
-            Some(RealReg(self.0))
-        } else {
-            None
-        }
+        pinned_vreg_to_preg(self.0).map(RealReg)
     }
 
     /// Get the virtual (non-physical) register, if this register is
@@ -104,7 +100,7 @@ impl std::fmt::Debug for Reg {
 /// ISA's named registers and can be used as an instruction operand.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
-pub struct RealReg(VReg);
+pub struct RealReg(PReg);
 
 impl RealReg {
     /// Get the class of this register.
@@ -114,7 +110,7 @@ impl RealReg {
 
     /// The physical register number.
     pub fn hw_enc(self) -> u8 {
-        PReg::from(self).hw_enc() as u8
+        self.0.hw_enc() as u8
     }
 }
 
@@ -189,7 +185,7 @@ impl<T: Clone + Copy + Debug + PartialEq + Eq + PartialOrd + Ord + Hash> Writabl
     }
 }
 
-// Conversions between regalloc2 types (VReg) and our types
+// Conversions between regalloc2 types (VReg, PReg) and our types
 // (VirtualReg, RealReg, Reg).
 
 impl std::convert::From<regalloc2::VReg> for Reg {
@@ -205,13 +201,6 @@ impl std::convert::From<regalloc2::VReg> for VirtualReg {
     }
 }
 
-impl std::convert::From<regalloc2::VReg> for RealReg {
-    fn from(vreg: regalloc2::VReg) -> RealReg {
-        debug_assert!(pinned_vreg_to_preg(vreg).is_some());
-        RealReg(vreg)
-    }
-}
-
 impl std::convert::From<Reg> for regalloc2::VReg {
     /// Extract the underlying `regalloc2::VReg`. Note that physical
     /// registers also map to particular (special) VRegs, so this
@@ -234,31 +223,33 @@ impl std::convert::From<VirtualReg> for regalloc2::VReg {
 
 impl std::convert::From<RealReg> for regalloc2::VReg {
     fn from(reg: RealReg) -> regalloc2::VReg {
-        reg.0
+        // This representation is redundant: the class is implied in the vreg
+        // index as well as being in the vreg class field.
+        VReg::new(reg.0.index(), reg.0.class())
     }
 }
 
 impl std::convert::From<RealReg> for regalloc2::PReg {
     fn from(reg: RealReg) -> regalloc2::PReg {
-        PReg::from_index(reg.0.vreg())
+        reg.0
     }
 }
 
 impl std::convert::From<regalloc2::PReg> for RealReg {
     fn from(preg: regalloc2::PReg) -> RealReg {
-        RealReg(VReg::new(preg.index(), preg.class()))
+        RealReg(preg)
     }
 }
 
 impl std::convert::From<regalloc2::PReg> for Reg {
     fn from(preg: regalloc2::PReg) -> Reg {
-        Reg(VReg::new(preg.index(), preg.class()))
+        RealReg(preg).into()
     }
 }
 
 impl std::convert::From<RealReg> for Reg {
     fn from(reg: RealReg) -> Reg {
-        Reg(reg.0)
+        Reg(reg.into())
     }
 }
 
diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs
index 1a2c10479..4b5bdb8e7 100644
--- a/cranelift/wasm/src/environ/dummy.rs
+++ b/cranelift/wasm/src/environ/dummy.rs
@@ -901,12 +901,6 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
     }
 
     fn wasm_features(&self) -> WasmFeatures {
-        WasmFeatures {
-            multi_value: true,
-            simd: true,
-            reference_types: true,
-            bulk_memory: true,
-            ..WasmFeatures::default()
-        }
+        WasmFeatures::default()
     }
 }
diff --git a/crates/environ/examples/factc.rs b/crates/environ/examples/factc.rs
index d0f49b547..979e617b4 100644
--- a/crates/environ/examples/factc.rs
+++ b/crates/environ/examples/factc.rs
@@ -120,10 +120,7 @@ impl Factc {
 
         let mut adapters = Vec::new();
         let input = wat::parse_file(&self.input)?;
-        let mut validator = Validator::new_with_features(WasmFeatures {
-            component_model: true,
-            ..Default::default()
-        });
+        let mut validator = Validator::new();
         let wasm_types = validator
             .validate_all(&input)
             .context("failed to validate input wasm")?;
@@ -191,13 +188,9 @@ impl Factc {
         }
 
         if !self.skip_validate {
-            Validator::new_with_features(WasmFeatures {
-                multi_memory: true,
-                memory64: true,
-                ..WasmFeatures::default()
-            })
-            .validate_all(&wasm)
-            .context("failed to validate generated module")?;
+            Validator::new_with_features(WasmFeatures::default() | WasmFeatures::MEMORY64)
+                .validate_all(&wasm)
+                .context("failed to validate generated module")?;
         }
 
         Ok(())
diff --git a/crates/environ/fuzz/fuzz_targets/fact-valid-module.rs b/crates/environ/fuzz/fuzz_targets/fact-valid-module.rs
index b43f8cda6..d6b323285 100644
--- a/crates/environ/fuzz/fuzz_targets/fact-valid-module.rs
+++ b/crates/environ/fuzz/fuzz_targets/fact-valid-module.rs
@@ -87,10 +87,7 @@ fn target(module: GenAdapterModule) {
         );
         let wasm = wat::parse_str(&wat).unwrap();
 
-        let mut validator = Validator::new_with_features(WasmFeatures {
-            component_model: true,
-            ..Default::default()
-        });
+        let mut validator = Validator::new();
 
         types.push_type_scope();
         for payload in Parser::new(0).parse_all(&wasm) {
@@ -148,12 +145,8 @@ fn target(module: GenAdapterModule) {
         fact_module.adapt(&format!("adapter{i}"), adapter);
     }
     let wasm = fact_module.encode();
-    let result = Validator::new_with_features(WasmFeatures {
-        multi_memory: true,
-        memory64: true,
-        ..WasmFeatures::default()
-    })
-    .validate_all(&wasm);
+    let result = Validator::new_with_features(WasmFeatures::default() | WasmFeatures::MEMORY64)
+        .validate_all(&wasm);
 
     let err = match result {
         Ok(_) => return,
diff --git a/crates/environ/src/component/translate/adapt.rs b/crates/environ/src/component/translate/adapt.rs
index 7b36fb102..d112fa808 100644
--- a/crates/environ/src/component/translate/adapt.rs
+++ b/crates/environ/src/component/translate/adapt.rs
@@ -212,10 +212,9 @@ impl<'data> Translator<'_, 'data> {
             // specifically enabled here since the adapter module is highly
             // likely to use that if anything is actually indirected through
             // memory.
-            let mut validator = Validator::new_with_features(WasmFeatures {
-                multi_memory: true,
-                ..*self.validator.features()
-            });
+            let mut validator = Validator::new_with_features(
+                *self.validator.features() | WasmFeatures::MULTI_MEMORY,
+            );
             let translation = ModuleEnvironment::new(
                 self.tunables,
                 &mut validator,
diff --git a/crates/environ/src/module_environ.rs b/crates/environ/src/module_environ.rs
index fe81cac53..77e96db9c 100644
--- a/crates/environ/src/module_environ.rs
+++ b/crates/environ/src/module_environ.rs
@@ -19,7 +19,7 @@ use wasmparser::types::{CoreTypeId, Types};
 use wasmparser::{
     CompositeType, CustomSectionReader, DataKind, ElementItems, ElementKind, Encoding,
     ExternalKind, FuncToValidate, FunctionBody, NameSectionReader, Naming, Operator, Parser,
-    Payload, TypeRef, Validator, ValidatorResources,
+    Payload, TypeRef, Validator, ValidatorResources, WasmFeatures,
 };
 use wasmtime_types::ModuleInternedTypeIndex;
 
@@ -605,7 +605,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
                             params: sig.params().into(),
                         });
                 }
-                body.allow_memarg64(self.validator.features().memory64);
+                body.allow_memarg64(self.validator.features().contains(WasmFeatures::MEMORY64));
                 self.result
                     .function_body_inputs
                     .push(FunctionBodyData { validator, body });
diff --git a/crates/fuzzing/src/generators/table_ops.rs b/crates/fuzzing/src/generators/table_ops.rs
index ee770c1a9..7e879367c 100644
--- a/crates/fuzzing/src/generators/table_ops.rs
+++ b/crates/fuzzing/src/generators/table_ops.rs
@@ -283,11 +283,7 @@ mod tests {
             let u = Unstructured::new(&buf);
             if let Ok(ops) = TableOps::arbitrary_take_rest(u) {
                 let wasm = ops.to_wasm_binary();
-                let mut validator =
-                    wasmparser::Validator::new_with_features(wasmparser::WasmFeatures {
-                        reference_types: true,
-                        ..Default::default()
-                    });
+                let mut validator = wasmparser::Validator::new();
                 let result = validator.validate_all(&wasm);
                 assert!(result.is_ok());
             }
diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs
index 2070c1c0c..8437647e6 100644
--- a/crates/wasmtime/src/config.rs
+++ b/crates/wasmtime/src/config.rs
@@ -259,16 +259,21 @@ impl Config {
         // Conditionally enabled features depending on compile-time crate
         // features. Note that if these features are disabled then `Config` has
         // no way of re-enabling them.
-        ret.features.reference_types = cfg!(feature = "gc");
-        ret.features.threads = cfg!(feature = "threads");
-        ret.features.component_model = cfg!(feature = "component-model");
+        ret.features
+            .set(WasmFeatures::REFERENCE_TYPES, cfg!(feature = "gc"));
+        ret.features
+            .set(WasmFeatures::THREADS, cfg!(feature = "threads"));
+        ret.features.set(
+            WasmFeatures::COMPONENT_MODEL,
+            cfg!(feature = "component-model"),
+        );
 
         // If GC is disabled at compile time also disable it in features
         // forcibly irrespective of `wasmparser` defaults. Note that these also
         // aren't yet fully implemented in Wasmtime.
         if !cfg!(feature = "gc") {
-            ret.features.function_references = false;
-            ret.features.gc = false;
+            ret.features.set(WasmFeatures::FUNCTION_REFERENCES, false);
+            ret.features.set(WasmFeatures::GC, false);
         }
 
         ret.wasm_multi_value(true);
@@ -278,7 +283,7 @@ impl Config {
 
         // This is on-by-default in `wasmparser` since it's a stage 4+ proposal
         // but it's not implemented in Wasmtime yet so disable it.
-        ret.features.tail_call = false;
+        ret.features.set(WasmFeatures::TAIL_CALL, false);
 
         ret
     }
@@ -702,7 +707,7 @@ impl Config {
     ///
     /// [WebAssembly tail calls proposal]: https://github.com/WebAssembly/tail-call
     pub fn wasm_tail_call(&mut self, enable: bool) -> &mut Self {
-        self.features.tail_call = enable;
+        self.features.set(WasmFeatures::TAIL_CALL, enable);
         self.tunables.tail_callable = Some(enable);
         self
     }
@@ -727,7 +732,7 @@ impl Config {
     #[cfg(feature = "threads")]
     #[cfg_attr(docsrs, doc(cfg(feature = "threads")))]
     pub fn wasm_threads(&mut self, enable: bool) -> &mut Self {
-        self.features.threads = enable;
+        self.features.set(WasmFeatures::THREADS, enable);
         self
     }
 
@@ -750,7 +755,7 @@ impl Config {
     #[cfg(feature = "gc")]
     #[cfg_attr(docsrs, doc(cfg(feature = "gc")))]
     pub fn wasm_reference_types(&mut self, enable: bool) -> &mut Self {
-        self.features.reference_types = enable;
+        self.features.set(WasmFeatures::REFERENCE_TYPES, enable);
         self
     }
 
@@ -770,7 +775,7 @@ impl Config {
     #[cfg(feature = "gc")]
     #[cfg_attr(docsrs, doc(cfg(feature = "gc")))]
     pub fn wasm_function_references(&mut self, enable: bool) -> &mut Self {
-        self.features.function_references = enable;
+        self.features.set(WasmFeatures::FUNCTION_REFERENCES, enable);
         self
     }
 
@@ -792,7 +797,7 @@ impl Config {
     #[cfg(feature = "gc")]
     #[cfg_attr(docsrs, doc(cfg(feature = "gc")))]
     pub fn wasm_gc(&mut self, enable: bool) -> &mut Self {
-        self.features.gc = enable;
+        self.features.set(WasmFeatures::GC, enable);
         self
     }
 
@@ -812,7 +817,7 @@ impl Config {
     /// [proposal]: https://github.com/webassembly/simd
     /// [relaxed simd proposal]: https://github.com/WebAssembly/relaxed-simd
     pub fn wasm_simd(&mut self, enable: bool) -> &mut Self {
-        self.features.simd = enable;
+        self.features.set(WasmFeatures::SIMD, enable);
         self
     }
 
@@ -839,7 +844,7 @@ impl Config {
     ///
     /// [proposal]: https://github.com/webassembly/relaxed-simd
     pub fn wasm_relaxed_simd(&mut self, enable: bool) -> &mut Self {
-        self.features.relaxed_simd = enable;
+        self.features.set(WasmFeatures::RELAXED_SIMD, enable);
         self
     }
 
@@ -883,7 +888,7 @@ impl Config {
     ///
     /// [proposal]: https://github.com/webassembly/bulk-memory-operations
     pub fn wasm_bulk_memory(&mut self, enable: bool) -> &mut Self {
-        self.features.bulk_memory = enable;
+        self.features.set(WasmFeatures::BULK_MEMORY, enable);
         self
     }
 
@@ -897,7 +902,7 @@ impl Config {
     ///
     /// [proposal]: https://github.com/webassembly/multi-value
     pub fn wasm_multi_value(&mut self, enable: bool) -> &mut Self {
-        self.features.multi_value = enable;
+        self.features.set(WasmFeatures::MULTI_VALUE, enable);
         self
     }
 
@@ -911,7 +916,7 @@ impl Config {
     ///
     /// [proposal]: https://github.com/webassembly/multi-memory
     pub fn wasm_multi_memory(&mut self, enable: bool) -> &mut Self {
-        self.features.multi_memory = enable;
+        self.features.set(WasmFeatures::MULTI_MEMORY, enable);
         self
     }
 
@@ -926,7 +931,7 @@ impl Config {
     ///
     /// [proposal]: https://github.com/webassembly/memory64
     pub fn wasm_memory64(&mut self, enable: bool) -> &mut Self {
-        self.features.memory64 = enable;
+        self.features.set(WasmFeatures::MEMORY64, enable);
         self
     }
 
@@ -940,7 +945,7 @@ impl Config {
     /// [proposal]: https://github.com/webassembly/component-model
     #[cfg(feature = "component-model")]
     pub fn wasm_component_model(&mut self, enable: bool) -> &mut Self {
-        self.features.component_model = enable;
+        self.features.set(WasmFeatures::COMPONENT_MODEL, enable);
         self
     }
 
@@ -1671,16 +1676,24 @@ impl Config {
     }
 
     pub(crate) fn validate(&self) -> Result<Tunables> {
-        if self.features.reference_types && !self.features.bulk_memory {
+        if self.features.contains(WasmFeatures::REFERENCE_TYPES)
+            && !self.features.contains(WasmFeatures::BULK_MEMORY)
+        {
             bail!("feature 'reference_types' requires 'bulk_memory' to be enabled");
         }
-        if self.features.threads && !self.features.bulk_memory {
+        if self.features.contains(WasmFeatures::THREADS)
+            && !self.features.contains(WasmFeatures::BULK_MEMORY)
+        {
             bail!("feature 'threads' requires 'bulk_memory' to be enabled");
         }
-        if self.features.function_references && !self.features.reference_types {
+        if self.features.contains(WasmFeatures::FUNCTION_REFERENCES)
+            && !self.features.contains(WasmFeatures::REFERENCE_TYPES)
+        {
             bail!("feature 'function_references' requires 'reference_types' to be enabled");
         }
-        if self.features.gc && !self.features.function_references {
+        if self.features.contains(WasmFeatures::GC)
+            && !self.features.contains(WasmFeatures::FUNCTION_REFERENCES)
+        {
             bail!("feature 'gc' requires 'function_references' to be enabled");
         }
         #[cfg(feature = "async")]
@@ -1854,7 +1867,7 @@ impl Config {
                 .insert("enable_probestack".into());
         }
 
-        if self.features.tail_call {
+        if self.features.contains(WasmFeatures::TAIL_CALL) {
             ensure!(
                 target.architecture != Architecture::S390x,
                 "Tail calls are not supported on s390x yet: \
@@ -1888,7 +1901,7 @@ impl Config {
             .insert("preserve_frame_pointers".into(), "true".into());
 
         // check for incompatible compiler options and set required values
-        if self.features.reference_types {
+        if self.features.contains(WasmFeatures::REFERENCE_TYPES) {
             if !self
                 .compiler_config
                 .ensure_setting_unset_or_given("enable_safepoints", "true")
@@ -1897,7 +1910,9 @@ impl Config {
             }
         }
 
-        if self.features.relaxed_simd && !self.features.simd {
+        if self.features.contains(WasmFeatures::RELAXED_SIMD)
+            && !self.features.contains(WasmFeatures::SIMD)
+        {
             bail!("cannot disable the simd proposal but enable the relaxed simd proposal");
         }
 
@@ -1996,17 +2011,32 @@ impl fmt::Debug for Config {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut f = f.debug_struct("Config");
         f.field("debug_info", &self.tunables.generate_native_debuginfo)
-            .field("wasm_threads", &self.features.threads)
-            .field("wasm_reference_types", &self.features.reference_types)
+            .field(
+                "wasm_threads",
+                &self.features.contains(WasmFeatures::THREADS),
+            )
+            .field(
+                "wasm_reference_types",
+                &self.features.contains(WasmFeatures::REFERENCE_TYPES),
+            )
             .field(
                 "wasm_function_references",
-                &self.features.function_references,
+                &self.features.contains(WasmFeatures::FUNCTION_REFERENCES),
+            )
+            .field("wasm_gc", &self.features.contains(WasmFeatures::GC))
+            .field(
+                "wasm_bulk_memory",
+                &self.features.contains(WasmFeatures::BULK_MEMORY),
+            )
+            .field("wasm_simd", &self.features.contains(WasmFeatures::SIMD))
+            .field(
+                "wasm_relaxed_simd",
+                &self.features.contains(WasmFeatures::RELAXED_SIMD),
+            )
+            .field(
+                "wasm_multi_value",
+                &self.features.contains(WasmFeatures::MULTI_VALUE),
             )
-            .field("wasm_gc", &self.features.gc)
-            .field("wasm_bulk_memory", &self.features.bulk_memory)
-            .field("wasm_simd", &self.features.simd)
-            .field("wasm_relaxed_simd", &self.features.relaxed_simd)
-            .field("wasm_multi_value", &self.features.multi_value)
             .field("parallel_compilation", &self.parallel_compilation);
         #[cfg(any(feature = "cranelift", feature = "winch"))]
         {
diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs
index a861f2a3e..02b2f376a 100644
--- a/crates/wasmtime/src/engine.rs
+++ b/crates/wasmtime/src/engine.rs
@@ -9,6 +9,7 @@ use once_cell::sync::OnceCell;
 use std::path::Path;
 use std::sync::atomic::{AtomicU64, Ordering};
 use std::sync::Arc;
+use wasmparser::WasmFeatures;
 use wasmtime_environ::obj;
 use wasmtime_environ::{FlagValue, ObjectKind, Tunables};
 #[cfg(feature = "runtime")]
@@ -299,7 +300,7 @@ impl Engine {
             // like typed function references and GC) are enabled this must be
             // enabled, otherwise this setting can have any value.
             "enable_safepoints" => {
-                if self.config().features.reference_types {
+                if self.config().features.contains(WasmFeatures::REFERENCE_TYPES) {
                     *value == FlagValue::Bool(true)
                 } else {
                     return Ok(())
diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs
index aaa68960b..d6254cdff 100644
--- a/crates/wasmtime/src/engine/serialization.rs
+++ b/crates/wasmtime/src/engine/serialization.rs
@@ -199,7 +199,7 @@ struct WasmFeatures {
 impl Metadata<'_> {
     #[cfg(any(feature = "cranelift", feature = "winch"))]
     pub fn new(engine: &Engine) -> Metadata<'static> {
-        let wasmparser::WasmFeatures {
+        let wasmparser::WasmFeaturesInflated {
             reference_types,
             multi_value,
             bulk_memory,
@@ -225,7 +225,7 @@ impl Metadata<'_> {
             saturating_float_to_int: _,
             sign_extension: _,
             floats: _,
-        } = engine.config().features;
+        } = engine.config().features.inflate();
 
         // These features are not implemented in Wasmtime yet. We match on them
         // above so that once we do implement support for them, we won't
@@ -460,69 +460,78 @@ impl Metadata<'_> {
             gc,
         } = self.features;
 
+        use wasmparser::WasmFeatures as F;
         Self::check_cfg_bool(
             cfg!(feature = "gc"),
             "gc",
             reference_types,
-            other.reference_types,
+            other.contains(F::REFERENCE_TYPES),
             "WebAssembly reference types support",
         )?;
         Self::check_cfg_bool(
             cfg!(feature = "gc"),
             "gc",
             function_references,
-            other.function_references,
+            other.contains(F::FUNCTION_REFERENCES),
             "WebAssembly function-references support",
         )?;
         Self::check_cfg_bool(
             cfg!(feature = "gc"),
             "gc",
             gc,
-            other.gc,
+            other.contains(F::GC),
             "WebAssembly garbage collection support",
         )?;
 
         Self::check_bool(
             multi_value,
-            other.multi_value,
+            other.contains(F::MULTI_VALUE),
             "WebAssembly multi-value support",
         )?;
         Self::check_bool(
             bulk_memory,
-            other.bulk_memory,
+            other.contains(F::BULK_MEMORY),
             "WebAssembly bulk memory support",
         )?;
         Self::check_bool(
             component_model,
-            other.component_model,
+            other.contains(F::COMPONENT_MODEL),
             "WebAssembly component model support",
         )?;
-        Self::check_bool(simd, other.simd, "WebAssembly SIMD support")?;
-        Self::check_bool(tail_call, other.tail_call, "WebAssembly tail calls support")?;
-        Self::check_bool(threads, other.threads, "WebAssembly threads support")?;
+        Self::check_bool(simd, other.contains(F::SIMD), "WebAssembly SIMD support")?;
+        Self::check_bool(
+            tail_call,
+            other.contains(F::TAIL_CALL),
+            "WebAssembly tail calls support",
+        )?;
+        Self::check_bool(
+            threads,
+            other.contains(F::THREADS),
+            "WebAssembly threads support",
+        )?;
         Self::check_bool(
             multi_memory,
-            other.multi_memory,
+            other.contains(F::MULTI_MEMORY),
             "WebAssembly multi-memory support",
         )?;
         Self::check_bool(
             exceptions,
-            other.exceptions,
+            other.contains(F::EXCEPTIONS),
             "WebAssembly exceptions support",
         )?;
         Self::check_bool(
             memory64,
-            other.memory64,
+            other.contains(F::MEMORY64),
             "WebAssembly 64-bit memory support",
         )?;
         Self::check_bool(
             extended_const,
-            other.extended_const,
+            other.contains(F::EXTENDED_CONST),
             "WebAssembly extended-const support",
         )?;
         Self::check_bool(
             relaxed_simd,
-            other.relaxed_simd,
+            other.contains(F::RELAXED_SIMD),
             "WebAssembly relaxed-simd support",
         )?;
 
diff --git a/crates/wasmtime/src/runtime/instance.rs b/crates/wasmtime/src/runtime/instance.rs
index 690591caf..5d55fb888 100644
--- a/crates/wasmtime/src/runtime/instance.rs
+++ b/crates/wasmtime/src/runtime/instance.rs
@@ -9,6 +9,7 @@ use anyhow::{anyhow, bail, Context, Result};
 use std::mem;
 use std::ptr::NonNull;
 use std::sync::Arc;
+use wasmparser::WasmFeatures;
 use wasmtime_environ::{
     EntityIndex, EntityType, FuncIndex, GlobalIndex, MemoryIndex, PrimaryMap, TableIndex, TypeTrace,
 };
@@ -340,7 +341,11 @@ impl Instance {
         // look at them.
         instance_handle.initialize(
             compiled_module.module(),
-            store.engine().config().features.bulk_memory,
+            store
+                .engine()
+                .config()
+                .features
+                .contains(WasmFeatures::BULK_MEMORY),
         )?;
 
         Ok((instance, compiled_module.module().start_func))
diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs
index c21273fab..a0c045bea 100644
--- a/crates/wasmtime/src/runtime/store.rs
+++ b/crates/wasmtime/src/runtime/store.rs
@@ -1467,7 +1467,11 @@ impl StoreOpaque {
 
         #[cfg(feature = "gc")]
         fn allocate_gc_store(engine: &Engine) -> Result<GcStore> {
-            let (index, heap) = if engine.config().features.reference_types {
+            let (index, heap) = if engine
+                .config()
+                .features
+                .contains(wasmparser::WasmFeatures::REFERENCE_TYPES)
+            {
                 engine
                     .allocator()
                     .allocate_gc_heap(&**engine.gc_runtime())?
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 1aa8ac186..263bfd6e6 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -1184,6 +1184,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-encoder]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-metadata]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1202,6 +1208,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-metadata]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-mutate]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1220,6 +1232,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-mutate]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-smith]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1238,6 +1256,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-smith]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmparser]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1256,6 +1280,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasmparser]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmprinter]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1274,6 +1304,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasmprinter]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmtime]]
 version = "18.0.2"
 when = "2024-02-28"
@@ -1580,6 +1616,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wast]]
+version = "204.0.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wat]]
 version = "1.201.0"
 when = "2024-02-27"
@@ -1598,6 +1640,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wat]]
+version = "1.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wiggle]]
 version = "18.0.2"
 when = "2024-02-28"
@@ -1886,6 +1934,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wit-component]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wit-parser]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1904,6 +1958,12 @@ when = "2024-04-12"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wit-parser]]
+version = "0.204.0"
+when = "2024-04-16"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.witx]]
 version = "0.9.1"
 when = "2021-06-22"
diff --git a/winch/codegen/src/isa/reg.rs b/winch/codegen/src/isa/reg.rs
index bfdcdb8fc..0a96df329 100644
--- a/winch/codegen/src/isa/reg.rs
+++ b/winch/codegen/src/isa/reg.rs
@@ -1,6 +1,5 @@
-use cranelift_codegen::RealReg;
+use regalloc2::PReg;
 pub use regalloc2::RegClass;
-use regalloc2::{PReg, VReg};
 
 /// A newtype abstraction on top of a physical register.
 //
@@ -72,15 +71,3 @@ 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()
-    }
-}


Test patch:
diff --git a/cranelift/filetests/src/test_wasm/env.rs b/cranelift/filetests/src/test_wasm/env.rs
index f8b7d419f..dccc9c31f 100644
--- a/cranelift/filetests/src/test_wasm/env.rs
+++ b/cranelift/filetests/src/test_wasm/env.rs
@@ -79,12 +79,10 @@ impl<'data> ModuleEnvironment<'data> for ModuleEnv {
     }
 
     fn wasm_features(&self) -> wasmparser::WasmFeatures {
-        wasmparser::WasmFeatures {
-            memory64: true,
-            multi_memory: true,
-            relaxed_simd: true,
-            ..self.inner.wasm_features()
-        }
+        self.inner.wasm_features()
+            | wasmparser::WasmFeatures::MEMORY64
+            | wasmparser::WasmFeatures::MULTI_MEMORY
+            | wasmparser::WasmFeatures::RELAXED_SIMD
     }
 
     // ================================================================