Repository: bytecodealliance/wasmtime
Pull request #8662 (2024-05-20 16:02:23)

c-api: Fix enabling parallel compilation by default
This commit fixes a mistake in #8642 where a late-minute refactor accidentally ended up disabling parallel compilation by default.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 2daf819f4..8e1d60303 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -610,6 +610,7 @@ dependencies = [
  "cranelift-entity",
  "cranelift-isle",
  "criterion",
+ "env_logger",
  "gimli",
  "hashbrown 0.14.3",
  "log",
@@ -852,7 +853,7 @@ dependencies = [
  "serde_derive",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmtime-types",
  "wat",
 ]
@@ -1403,6 +1404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
 dependencies = [
  "ahash",
+ "serde",
 ]
 
 [[package]]
@@ -2758,7 +2760,7 @@ dependencies = [
  "cargo_metadata",
  "heck",
  "wasmtime",
- "wit-component 0.207.0",
+ "wit-component 0.208.1",
 ]
 
 [[package]]
@@ -3094,7 +3096,7 @@ name = "verify-component-adapter"
 version = "22.0.0"
 dependencies = [
  "anyhow",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wat",
 ]
 
@@ -3186,7 +3188,7 @@ dependencies = [
  "byte-array-literals",
  "object 0.33.0",
  "wasi",
- "wasm-encoder 0.207.0",
+ "wasm-encoder 0.208.1",
  "wit-bindgen",
 ]
 
@@ -3255,9 +3257,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d996306fb3aeaee0d9157adbe2f670df0236caf19f6728b221e92d0f27b3fe17"
+checksum = "6425e84e42f7f558478e40ecc2287912cb319f2ca68e5c0bb93c61d4fc63fa17"
 dependencies = [
  "leb128",
 ]
@@ -3280,9 +3282,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-metadata"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2c44e62d325ce9253f88c01f0f67be121356767d12f2f13e701fdcd99e1f5b0"
+checksum = "42a2c4280ad374a6db3d76d4bb61e2ec4b3b9ce5469cc4f2bbc5708047a2bbff"
 dependencies = [
  "anyhow",
  "indexmap 2.2.6",
@@ -3290,36 +3292,36 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "spdx",
- "wasm-encoder 0.207.0",
- "wasmparser 0.207.0",
+ "wasm-encoder 0.208.1",
+ "wasmparser 0.208.1",
 ]
 
 [[package]]
 name = "wasm-mutate"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17f1f13b2d32934450e1092213385bf98411c9448a4418b79d54640df0280c36"
+checksum = "d279475f0f5e68af5ad6eebf0377f777cadcd0c15208f64121522e44dbe45ec9"
 dependencies = [
  "egg",
  "log",
  "rand",
  "thiserror",
- "wasm-encoder 0.207.0",
- "wasmparser 0.207.0",
+ "wasm-encoder 0.208.1",
+ "wasmparser 0.208.1",
 ]
 
 [[package]]
 name = "wasm-smith"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "604b90d8a005c9dfb783c5cfba074429f9c7f3f7d6aea5ba79a4657413fdb1ad"
+checksum = "8c94a8e7d3a1c3b34ad60d41421c857105aac67e00ae9854247a4a668694f6e9"
 dependencies = [
  "anyhow",
  "arbitrary",
  "flagset",
  "indexmap 2.2.6",
  "leb128",
- "wasm-encoder 0.207.0",
+ "wasm-encoder 0.208.1",
 ]
 
 [[package]]
@@ -3375,15 +3377,16 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e19bb9f8ab07616da582ef8adb24c54f1424c7ec876720b7da9db8ec0626c92c"
+checksum = "dd921789c9dcc495f589cb37d200155dee65b4a4beeb853323b5e24e0a5f9c58"
 dependencies = [
  "ahash",
  "bitflags 2.4.1",
  "hashbrown 0.14.3",
  "indexmap 2.2.6",
  "semver",
+ "serde",
 ]
 
 [[package]]
@@ -3397,12 +3400,12 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c2d8a7b4dabb460208e6b4334d9db5766e84505038b2529e69c3d07ac619115"
+checksum = "0700bdace4821e6c694617938500ae9999946df464bb13219c16570f8b6f202f"
 dependencies = [
  "anyhow",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
 ]
 
 [[package]]
@@ -3445,8 +3448,8 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "wasi-common",
- "wasm-encoder 0.207.0",
- "wasmparser 0.207.0",
+ "wasm-encoder 0.208.1",
+ "wasmparser 0.208.1",
  "wasmtime-asm-macros",
  "wasmtime-cache",
  "wasmtime-component-macro",
@@ -3588,7 +3591,7 @@ dependencies = [
  "tracing",
  "walkdir",
  "wasi-common",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmtime",
  "wasmtime-cache",
  "wasmtime-cli-flags",
@@ -3601,10 +3604,10 @@ dependencies = [
  "wasmtime-wasi-nn",
  "wasmtime-wasi-threads",
  "wasmtime-wast",
- "wast 207.0.0",
+ "wast 208.0.1",
  "wat",
  "windows-sys 0.52.0",
- "wit-component 0.207.0",
+ "wit-component 0.208.1",
 ]
 
 [[package]]
@@ -3637,7 +3640,7 @@ dependencies = [
  "wasmtime",
  "wasmtime-component-util",
  "wasmtime-wit-bindgen",
- "wit-parser 0.207.0",
+ "wit-parser 0.208.1",
 ]
 
 [[package]]
@@ -3661,7 +3664,7 @@ dependencies = [
  "object 0.33.0",
  "target-lexicon",
  "thiserror",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmtime-environ",
  "wasmtime-versioned-export-macros",
 ]
@@ -3684,8 +3687,8 @@ dependencies = [
  "serde",
  "serde_derive",
  "target-lexicon",
- "wasm-encoder 0.207.0",
- "wasmparser 0.207.0",
+ "wasm-encoder 0.208.1",
+ "wasmparser 0.208.1",
  "wasmprinter",
  "wasmtime-component-util",
  "wasmtime-types",
@@ -3700,7 +3703,7 @@ dependencies = [
  "component-fuzz-util",
  "env_logger",
  "libfuzzer-sys",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmprinter",
  "wasmtime-environ",
  "wat",
@@ -3757,7 +3760,7 @@ dependencies = [
  "rand",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmtime",
  "wasmtime-fuzzing",
 ]
@@ -3778,12 +3781,12 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "v8",
- "wasm-encoder 0.207.0",
+ "wasm-encoder 0.208.1",
  "wasm-mutate",
  "wasm-smith",
  "wasm-spec-interpreter",
  "wasmi",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmprinter",
  "wasmtime",
  "wasmtime-wast",
@@ -3822,7 +3825,7 @@ dependencies = [
  "serde",
  "serde_derive",
  "smallvec",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
 ]
 
 [[package]]
@@ -3929,7 +3932,7 @@ dependencies = [
  "anyhow",
  "log",
  "wasmtime",
- "wast 207.0.0",
+ "wast 208.0.1",
 ]
 
 [[package]]
@@ -3941,7 +3944,7 @@ dependencies = [
  "gimli",
  "object 0.33.0",
  "target-lexicon",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmtime-cranelift",
  "wasmtime-environ",
  "winch-codegen",
@@ -3954,7 +3957,7 @@ dependencies = [
  "anyhow",
  "heck",
  "indexmap 2.2.6",
- "wit-parser 0.207.0",
+ "wit-parser 0.208.1",
 ]
 
 [[package]]
@@ -3972,24 +3975,24 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "207.0.0"
+version = "208.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e40be9fd494bfa501309487d2dc0b3f229be6842464ecbdc54eac2679c84c93"
+checksum = "bc00b3f023b4e2ccd2e054e240294263db52ae962892e6523e550783c83a67f1"
 dependencies = [
  "bumpalo",
  "leb128",
  "memchr",
  "unicode-width",
- "wasm-encoder 0.207.0",
+ "wasm-encoder 0.208.1",
 ]
 
 [[package]]
 name = "wat"
-version = "1.207.0"
+version = "1.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8eb2b15e2d5f300f5e1209e7dc237f2549edbd4203655b6c6cab5cf180561ee7"
+checksum = "58ed38e59176550214c025ea2bd0eeefd8e86b92d0af6698d5ba95020ec2e07b"
 dependencies = [
- "wast 207.0.0",
+ "wast 208.0.1",
 ]
 
 [[package]]
@@ -4109,7 +4112,7 @@ dependencies = [
  "regalloc2",
  "smallvec",
  "target-lexicon",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
  "wasmtime-cranelift",
  "wasmtime-environ",
 ]
@@ -4360,9 +4363,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a411ff9c471737091b2c1a738a25031029fc4d0b8f1a60bef0e68906e9f6534b"
+checksum = "fef7dd0e47f5135dd8739ccc5b188ab8b7e27e1d64df668aa36680f0b8646db8"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -4371,10 +4374,10 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.207.0",
- "wasm-metadata 0.207.0",
- "wasmparser 0.207.0",
- "wit-parser 0.207.0",
+ "wasm-encoder 0.208.1",
+ "wasm-metadata 0.208.1",
+ "wasmparser 0.208.1",
+ "wit-parser 0.208.1",
 ]
 
 [[package]]
@@ -4397,9 +4400,9 @@ dependencies = [
 
 [[package]]
 name = "wit-parser"
-version = "0.207.0"
+version = "0.208.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78c83dab33a9618d86cfe3563cc864deffd08c17efc5db31a3b7cd1edeffe6e1"
+checksum = "516417a730725fe3e6c9e2efc8d86697480f80496d32b24e62736950704c047c"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -4410,7 +4413,7 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser 0.207.0",
+ "wasmparser 0.208.1",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 9efec7e6b..7bbb775a9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -231,15 +231,15 @@ rustix = "0.38.31"
 wit-bindgen = { version = "0.22.0", default-features = false }
 
 # wasm-tools family:
-wasmparser = { version = "0.207.0", default-features = false }
-wat = "1.207.0"
-wast = "207.0.0"
-wasmprinter = "0.207.0"
-wasm-encoder = "0.207.0"
-wasm-smith = "0.207.0"
-wasm-mutate = "0.207.0"
-wit-parser = "0.207.0"
-wit-component = "0.207.0"
+wasmparser = { version = "0.208.1", default-features = false }
+wat = "1.208.1"
+wast = "208.0.1"
+wasmprinter = "0.208.1"
+wasm-encoder = "0.208.1"
+wasm-smith = "0.208.1"
+wasm-mutate = "0.208.1"
+wit-parser = "0.208.1"
+wit-component = "0.208.1"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
@@ -341,6 +341,7 @@ default = [
   "component-model",
   "threads",
   "gc",
+  "winch",
 
   # Enable some nice features of clap by default, but they come at a binary size
   # cost, so allow disabling this through disabling of our own `default`
diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml
index b241412b2..581104311 100644
--- a/cranelift/codegen/Cargo.toml
+++ b/cranelift/codegen/Cargo.toml
@@ -43,6 +43,7 @@ rustc-hash  = { workspace = true }
 [dev-dependencies]
 criterion = { workspace = true }
 similar = "2.1.0"
+env_logger = { workspace = true }
 
 [build-dependencies]
 cranelift-codegen-meta = { path = "meta", version = "0.109.0" }
diff --git a/cranelift/codegen/src/dominator_tree.rs b/cranelift/codegen/src/dominator_tree.rs
index c076d3c1d..12288362b 100644
--- a/cranelift/codegen/src/dominator_tree.rs
+++ b/cranelift/codegen/src/dominator_tree.rs
@@ -5,6 +5,7 @@ use crate::flowgraph::{BlockPredecessor, ControlFlowGraph};
 use crate::ir::{Block, Function, Inst, Layout, ProgramPoint};
 use crate::packed_option::PackedOption;
 use crate::timing;
+use crate::traversals::Dfs;
 use alloc::vec::Vec;
 use core::cmp;
 use core::cmp::Ordering;
@@ -14,9 +15,6 @@ use core::mem;
 /// room for modifications of the dominator tree.
 const STRIDE: u32 = 4;
 
-/// Special RPO numbers used during `compute_postorder`.
-const SEEN: u32 = 1;
-
 /// Dominator tree node. We keep one of these per block.
 #[derive(Clone, Default)]
 struct DomNode {
@@ -34,12 +32,6 @@ struct DomNode {
     idom: PackedOption<Inst>,
 }
 
-/// DFT stack state marker for computing the cfg postorder.
-enum Visit {
-    First,
-    Last,
-}
-
 /// The dominator tree for a single function.
 pub struct DominatorTree {
     nodes: SecondaryMap<Block, DomNode>,
@@ -47,8 +39,8 @@ pub struct DominatorTree {
     /// CFG post-order of all reachable blocks.
     postorder: Vec<Block>,
 
-    /// Scratch memory used by `compute_postorder()`.
-    stack: Vec<(Visit, Block)>,
+    /// Scratch traversal state used by `compute_postorder()`.
+    dfs: Dfs,
 
     valid: bool,
 }
@@ -225,7 +217,7 @@ impl DominatorTree {
         Self {
             nodes: SecondaryMap::new(),
             postorder: Vec::new(),
-            stack: Vec::new(),
+            dfs: Dfs::new(),
             valid: false,
         }
     }
@@ -236,7 +228,7 @@ impl DominatorTree {
         let mut domtree = Self {
             nodes: SecondaryMap::with_capacity(block_capacity),
             postorder: Vec::with_capacity(block_capacity),
-            stack: Vec::new(),
+            dfs: Dfs::new(),
             valid: false,
         };
         domtree.compute(func, cfg);
@@ -257,7 +249,6 @@ impl DominatorTree {
     pub fn clear(&mut self) {
         self.nodes.clear();
         self.postorder.clear();
-        debug_assert!(self.stack.is_empty());
         self.valid = false;
     }
 
@@ -276,73 +267,7 @@ impl DominatorTree {
     fn compute_postorder(&mut self, func: &Function) {
         self.clear();
         self.nodes.resize(func.dfg.num_blocks());
-
-        // This algorithm is a depth first traversal (DFT) of the control flow graph, computing a
-        // post-order of the blocks that are reachable form the entry block. A DFT post-order is not
-        // unique. The specific order we get is controlled by the order each node's children are
-        // visited.
-        //
-        // We view the CFG as a graph where each `BlockCall` value of a terminating branch
-        // instruction is an edge. A consequence of this is that we visit successor nodes in the
-        // reverse order specified by the branch instruction that terminates the basic block.
-        // (Reversed because we are using a stack to control traversal, and push the successors in
-        // the order the branch instruction specifies -- there's no good reason for this particular
-        // order.)
-        //
-        // During this algorithm only, use `rpo_number` to hold the following state:
-        //
-        //   0:    block has not yet had its first visit
-        //   SEEN: block has been visited at least once, implying that all of its successors are on
-        //         the stack
-
-        match func.layout.entry_block() {
-            Some(block) => {
-                self.stack.push((Visit::First, block));
-            }
-            None => return,
-        }
-
-        while let Some((visit, block)) = self.stack.pop() {
-            match visit {
-                Visit::First => {
-                    if self.nodes[block].rpo_number == 0 {
-                        // This is the first time we pop the block, so we need to scan its
-                        // successors and then revisit it.
-                        self.nodes[block].rpo_number = SEEN;
-                        self.stack.push((Visit::Last, block));
-                        if let Some(inst) = func.stencil.layout.last_inst(block) {
-                            // Heuristic: chase the children in reverse. This puts the first
-                            // successor block first in the postorder, all other things being
-                            // equal, which tends to prioritize loop backedges over out-edges,
-                            // putting the edge-block closer to the loop body and minimizing
-                            // live-ranges in linear instruction space. This heuristic doesn't have
-                            // any effect on the computation of dominators, and is purely for other
-                            // consumers of the postorder we cache here.
-                            for block in func.stencil.dfg.insts[inst]
-                                .branch_destination(&func.stencil.dfg.jump_tables)
-                                .iter()
-                                .rev()
-                            {
-                                let succ = block.block(&func.stencil.dfg.value_lists);
-
-                                // This is purely an optimization to avoid additional iterations of
-                                // the loop, and is not required; it's merely inlining the check
-                                // from the outer conditional of this case to avoid the extra loop
-                                // iteration.
-                                if self.nodes[succ].rpo_number == 0 {
-                                    self.stack.push((Visit::First, succ))
-                                }
-                            }
-                        }
-                    }
-                }
-
-                Visit::Last => {
-                    // We've finished all this node's successors.
-                    self.postorder.push(block);
-                }
-            }
-        }
+        self.postorder.extend(self.dfs.post_order_iter(func));
     }
 
     /// Build a dominator tree from a control flow graph using Keith D. Cooper's
@@ -467,7 +392,6 @@ impl DominatorTreePreorder {
     /// Recompute this data structure to match `domtree`.
     pub fn compute(&mut self, domtree: &DominatorTree, layout: &Layout) {
         self.nodes.clear();
-        debug_assert_eq!(self.stack.len(), 0);
 
         // Step 1: Populate the child and sibling links.
         //
diff --git a/cranelift/codegen/src/lib.rs b/cranelift/codegen/src/lib.rs
index 31e4206a6..017122a8c 100644
--- a/cranelift/codegen/src/lib.rs
+++ b/cranelift/codegen/src/lib.rs
@@ -49,6 +49,7 @@ pub mod loop_analysis;
 pub mod print_errors;
 pub mod settings;
 pub mod timing;
+pub mod traversals;
 pub mod verifier;
 pub mod write;
 
diff --git a/cranelift/codegen/src/machinst/lower.rs b/cranelift/codegen/src/machinst/lower.rs
index f74faa6eb..5ebbb24bd 100644
--- a/cranelift/codegen/src/machinst/lower.rs
+++ b/cranelift/codegen/src/machinst/lower.rs
@@ -398,7 +398,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
         }
 
         // Find the sret register, if it's used.
-        let mut sret_reg = None;
+        let mut sret_param = None;
         for ret in vcode.abi().signature().returns.iter() {
             if ret.purpose == ArgumentPurpose::StructReturn {
                 let entry_bb = f.stencil.layout.entry_block().unwrap();
@@ -409,18 +409,21 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
                     .zip(vcode.abi().signature().params.iter())
                 {
                     if sig_param.purpose == ArgumentPurpose::StructReturn {
-                        let regs = value_regs[param];
-                        assert!(regs.len() == 1);
-
-                        assert!(sret_reg.is_none());
-                        sret_reg = Some(regs);
+                        assert!(sret_param.is_none());
+                        sret_param = Some(param);
                     }
                 }
 
-                assert!(sret_reg.is_some());
+                assert!(sret_param.is_some());
             }
         }
 
+        let sret_reg = sret_param.map(|param| {
+            let regs = value_regs[param];
+            assert!(regs.len() == 1);
+            regs
+        });
+
         // Compute instruction colors, find constant instructions, and find instructions with
         // side-effects, in one combined pass.
         let mut cur_color = 0;
@@ -449,7 +452,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
             block_end_colors[bb] = InstColor::new(cur_color);
         }
 
-        let value_ir_uses = Self::compute_use_states(f);
+        let value_ir_uses = Self::compute_use_states(f, sret_param);
 
         Ok(Lower {
             f,
@@ -482,7 +485,10 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
     /// Pre-analysis: compute `value_ir_uses`. See comment on
     /// `ValueUseState` for a description of what this analysis
     /// computes.
-    fn compute_use_states<'a>(f: &'a Function) -> SecondaryMap<Value, ValueUseState> {
+    fn compute_use_states<'a>(
+        f: &'a Function,
+        sret_param: Option<Value>,
+    ) -> SecondaryMap<Value, ValueUseState> {
         // We perform the analysis without recursion, so we don't
         // overflow the stack on long chains of ops in the input.
         //
@@ -502,6 +508,12 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
 
         let mut value_ir_uses = SecondaryMap::with_default(ValueUseState::Unused);
 
+        if let Some(sret_param) = sret_param {
+            // There's an implicit use of the struct-return parameter in each
+            // copy of the function epilogue, which we count here.
+            value_ir_uses[sret_param] = ValueUseState::Multiple;
+        }
+
         // Stack of iterators over Values as we do DFS to mark
         // Multiple-state subtrees. The iterator type is whatever is
         // returned by `uses` below.
diff --git a/cranelift/codegen/src/traversals.rs b/cranelift/codegen/src/traversals.rs
new file mode 100644
index 000000000..bd410e1bc
--- /dev/null
+++ b/cranelift/codegen/src/traversals.rs
@@ -0,0 +1,216 @@
+//! Traversals over the IR.
+
+use crate::ir;
+use alloc::vec::Vec;
+use core::fmt::Debug;
+use core::hash::Hash;
+use cranelift_entity::EntitySet;
+
+/// A low-level DFS traversal event: either entering or exiting the traversal of
+/// a block.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum Event {
+    /// Entering traversal of a block.
+    ///
+    /// Processing a block upon this event corresponds to a pre-order,
+    /// depth-first traversal.
+    Enter,
+
+    /// Exiting traversal of a block.
+    ///
+    /// Processing a block upon this event corresponds to a post-order,
+    /// depth-first traversal.
+    Exit,
+}
+
+/// A depth-first traversal.
+///
+/// This is a fairly low-level traversal type, and is generally intended to be
+/// used as a building block for making specific pre-order or post-order
+/// traversals for whatever problem is at hand.
+///
+/// This type may be reused multiple times across different passes or functions
+/// and will internally reuse any heap allocations its already made.
+///
+/// Traversal is not recursive.
+#[derive(Debug, Default, Clone)]
+pub struct Dfs {
+    stack: Vec<(Event, ir::Block)>,
+    seen: EntitySet<ir::Block>,
+}
+
+impl Dfs {
+    /// Construct a new depth-first traversal.
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Perform a depth-first traversal over the given function.
+    ///
+    /// Yields pairs of `(Event, ir::Block)`.
+    ///
+    /// This iterator can be used to perform either pre- or post-order
+    /// traversals, or a combination of the two.
+    pub fn iter<'a>(&'a mut self, func: &'a ir::Function) -> DfsIter<'a> {
+        self.seen.clear();
+        self.stack.clear();
+        if let Some(e) = func.layout.entry_block() {
+            self.stack.push((Event::Enter, e));
+        }
+        DfsIter { dfs: self, func }
+    }
+
+    /// Perform a pre-order traversal over the given function.
+    ///
+    /// Yields `ir::Block` items.
+    pub fn pre_order_iter<'a>(&'a mut self, func: &'a ir::Function) -> DfsPreOrderIter<'a> {
+        DfsPreOrderIter(self.iter(func))
+    }
+
+    /// Perform a post-order traversal over the given function.
+    ///
+    /// Yields `ir::Block` items.
+    pub fn post_order_iter<'a>(&'a mut self, func: &'a ir::Function) -> DfsPostOrderIter<'a> {
+        DfsPostOrderIter(self.iter(func))
+    }
+}
+
+/// An iterator that yields pairs of `(Event, ir::Block)` items as it performs a
+/// depth-first traversal over its associated function.
+pub struct DfsIter<'a> {
+    dfs: &'a mut Dfs,
+    func: &'a ir::Function,
+}
+
+impl Iterator for DfsIter<'_> {
+    type Item = (Event, ir::Block);
+
+    fn next(&mut self) -> Option<(Event, ir::Block)> {
+        let (event, block) = self.dfs.stack.pop()?;
+
+        if event == Event::Enter && self.dfs.seen.insert(block) {
+            self.dfs.stack.push((Event::Exit, block));
+            if let Some(inst) = self.func.layout.last_inst(block) {
+                self.dfs.stack.extend(
+                    self.func.dfg.insts[inst]
+                        .branch_destination(&self.func.dfg.jump_tables)
+                        .iter()
+                        // Heuristic: chase the children in reverse. This puts
+                        // the first successor block first in the postorder, all
+                        // other things being equal, which tends to prioritize
+                        // loop backedges over out-edges, putting the edge-block
+                        // closer to the loop body and minimizing live-ranges in
+                        // linear instruction space. This heuristic doesn't have
+                        // any effect on the computation of dominators, and is
+                        // purely for other consumers of the postorder we cache
+                        // here.
+                        .rev()
+                        .map(|block| block.block(&self.func.dfg.value_lists))
+                        // This is purely an optimization to avoid additional
+                        // iterations of the loop, and is not required; it's
+                        // merely inlining the check from the outer conditional
+                        // of this case to avoid the extra loop iteration. This
+                        // also avoids potential excess stack growth.
+                        .filter(|block| !self.dfs.seen.contains(*block))
+                        .map(|block| (Event::Enter, block)),
+                );
+            }
+        }
+
+        Some((event, block))
+    }
+}
+
+/// An iterator that yields `ir::Block` items during a depth-first, pre-order
+/// traversal over its associated function.
+pub struct DfsPreOrderIter<'a>(DfsIter<'a>);
+
+impl Iterator for DfsPreOrderIter<'_> {
+    type Item = ir::Block;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        loop {
+            match self.0.next()? {
+                (Event::Enter, b) => return Some(b),
+                (Event::Exit, _) => continue,
+            }
+        }
+    }
+}
+
+/// An iterator that yields `ir::Block` items during a depth-first, post-order
+/// traversal over its associated function.
+pub struct DfsPostOrderIter<'a>(DfsIter<'a>);
+
+impl Iterator for DfsPostOrderIter<'_> {
+    type Item = ir::Block;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        loop {
+            match self.0.next()? {
+                (Event::Exit, b) => return Some(b),
+                (Event::Enter, _) => continue,
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::cursor::{Cursor, FuncCursor};
+    use crate::ir::{types::I32, Function, InstBuilder, TrapCode};
+
+    #[test]
+    fn test_dfs_traversal() {
+        let _ = env_logger::try_init();
+
+        let mut func = Function::new();
+
+        let block0 = func.dfg.make_block();
+        let v0 = func.dfg.append_block_param(block0, I32);
+        let block1 = func.dfg.make_block();
+        let block2 = func.dfg.make_block();
+        let block3 = func.dfg.make_block();
+
+        let mut cur = FuncCursor::new(&mut func);
+
+        // block0(v0):
+        //   br_if v0, block2, trap_block
+        cur.insert_block(block0);
+        cur.ins().brif(v0, block2, &[], block3, &[]);
+
+        // block3:
+        //   trap user0
+        cur.insert_block(block3);
+        cur.ins().trap(TrapCode::User(0));
+
+        // block1:
+        //   v1 = iconst.i32 1
+        //   v2 = iadd v0, v1
+        //   jump block0(v2)
+        cur.insert_block(block1);
+        let v1 = cur.ins().iconst(I32, 1);
+        let v2 = cur.ins().iadd(v0, v1);
+        cur.ins().jump(block0, &[v2]);
+
+        // block2:
+        //   return v0
+        cur.insert_block(block2);
+        cur.ins().return_(&[v0]);
+
+        let mut dfs = Dfs::new();
+
+        assert_eq!(
+            dfs.iter(&func).collect::<Vec<_>>(),
+            vec![
+                (Event::Enter, block0),
+                (Event::Enter, block2),
+                (Event::Exit, block2),
+                (Event::Enter, block3),
+                (Event::Exit, block3),
+                (Event::Exit, block0)
+            ],
+        );
+    }
+}
diff --git a/cranelift/codegen/src/verifier/mod.rs b/cranelift/codegen/src/verifier/mod.rs
index 0b19ba261..c277defc5 100644
--- a/cranelift/codegen/src/verifier/mod.rs
+++ b/cranelift/codegen/src/verifier/mod.rs
@@ -1102,8 +1102,8 @@ impl<'a> Verifier<'a> {
                 return errors.fatal((
                     next_block,
                     format!(
-                        "invalid domtree, rpo_cmp_block does not says {} is greater than {}",
-                        prev_block, next_block
+                        "invalid domtree, rpo_cmp_block does not say {} is greater than {}; rpo = {:#?}",
+                        prev_block, next_block, domtree.cfg_postorder()
                     ),
                 ));
             }
diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs
index 3cbdd6c2d..365a48771 100644
--- a/cranelift/wasm/src/code_translator.rs
+++ b/cranelift/wasm/src/code_translator.rs
@@ -2544,7 +2544,15 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
             unimplemented!("GC operators not yet implemented")
         }
 
-        Operator::GlobalAtomicGet { .. } | Operator::GlobalAtomicSet { .. } => {
+        Operator::GlobalAtomicGet { .. }
+        | Operator::GlobalAtomicSet { .. }
+        | Operator::GlobalAtomicRmwAdd { .. }
+        | Operator::GlobalAtomicRmwSub { .. }
+        | Operator::GlobalAtomicRmwOr { .. }
+        | Operator::GlobalAtomicRmwXor { .. }
+        | Operator::GlobalAtomicRmwAnd { .. }
+        | Operator::GlobalAtomicRmwXchg { .. }
+        | Operator::GlobalAtomicRmwCmpxchg { .. } => {
             unimplemented!("shared-everything-threads not yet implemented")
         }
     };
diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs
index 20e60ba79..15bc960e7 100644
--- a/cranelift/wasm/src/func_translator.rs
+++ b/cranelift/wasm/src/func_translator.rs
@@ -13,7 +13,7 @@ use cranelift_codegen::entity::EntityRef;
 use cranelift_codegen::ir::{self, Block, InstBuilder, ValueLabel};
 use cranelift_codegen::timing;
 use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
-use wasmparser::{BinaryReader, FuncValidator, FunctionBody, WasmModuleResources};
+use wasmparser::{BinaryReader, FuncValidator, FunctionBody, WasmFeatures, WasmModuleResources};
 
 /// WebAssembly to Cranelift IR function translator.
 ///
@@ -68,7 +68,7 @@ impl FuncTranslator {
     ) -> WasmResult<()> {
         self.translate_body(
             validator,
-            FunctionBody::new(code_offset, code),
+            FunctionBody::new(BinaryReader::new(code, code_offset, WasmFeatures::all())),
             func,
             environ,
         )
diff --git a/cranelift/wasm/src/module_translator.rs b/cranelift/wasm/src/module_translator.rs
index 6da7d0b5b..13b8b9d50 100644
--- a/cranelift/wasm/src/module_translator.rs
+++ b/cranelift/wasm/src/module_translator.rs
@@ -3,13 +3,13 @@
 use crate::environ::ModuleEnvironment;
 use crate::sections_translator::{
     parse_data_section, parse_element_section, parse_export_section, parse_function_section,
-    parse_global_section, parse_import_section, parse_memory_section, parse_name_section,
-    parse_start_section, parse_table_section, parse_tag_section, parse_type_section,
+    parse_global_section, parse_import_section, parse_memory_section, parse_start_section,
+    parse_table_section, parse_tag_section, parse_type_section,
 };
 use crate::WasmResult;
 use cranelift_codegen::timing;
 use std::prelude::v1::*;
-use wasmparser::{NameSectionReader, Parser, Payload, Validator};
+use wasmparser::{Parser, Payload, Validator};
 
 /// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cranelift IR
 /// [`Function`](cranelift_codegen::ir::Function).
@@ -107,14 +107,6 @@ pub fn translate_module<'data>(
                 environ.reserve_passive_data(count)?;
             }
 
-            Payload::CustomSection(s) if s.name() == "name" => {
-                let result =
-                    parse_name_section(NameSectionReader::new(s.data(), s.data_offset()), environ);
-                if let Err(e) = result {
-                    log::warn!("failed to parse name section {:?}", e);
-                }
-            }
-
             Payload::CustomSection(s) => environ.custom_section(s.name(), s.data())?,
 
             other => {
diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs
index d497d8e09..1ad9d88b1 100644
--- a/cranelift/wasm/src/sections_translator.rs
+++ b/cranelift/wasm/src/sections_translator.rs
@@ -20,8 +20,8 @@ use std::vec::Vec;
 use wasmparser::{
     Data, DataKind, DataSectionReader, Element, ElementItems, ElementKind, ElementSectionReader,
     Export, ExportSectionReader, ExternalKind, FunctionSectionReader, GlobalSectionReader,
-    ImportSectionReader, MemorySectionReader, MemoryType, NameSectionReader, Naming, Operator,
-    TableSectionReader, TagSectionReader, TagType, TypeRef, TypeSectionReader,
+    ImportSectionReader, MemorySectionReader, MemoryType, Operator, TableSectionReader,
+    TagSectionReader, TagType, TypeRef, TypeSectionReader,
 };
 use wasmtime_types::ConstExpr;
 
@@ -341,49 +341,3 @@ pub fn parse_data_section<'data>(
 
     Ok(())
 }
-
-/// Parses the Name section of the wasm module.
-pub fn parse_name_section<'data>(
-    names: NameSectionReader<'data>,
-    environ: &mut dyn ModuleEnvironment<'data>,
-) -> WasmResult<()> {
-    for subsection in names {
-        match subsection? {
-            wasmparser::Name::Function(names) => {
-                for name in names {
-                    let Naming { index, name } = name?;
-                    // We reserve `u32::MAX` for our own use in cranelift-entity.
-                    if index != u32::max_value() {
-                        environ.declare_func_name(FuncIndex::from_u32(index), name);
-                    }
-                }
-            }
-            wasmparser::Name::Module { name, .. } => {
-                environ.declare_module_name(name);
-            }
-            wasmparser::Name::Local(reader) => {
-                for f in reader {
-                    let f = f?;
-                    if f.index == u32::max_value() {
-                        continue;
-                    }
-                    for name in f.names {
-                        let Naming { index, name } = name?;
-                        environ.declare_local_name(FuncIndex::from_u32(f.index), index, name)
-                    }
-                }
-            }
-            wasmparser::Name::Label(_)
-            | wasmparser::Name::Type(_)
-            | wasmparser::Name::Table(_)
-            | wasmparser::Name::Global(_)
-            | wasmparser::Name::Memory(_)
-            | wasmparser::Name::Element(_)
-            | wasmparser::Name::Data(_)
-            | wasmparser::Name::Tag(_)
-            | wasmparser::Name::Field(_)
-            | wasmparser::Name::Unknown { .. } => {}
-        }
-    }
-    Ok(())
-}
diff --git a/crates/c-api/CMakeLists.txt b/crates/c-api/CMakeLists.txt
index 2112f9b5a..a8b5098ec 100644
--- a/crates/c-api/CMakeLists.txt
+++ b/crates/c-api/CMakeLists.txt
@@ -22,6 +22,7 @@ option(WASMTIME_DISABLE_ALL_FEATURES
 
 macro(feature rust_name default)
   string(TOUPPER "wasmtime_feature_${rust_name}" cmake_name)
+  string(REPLACE "-" "_" cmake_name ${cmake_name})
   if(${default})
     if(${WASMTIME_DISABLE_ALL_FEATURES})
       set(feature_default OFF)
@@ -53,6 +54,8 @@ feature(demangle ON)
 feature(threads ON)
 feature(gc ON)
 feature(async ON)
+feature(cranelift ON)
+feature(winch ON)
 # ... if you add a line above this be sure to also change:
 #
 #   crates/c-api/include/wasmtime/conf.h.in
@@ -164,6 +167,7 @@ endif()
 set(DOXYGEN_CONF_IN ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.conf.in)
 set(DOXYGEN_CONF_OUT ${CMAKE_BINARY_DIR}/doxygen.conf)
 configure_file(${DOXYGEN_CONF_IN} ${DOXYGEN_CONF_OUT})
-add_custom_target(doc doxygen ${DOXYGEN_CONF_OUT}
+add_custom_target(doc
+    COMMAND doxygen ${DOXYGEN_CONF_OUT}
     DEPENDS ${WASMTIME_GENERATED_CONF_H} ${DOXYGEN_CONF_OUT}
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/crates/c-api/Cargo.toml b/crates/c-api/Cargo.toml
index 46336ed16..5b8a964f2 100644
--- a/crates/c-api/Cargo.toml
+++ b/crates/c-api/Cargo.toml
@@ -22,7 +22,7 @@ doctest = false
 env_logger = { workspace = true, optional = true }
 anyhow = { workspace = true }
 once_cell = { workspace = true }
-wasmtime = { workspace = true, features = ['cranelift', 'runtime', 'gc', 'std'] }
+wasmtime = { workspace = true, features = ['runtime', 'gc', 'std'] }
 wasmtime-c-api-macros = { workspace = true }
 log = { workspace = true }
 tracing = { workspace = true }
@@ -51,6 +51,8 @@ addr2line = ["wasmtime/addr2line"]
 demangle = ["wasmtime/demangle"]
 threads = ["wasmtime/threads"]
 gc = ["wasmtime/gc"]
+cranelift = ['wasmtime/cranelift']
+winch = ['wasmtime/winch']
 # ... if you add a line above this be sure to also change:
 #
 #   crates/c-api/artifact/Cargo.toml
diff --git a/crates/c-api/artifact/Cargo.toml b/crates/c-api/artifact/Cargo.toml
index d14123550..a64007cc2 100644
--- a/crates/c-api/artifact/Cargo.toml
+++ b/crates/c-api/artifact/Cargo.toml
@@ -32,6 +32,8 @@ default = [
   'demangle',
   'threads',
   'gc',
+  'cranelift',
+  'winch',
   # ... if you add a line above this be sure to also change:
   #
   #   crates/c-api/CMakeLists.txt
@@ -50,5 +52,7 @@ demangle = ["wasmtime-c-api/demangle"]
 wat = ["wasmtime-c-api/wat"]
 threads = ["wasmtime-c-api/threads"]
 gc = ["wasmtime-c-api/gc"]
+cranelift = ["wasmtime-c-api/cranelift"]
+winch = ["wasmtime-c-api/winch"]
 # ... if you add a line above this be sure to read the comment at the end of
 # `default`
diff --git a/crates/c-api/doxygen.conf.in b/crates/c-api/doxygen.conf.in
index b2a7c2998..1f6645dfd 100644
--- a/crates/c-api/doxygen.conf.in
+++ b/crates/c-api/doxygen.conf.in
@@ -864,7 +864,7 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = include
+INPUT                  = include @CMAKE_BINARY_DIR@/include
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/crates/c-api/include/wasmtime/conf.h.in b/crates/c-api/include/wasmtime/conf.h.in
index 44cbd4d87..009c00b9d 100644
--- a/crates/c-api/include/wasmtime/conf.h.in
+++ b/crates/c-api/include/wasmtime/conf.h.in
@@ -20,5 +20,11 @@
 #cmakedefine WASMTIME_FEATURE_THREADS
 #cmakedefine WASMTIME_FEATURE_GC
 #cmakedefine WASMTIME_FEATURE_ASYNC
+#cmakedefine WASMTIME_FEATURE_CRANELIFT
+#cmakedefine WASMTIME_FEATURE_WINCH
+
+#if defined(WASMTIME_FEATURE_CRANELIFT) || defined(WASMTIME_FEATURE_WINCH)
+#define WASMTIME_FEATURE_COMPILER
+#endif
 
 #endif // WASMTIME_CONF_H
diff --git a/crates/c-api/include/wasmtime/config.h b/crates/c-api/include/wasmtime/config.h
index 7c6f60b2f..0cd970ccc 100644
--- a/crates/c-api/include/wasmtime/config.h
+++ b/crates/c-api/include/wasmtime/config.h
@@ -240,6 +240,8 @@ WASMTIME_CONFIG_PROP(void, wasm_multi_memory, bool)
  */
 WASMTIME_CONFIG_PROP(void, wasm_memory64, bool)
 
+#ifdef WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Configures how JIT code will be compiled.
  *
@@ -247,6 +249,8 @@ WASMTIME_CONFIG_PROP(void, wasm_memory64, bool)
  */
 WASMTIME_CONFIG_PROP(void, strategy, wasmtime_strategy_t)
 
+#endif // WASMTIME_FEATURE_COMPILER
+
 #ifdef WASMTIME_FEATURE_PARALLEL_COMPILATION
 
 /**
@@ -260,6 +264,8 @@ WASMTIME_CONFIG_PROP(void, parallel_compilation, bool)
 
 #endif // WASMTIME_FEATURE_PARALLEL_COMPILATION
 
+#ifdef WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Configures whether Cranelift's debug verifier is enabled.
  *
@@ -292,6 +298,8 @@ WASMTIME_CONFIG_PROP(void, cranelift_nan_canonicalization, bool)
  */
 WASMTIME_CONFIG_PROP(void, cranelift_opt_level, wasmtime_opt_level_t)
 
+#endif // WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Configures the profiling strategy used for JIT code.
  *
@@ -372,6 +380,8 @@ wasmtime_config_cache_config_load(wasm_config_t *, const char *);
 
 #endif // WASMTIME_FEATURE_CACHE
 
+#ifdef WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Configures the target triple that this configuration will produce
  * machine code for.
@@ -411,6 +421,8 @@ WASM_API_EXTERN void wasmtime_config_cranelift_flag_set(wasm_config_t *,
                                                         const char *key,
                                                         const char *value);
 
+#endif // WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Configures whether, when on macOS, Mach ports are used for exception
  * handling instead of traditional Unix-based signal handling.
diff --git a/crates/c-api/include/wasmtime/module.h b/crates/c-api/include/wasmtime/module.h
index 0460798ed..286f784bd 100644
--- a/crates/c-api/include/wasmtime/module.h
+++ b/crates/c-api/include/wasmtime/module.h
@@ -27,6 +27,8 @@ extern "C" {
  */
 typedef struct wasmtime_module wasmtime_module_t;
 
+#ifdef WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Compiles a WebAssembly binary into a #wasmtime_module_t
  *
@@ -46,6 +48,8 @@ WASM_API_EXTERN wasmtime_error_t *wasmtime_module_new(wasm_engine_t *engine,
                                                       size_t wasm_len,
                                                       wasmtime_module_t **ret);
 
+#endif // WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Deletes a module.
  */
@@ -69,6 +73,8 @@ WASM_API_EXTERN void wasmtime_module_imports(const wasmtime_module_t *module,
 WASM_API_EXTERN void wasmtime_module_exports(const wasmtime_module_t *module,
                                              wasm_exporttype_vec_t *out);
 
+#ifdef WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Validate a WebAssembly binary.
  *
@@ -101,6 +107,8 @@ wasmtime_module_validate(wasm_engine_t *engine, const uint8_t *wasm,
 WASM_API_EXTERN wasmtime_error_t *
 wasmtime_module_serialize(wasmtime_module_t *module, wasm_byte_vec_t *ret);
 
+#endif // WASMTIME_FEATURE_COMPILER
+
 /**
  * \brief Build a module from serialized data.
  *
@@ -109,7 +117,7 @@ wasmtime_module_serialize(wasmtime_module_t *module, wasm_byte_vec_t *ret);
  *
  * This function is not safe to receive arbitrary user input. See the Rust
  * documentation for more information on what inputs are safe to pass in here
- * (e.g. only that of #wasmtime_module_serialize)
+ * (e.g. only that of `wasmtime_module_serialize`)
  */
 WASM_API_EXTERN wasmtime_error_t *
 wasmtime_module_deserialize(wasm_engine_t *engine, const uint8_t *bytes,
@@ -127,7 +135,7 @@ wasmtime_module_deserialize(wasm_engine_t *engine, const uint8_t *bytes,
  *
  * This function is not safe to receive arbitrary user input. See the Rust
  * documentation for more information on what inputs are safe to pass in here
- * (e.g. only that of #wasmtime_module_serialize)
+ * (e.g. only that of `wasmtime_module_serialize`)
  */
 WASM_API_EXTERN wasmtime_error_t *
 wasmtime_module_deserialize_file(wasm_engine_t *engine, const char *path,
diff --git a/crates/c-api/src/config.rs b/crates/c-api/src/config.rs
index fb93ab0d1..75d8cd5d9 100644
--- a/crates/c-api/src/config.rs
+++ b/crates/c-api/src/config.rs
@@ -138,6 +138,7 @@ pub extern "C" fn wasmtime_config_wasm_memory64_set(c: &mut wasm_config_t, enabl
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub extern "C" fn wasmtime_config_strategy_set(
     c: &mut wasm_config_t,
     strategy: wasmtime_strategy_t,
@@ -156,6 +157,7 @@ pub extern "C" fn wasmtime_config_parallel_compilation_set(c: &mut wasm_config_t
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub extern "C" fn wasmtime_config_cranelift_debug_verifier_set(
     c: &mut wasm_config_t,
     enable: bool,
@@ -164,6 +166,7 @@ pub extern "C" fn wasmtime_config_cranelift_debug_verifier_set(
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub extern "C" fn wasmtime_config_cranelift_nan_canonicalization_set(
     c: &mut wasm_config_t,
     enable: bool,
@@ -172,6 +175,7 @@ pub extern "C" fn wasmtime_config_cranelift_nan_canonicalization_set(
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub extern "C" fn wasmtime_config_cranelift_opt_level_set(
     c: &mut wasm_config_t,
     opt_level: wasmtime_opt_level_t,
@@ -251,6 +255,7 @@ pub extern "C" fn wasmtime_config_native_unwind_info_set(c: &mut wasm_config_t,
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub unsafe extern "C" fn wasmtime_config_target_set(
     c: &mut wasm_config_t,
     target: *const c_char,
@@ -265,6 +270,7 @@ pub extern "C" fn wasmtime_config_macos_use_mach_ports_set(c: &mut wasm_config_t
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub unsafe extern "C" fn wasmtime_config_cranelift_flag_enable(
     c: &mut wasm_config_t,
     flag: *const c_char,
@@ -274,6 +280,7 @@ pub unsafe extern "C" fn wasmtime_config_cranelift_flag_enable(
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub unsafe extern "C" fn wasmtime_config_cranelift_flag_set(
     c: &mut wasm_config_t,
     flag: *const c_char,
diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs
index 970e7ba27..47250fb71 100644
--- a/crates/c-api/src/module.rs
+++ b/crates/c-api/src/module.rs
@@ -29,6 +29,7 @@ pub struct wasm_shared_module_t {
 wasmtime_c_api_macros::declare_own!(wasm_shared_module_t);
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub unsafe extern "C" fn wasm_module_new(
     store: &mut wasm_store_t,
     binary: &wasm_byte_vec_t,
@@ -40,6 +41,7 @@ pub unsafe extern "C" fn wasm_module_new(
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub unsafe extern "C" fn wasm_module_validate(
     store: &mut wasm_store_t,
     binary: &wasm_byte_vec_t,
@@ -105,6 +107,7 @@ pub unsafe extern "C" fn wasm_module_obtain(
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub extern "C" fn wasm_module_serialize(module: &wasm_module_t, ret: &mut wasm_byte_vec_t) {
     if let Ok(buf) = module.module.serialize() {
         ret.set_buffer(buf);
@@ -130,6 +133,7 @@ pub struct wasmtime_module_t {
 wasmtime_c_api_macros::declare_own!(wasmtime_module_t);
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub unsafe extern "C" fn wasmtime_module_new(
     engine: &wasm_engine_t,
     wasm: *const u8,
@@ -166,6 +170,7 @@ pub extern "C" fn wasmtime_module_imports(
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub unsafe extern "C" fn wasmtime_module_validate(
     engine: &wasm_engine_t,
     wasm: *const u8,
@@ -176,6 +181,7 @@ pub unsafe extern "C" fn wasmtime_module_validate(
 }
 
 #[no_mangle]
+#[cfg(any(feature = "cranelift", feature = "winch"))]
 pub extern "C" fn wasmtime_module_serialize(
     module: &wasmtime_module_t,
     ret: &mut wasm_byte_vec_t,
diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml
index 8eb93325a..8ca3e98d6 100644
--- a/crates/environ/Cargo.toml
+++ b/crates/environ/Cargo.toml
@@ -19,7 +19,7 @@ postcard = { workspace = true }
 cpp_demangle = { version = "0.4.3", optional = true }
 cranelift-entity = { workspace = true }
 wasmtime-types = { workspace = true }
-wasmparser = { workspace = true, features = ['validate'] }
+wasmparser = { workspace = true, features = ['validate', 'serde'] }
 indexmap = { workspace = true, features = ["serde"] }
 serde = { workspace = true }
 serde_derive = { workspace = true }
diff --git a/crates/environ/src/compile/module_environ.rs b/crates/environ/src/compile/module_environ.rs
index 639883b18..111e7f094 100644
--- a/crates/environ/src/compile/module_environ.rs
+++ b/crates/environ/src/compile/module_environ.rs
@@ -19,8 +19,8 @@ use std::path::PathBuf;
 use std::sync::Arc;
 use wasmparser::{
     types::Types, CustomSectionReader, DataKind, ElementItems, ElementKind, Encoding, ExternalKind,
-    FuncToValidate, FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload, TypeRef,
-    Validator, ValidatorResources, WasmFeatures,
+    FuncToValidate, FunctionBody, KnownCustom, NameSectionReader, Naming, Operator, Parser,
+    Payload, TypeRef, Validator, ValidatorResources,
 };
 use wasmtime_types::{ConstExpr, ConstOp, ModuleInternedTypeIndex, WasmHeapTopType};
 
@@ -541,9 +541,8 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
                 self.result.debuginfo.wasm_file.code_section_offset = range.start as u64;
             }
 
-            Payload::CodeSectionEntry(mut body) => {
+            Payload::CodeSectionEntry(body) => {
                 let validator = self.validator.code_section_entry(&body)?;
-                body.allow_memarg64(self.validator.features().contains(WasmFeatures::MEMORY64));
                 let func_index =
                     self.result.code_index + self.result.module.num_imported_funcs as u32;
                 let func_index = FuncIndex::from_u32(func_index);
@@ -569,7 +568,6 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
                         });
                 }
                 self.prescan_code_section(&body)?;
-                body.allow_memarg64(self.validator.features().contains(WasmFeatures::MEMORY64));
                 self.result.function_body_inputs.push(FunctionBodyData {
                     validator,
                     body,
@@ -652,13 +650,6 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
                 // the passive count, do not reserve anything here.
             }
 
-            Payload::CustomSection(s) if s.name() == "name" => {
-                let result = self.name_section(NameSectionReader::new(s.data(), s.data_offset()));
-                if let Err(e) = result {
-                    log::warn!("failed to parse name section {:?}", e);
-                }
-            }
-
             Payload::CustomSection(s)
                 if s.name() == "webidl-bindings" || s.name() == "wasm-interface-types" =>
             {
@@ -678,7 +669,7 @@ and for re-adding support for interface types you can see this issue:
             }
 
             Payload::CustomSection(s) => {
-                self.register_dwarf_section(&s);
+                self.register_custom_section(&s);
             }
 
             // It's expected that validation will probably reject other
@@ -770,11 +761,24 @@ and for re-adding support for interface types you can see this issue:
         Ok(())
     }
 
-    fn register_dwarf_section(&mut self, section: &CustomSectionReader<'data>) {
-        let name = section.name().trim_end_matches(".dwo");
-        if !name.starts_with(".debug_") {
-            return;
+    fn register_custom_section(&mut self, section: &CustomSectionReader<'data>) {
+        match section.as_known() {
+            KnownCustom::Name(name) => {
+                let result = self.name_section(name);
+                if let Err(e) = result {
+                    log::warn!("failed to parse name section {:?}", e);
+                }
+            }
+            _ => {
+                let name = section.name().trim_end_matches(".dwo");
+                if name.starts_with(".debug_") {
+                    self.dwarf_section(name, section);
+                }
+            }
         }
+    }
+
+    fn dwarf_section(&mut self, name: &str, section: &CustomSectionReader<'data>) {
         if !self.tunables.generate_native_debuginfo && !self.tunables.parse_wasm_debuginfo {
             self.result.has_unparsed_debuginfo = true;
             return;
diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs
index 224352455..7239a7783 100644
--- a/crates/environ/src/component/types.rs
+++ b/crates/environ/src/component/types.rs
@@ -855,7 +855,10 @@ pub struct TypeVariant {
 impl Hash for TypeVariant {
     fn hash<H: Hasher>(&self, h: &mut H) {
         let TypeVariant { cases, abi, info } = self;
-        cases.as_slice().hash(h);
+        cases.len().hash(h);
+        for pair in cases {
+            pair.hash(h);
+        }
         abi.hash(h);
         info.hash(h);
     }
@@ -888,7 +891,10 @@ pub struct TypeFlags {
 impl Hash for TypeFlags {
     fn hash<H: Hasher>(&self, h: &mut H) {
         let TypeFlags { names, abi } = self;
-        names.as_slice().hash(h);
+        names.len().hash(h);
+        for name in names {
+            name.hash(h);
+        }
         abi.hash(h);
     }
 }
@@ -911,7 +917,10 @@ pub struct TypeEnum {
 impl Hash for TypeEnum {
     fn hash<H: Hasher>(&self, h: &mut H) {
         let TypeEnum { names, abi, info } = self;
-        names.as_slice().hash(h);
+        names.len().hash(h);
+        for name in names {
+            name.hash(h);
+        }
         abi.hash(h);
         info.hash(h);
     }
diff --git a/crates/environ/src/component/types_builder.rs b/crates/environ/src/component/types_builder.rs
index 0b7bb8b8d..350c481a8 100644
--- a/crates/environ/src/component/types_builder.rs
+++ b/crates/environ/src/component/types_builder.rs
@@ -517,7 +517,7 @@ impl ComponentTypesBuilder {
         self.add_tuple_type(TypeTuple { types, abi })
     }
 
-    fn flags_type(&mut self, flags: &wasmparser::map::IndexSet<KebabString>) -> TypeFlagsIndex {
+    fn flags_type(&mut self, flags: &IndexSet<KebabString>) -> TypeFlagsIndex {
         let flags = TypeFlags {
             names: flags.iter().map(|s| s.to_string()).collect(),
             abi: CanonicalAbiInfo::flags(flags.len()),
@@ -525,7 +525,7 @@ impl ComponentTypesBuilder {
         self.add_flags_type(flags)
     }
 
-    fn enum_type(&mut self, variants: &wasmparser::map::IndexSet<KebabString>) -> TypeEnumIndex {
+    fn enum_type(&mut self, variants: &IndexSet<KebabString>) -> TypeEnumIndex {
         let names = variants
             .iter()
             .map(|s| s.to_string())
diff --git a/crates/environ/src/lib.rs b/crates/environ/src/lib.rs
index ab5e2e339..5ff1eeccd 100644
--- a/crates/environ/src/lib.rs
+++ b/crates/environ/src/lib.rs
@@ -40,7 +40,7 @@ pub mod prelude {
     pub use alloc::string::{String, ToString};
     pub use alloc::vec;
     pub use alloc::vec::Vec;
-    pub use wasmparser::map::{IndexMap, IndexSet};
+    pub use wasmparser::collections::{IndexMap, IndexSet};
 }
 
 /// Convenience trait for converting `Result<T, E>` into `anyhow::Result<T>`
diff --git a/crates/wasmtime/src/runtime/vm/instance.rs b/crates/wasmtime/src/runtime/vm/instance.rs
index 7c942852e..3f817bf21 100644
--- a/crates/wasmtime/src/runtime/vm/instance.rs
+++ b/crates/wasmtime/src/runtime/vm/instance.rs
@@ -579,7 +579,7 @@ impl Instance {
     /// Specifically, it provides access to the key-value pairs, where the keys
     /// are export names, and the values are export declarations which can be
     /// resolved `lookup_by_declaration`.
-    pub fn exports(&self) -> indexmap::map::Iter<String, EntityIndex> {
+    pub fn exports(&self) -> wasmparser::collections::index_map::Iter<String, EntityIndex> {
         self.module().exports.iter()
     }
 
@@ -1359,7 +1359,7 @@ impl InstanceHandle {
     /// Specifically, it provides access to the key-value pairs, where the keys
     /// are export names, and the values are export declarations which can be
     /// resolved `lookup_by_declaration`.
-    pub fn exports(&self) -> indexmap::map::Iter<String, EntityIndex> {
+    pub fn exports(&self) -> wasmparser::collections::index_map::Iter<String, EntityIndex> {
         self.instance().exports()
     }
 
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 1b2cddce9..daf36464a 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -1538,6 +1538,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-encoder]]
+version = "0.208.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-metadata]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1580,6 +1586,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasm-metadata]]
+version = "0.208.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-mutate]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1694,6 +1706,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasmparser]]
+version = "0.208.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmprinter]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -1736,6 +1754,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wasmprinter]]
+version = "0.208.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmtime]]
 version = "18.0.2"
 when = "2024-02-28"
@@ -2192,6 +2216,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wast]]
+version = "208.0.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wat]]
 version = "1.201.0"
 when = "2024-02-27"
@@ -2234,6 +2264,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wat]]
+version = "1.208.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wiggle]]
 version = "18.0.2"
 when = "2024-02-28"
@@ -2570,6 +2606,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wit-component]]
+version = "0.208.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wit-parser]]
 version = "0.201.0"
 when = "2024-02-27"
@@ -2612,6 +2654,12 @@ when = "2024-05-07"
 user-id = 73222
 user-login = "wasmtime-publish"
 
+[[publisher.wit-parser]]
+version = "0.208.1"
+when = "2024-05-20"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.witx]]
 version = "0.9.1"
 when = "2021-06-22"


Test patch:
diff --git a/cranelift/filetests/filetests/isa/aarch64/issue-8659.clif b/cranelift/filetests/filetests/isa/aarch64/issue-8659.clif
new file mode 100644
index 000000000..d21ecf02f
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/aarch64/issue-8659.clif
@@ -0,0 +1,16 @@
+test compile precise-output
+target aarch64
+
+function u0:11(i64 sret) system_v {
+block0(v0: i64):
+    return
+}
+
+; VCode:
+; block0:
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   ret
+
diff --git a/cranelift/filetests/filetests/isa/x64/issue-8659.clif b/cranelift/filetests/filetests/isa/x64/issue-8659.clif
new file mode 100644
index 000000000..24ef5b56c
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/x64/issue-8659.clif
@@ -0,0 +1,27 @@
+test compile precise-output
+target x86_64
+
+function u0:11(i64 sret) system_v {
+block0(v0: i64):
+    return
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movq    %rdi, %rax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movq %rdi, %rax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+