Repository: bytecodealliance/wasmtime
Pull request #7948 (2024-02-15 21:00:45)

cranelift: Remove redundant dominator-tree structure
The egraph work introduced a helper for walking over the dominator tree in pre-order, but it turns out that helper already existed in the `dominator_tree` module itself, and the older version also supports constant-time dominance checks using the same trick that @cfallin suggested in #7891. So let's just use that version.

cc: @elliottt @lpereira


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 600b2e2a5..11113a9ca 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -653,7 +653,7 @@ dependencies = [
  "target-lexicon",
  "thiserror",
  "toml",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wat",
 ]
 
@@ -832,7 +832,7 @@ dependencies = [
  "serde_derive",
  "smallvec",
  "target-lexicon",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime-types",
  "wat",
 ]
@@ -2620,7 +2620,7 @@ version = "0.0.0"
 dependencies = [
  "cargo_metadata",
  "heck",
- "wit-component 0.21.0",
+ "wit-component 0.200.0",
 ]
 
 [[package]]
@@ -2930,7 +2930,7 @@ name = "verify-component-adapter"
 version = "19.0.0"
 dependencies = [
  "anyhow",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wat",
 ]
 
@@ -3021,7 +3021,7 @@ dependencies = [
  "byte-array-literals",
  "object",
  "wasi",
- "wasm-encoder",
+ "wasm-encoder 0.200.0",
  "wit-bindgen",
 ]
 
@@ -3088,6 +3088,15 @@ dependencies = [
  "leb128",
 ]
 
+[[package]]
+name = "wasm-encoder"
+version = "0.200.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e3fb0c8fbddd78aa6095b850dfeedbc7506cf5f81e633f69cf8f2333ab84b9"
+dependencies = [
+ "leb128",
+]
+
 [[package]]
 name = "wasm-metadata"
 version = "0.10.20"
@@ -3100,36 +3109,52 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "spdx",
- "wasm-encoder",
- "wasmparser",
+ "wasm-encoder 0.41.2",
+ "wasmparser 0.121.2",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.200.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b8cc0c21f46d55b0aaa419cacce1eadcf28eaebd0e1488d6a6313ee71a586"
+dependencies = [
+ "anyhow",
+ "indexmap 2.0.0",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "spdx",
+ "wasm-encoder 0.200.0",
+ "wasmparser 0.200.0",
 ]
 
 [[package]]
 name = "wasm-mutate"
-version = "0.2.48"
+version = "0.200.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66190ebefee2459923201c7683489eda894e703625b0c91324b1186b830410e0"
+checksum = "940164dfefc300dbe5e2c310d7b67e9a502a03083bcec9fcbc8e852b79214135"
 dependencies = [
  "egg",
  "log",
  "rand",
  "thiserror",
- "wasm-encoder",
- "wasmparser",
+ "wasm-encoder 0.200.0",
+ "wasmparser 0.200.0",
 ]
 
 [[package]]
 name = "wasm-smith"
-version = "0.16.1"
+version = "0.200.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9411792ad7c3f356ec2b31685d6553e4e8c20ed9efa192c24ab7f7560c290598"
+checksum = "4c94f72d4693c627c5d0b73b95f24f73566a610fd748b57216ea90f400d09f55"
 dependencies = [
  "anyhow",
  "arbitrary",
  "flagset",
  "indexmap 2.0.0",
  "leb128",
- "wasm-encoder",
+ "wasm-encoder 0.200.0",
 ]
 
 [[package]]
@@ -3183,6 +3208,17 @@ dependencies = [
  "semver",
 ]
 
+[[package]]
+name = "wasmparser"
+version = "0.200.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a03f65ac876612140c57ff6c3b8fe4990067cce97c2cfdb07368a3cc3354b062"
+dependencies = [
+ "bitflags 2.4.1",
+ "indexmap 2.0.0",
+ "semver",
+]
+
 [[package]]
 name = "wasmparser-nostd"
 version = "0.100.1"
@@ -3194,12 +3230,12 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.2.80"
+version = "0.200.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60e73986a6b7fdfedb7c5bf9e7eb71135486507c8fbc4c0c42cffcb6532988b7"
+checksum = "2bd153b0dce4e727565ccb3bd41b0bd2b62b2b9b6b1057d1cdb7fe8e0f3e06ab"
 dependencies = [
  "anyhow",
- "wasmparser",
+ "wasmparser 0.200.0",
 ]
 
 [[package]]
@@ -3230,8 +3266,8 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "wasi-common",
- "wasm-encoder",
- "wasmparser",
+ "wasm-encoder 0.200.0",
+ "wasmparser 0.200.0",
  "wasmtime-cache",
  "wasmtime-component-macro",
  "wasmtime-component-util",
@@ -3362,7 +3398,7 @@ dependencies = [
  "tracing",
  "walkdir",
  "wasi-common",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime",
  "wasmtime-cache",
  "wasmtime-cli-flags",
@@ -3376,10 +3412,10 @@ dependencies = [
  "wasmtime-wasi-nn",
  "wasmtime-wasi-threads",
  "wasmtime-wast",
- "wast 71.0.1",
+ "wast 200.0.0",
  "wat",
  "windows-sys 0.52.0",
- "wit-component 0.21.0",
+ "wit-component 0.200.0",
 ]
 
 [[package]]
@@ -3408,7 +3444,7 @@ dependencies = [
  "wasmtime",
  "wasmtime-component-util",
  "wasmtime-wit-bindgen",
- "wit-parser 0.14.0",
+ "wit-parser 0.200.0",
 ]
 
 [[package]]
@@ -3432,7 +3468,7 @@ dependencies = [
  "object",
  "target-lexicon",
  "thiserror",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime-cranelift-shared",
  "wasmtime-environ",
  "wasmtime-versioned-export-macros",
@@ -3471,8 +3507,8 @@ dependencies = [
  "serde_derive",
  "target-lexicon",
  "thiserror",
- "wasm-encoder",
- "wasmparser",
+ "wasm-encoder 0.200.0",
+ "wasmparser 0.200.0",
  "wasmprinter",
  "wasmtime-component-util",
  "wasmtime-types",
@@ -3487,7 +3523,7 @@ dependencies = [
  "component-fuzz-util",
  "env_logger",
  "libfuzzer-sys",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmprinter",
  "wasmtime-environ",
  "wat",
@@ -3544,7 +3580,7 @@ dependencies = [
  "rand",
  "smallvec",
  "target-lexicon",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime",
  "wasmtime-fuzzing",
 ]
@@ -3564,12 +3600,12 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "v8",
- "wasm-encoder",
+ "wasm-encoder 0.200.0",
  "wasm-mutate",
  "wasm-smith",
  "wasm-spec-interpreter",
  "wasmi",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmprinter",
  "wasmtime",
  "wasmtime-wast",
@@ -3616,7 +3652,7 @@ dependencies = [
  "rand",
  "rustix",
  "sptr",
- "wasm-encoder",
+ "wasm-encoder 0.200.0",
  "wasmtime-asm-macros",
  "wasmtime-environ",
  "wasmtime-fiber",
@@ -3634,7 +3670,7 @@ dependencies = [
  "serde",
  "serde_derive",
  "thiserror",
- "wasmparser",
+ "wasmparser 0.200.0",
 ]
 
 [[package]]
@@ -3742,7 +3778,7 @@ dependencies = [
  "anyhow",
  "log",
  "wasmtime",
- "wast 71.0.1",
+ "wast 200.0.0",
 ]
 
 [[package]]
@@ -3754,7 +3790,7 @@ dependencies = [
  "gimli",
  "object",
  "target-lexicon",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime-cranelift-shared",
  "wasmtime-environ",
  "winch-codegen",
@@ -3767,7 +3803,7 @@ dependencies = [
  "anyhow",
  "heck",
  "indexmap 2.0.0",
- "wit-parser 0.14.0",
+ "wit-parser 0.200.0",
 ]
 
 [[package]]
@@ -3785,24 +3821,24 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "71.0.1"
+version = "200.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "647c3ac4354da32688537e8fc4d2fe6c578df51896298cb64727d98088a1fd26"
+checksum = "d1810d14e6b03ebb8fb05eef4009ad5749c989b65197d83bce7de7172ed91366"
 dependencies = [
  "bumpalo",
  "leb128",
  "memchr",
  "unicode-width",
- "wasm-encoder",
+ "wasm-encoder 0.200.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.0.88"
+version = "1.200.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b69c36f634411568a2c6d24828b674961e37ea03340fe1d605c337ed8162d901"
+checksum = "776cbd10e217f83869beaa3f40e312bb9e91d5eee29bbf6f560db1261b6a4c3d"
 dependencies = [
- "wast 71.0.1",
+ "wast 200.0.0",
 ]
 
 [[package]]
@@ -3927,7 +3963,7 @@ dependencies = [
  "regalloc2",
  "smallvec",
  "target-lexicon",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime-environ",
 ]
 
@@ -3943,7 +3979,7 @@ dependencies = [
  "similar",
  "target-lexicon",
  "toml",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime-environ",
  "wat",
  "winch-codegen",
@@ -3973,7 +4009,7 @@ dependencies = [
  "similar",
  "target-lexicon",
  "toml",
- "wasmparser",
+ "wasmparser 0.200.0",
  "wasmtime-environ",
  "wat",
  "winch-codegen",
@@ -4170,7 +4206,7 @@ checksum = "c6a691b95d07cc4e7f7aa259b480f7f0208c4ded49406fd4f8bfd5a5a61c5db1"
 dependencies = [
  "anyhow",
  "heck",
- "wasm-metadata",
+ "wasm-metadata 0.10.20",
  "wit-bindgen-core",
  "wit-component 0.20.1",
 ]
@@ -4203,17 +4239,17 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
+ "wasm-encoder 0.41.2",
+ "wasm-metadata 0.10.20",
+ "wasmparser 0.121.2",
  "wit-parser 0.13.1",
 ]
 
 [[package]]
 name = "wit-component"
-version = "0.21.0"
+version = "0.200.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be60cd1b2ff7919305301d0c27528d4867bd793afe890ba3837743da9655d91b"
+checksum = "39979723340baea490b87b11b2abae05f149d86f2b55c18d41d78a2a2b284c16"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -4222,10 +4258,10 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser 0.14.0",
+ "wasm-encoder 0.200.0",
+ "wasm-metadata 0.200.0",
+ "wasmparser 0.200.0",
+ "wit-parser 0.200.0",
 ]
 
 [[package]]
@@ -4247,9 +4283,9 @@ dependencies = [
 
 [[package]]
 name = "wit-parser"
-version = "0.14.0"
+version = "0.200.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ee4ad7310367bf272507c0c8e0c74a80b4ed586b833f7c7ca0b7588f686f11a"
+checksum = "7f717576b37f01c15696bda7f6f13868367b9c5913485f9f0ec8e59fd28c8e13"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -4260,7 +4296,7 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser",
+ "wasmparser 0.200.0",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index c5802b707..b6b88a759 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -234,15 +234,15 @@ rustix = "0.38.31"
 wit-bindgen = { version = "0.17.0", default-features = false }
 
 # wasm-tools family:
-wasmparser = "0.121.2"
-wat = "1.0.88"
-wast = "71.0.1"
-wasmprinter = "0.2.80"
-wasm-encoder = "0.41.2"
-wasm-smith = "0.16.1"
-wasm-mutate = "0.2.48"
-wit-parser = "0.14.0"
-wit-component = "0.21.0"
+wasmparser = "0.200.0"
+wat = "1.200.0"
+wast = "200.0.0"
+wasmprinter = "0.200.0"
+wasm-encoder = "0.200.0"
+wasm-smith = "0.200.0"
+wasm-mutate = "0.200.0"
+wit-parser = "0.200.0"
+wit-component = "0.200.0"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
diff --git a/cranelift/codegen/src/egraph.rs b/cranelift/codegen/src/egraph.rs
index 32f670287..fd8974395 100644
--- a/cranelift/codegen/src/egraph.rs
+++ b/cranelift/codegen/src/egraph.rs
@@ -3,8 +3,7 @@
 use crate::alias_analysis::{AliasAnalysis, LastStores};
 use crate::ctxhash::{CtxEq, CtxHash, CtxHashMap};
 use crate::cursor::{Cursor, CursorPosition, FuncCursor};
-use crate::dominator_tree::DominatorTree;
-use crate::egraph::domtree::DomTreeWithChildren;
+use crate::dominator_tree::{DominatorTree, DominatorTreePreorder};
 use crate::egraph::elaborate::Elaborator;
 use crate::fx::FxHashSet;
 use crate::inst_predicates::{is_mergeable_for_egraph, is_pure_for_egraph};
@@ -22,7 +21,6 @@ use smallvec::SmallVec;
 use std::hash::Hasher;
 
 mod cost;
-mod domtree;
 mod elaborate;
 
 /// Pass over a Function that does the whole aegraph thing.
@@ -46,14 +44,12 @@ mod elaborate;
 pub struct EgraphPass<'a> {
     /// The function we're operating on.
     func: &'a mut Function,
-    /// Dominator tree, used for elaboration pass.
-    domtree: &'a DominatorTree,
+    /// Dominator tree for the CFG, used to visit blocks in pre-order
+    /// so we see value definitions before their uses, and also used for
+    /// O(1) dominance checks.
+    domtree: DominatorTreePreorder,
     /// Alias analysis, used during optimization.
     alias_analysis: &'a mut AliasAnalysis<'a>,
-    /// "Domtree with children": like `domtree`, but with an explicit
-    /// list of children, complementing the parent pointers stored
-    /// in `domtree`.
-    domtree_children: DomTreeWithChildren,
     /// Loop analysis results, used for built-in LICM during
     /// elaboration.
     loop_analysis: &'a LoopAnalysis,
@@ -401,16 +397,16 @@ impl<'a> EgraphPass<'a> {
     /// Create a new EgraphPass.
     pub fn new(
         func: &'a mut Function,
-        domtree: &'a DominatorTree,
+        raw_domtree: &'a DominatorTree,
         loop_analysis: &'a LoopAnalysis,
         alias_analysis: &'a mut AliasAnalysis<'a>,
     ) -> Self {
         let num_values = func.dfg.num_values();
-        let domtree_children = DomTreeWithChildren::new(func, domtree);
+        let mut domtree = DominatorTreePreorder::new();
+        domtree.compute(raw_domtree, &func.layout);
         Self {
             func,
             domtree,
-            domtree_children,
             loop_analysis,
             alias_analysis,
             stats: Stats::default(),
@@ -497,7 +493,7 @@ impl<'a> EgraphPass<'a> {
 
         // In domtree preorder, visit blocks. (TODO: factor out an
         // iterator from this and elaborator.)
-        let root = self.domtree_children.root();
+        let root = cursor.layout().entry_block().unwrap();
         enum StackEntry {
             Visit(Block),
             Pop,
@@ -509,8 +505,7 @@ impl<'a> EgraphPass<'a> {
                     // We popped this block; push children
                     // immediately, then process this block.
                     block_stack.push(StackEntry::Pop);
-                    block_stack
-                        .extend(self.domtree_children.children(block).map(StackEntry::Visit));
+                    block_stack.extend(self.domtree.children(block).map(StackEntry::Visit));
                     effectful_gvn_map.increment_depth();
 
                     trace!("Processing block {}", block);
@@ -615,8 +610,7 @@ impl<'a> EgraphPass<'a> {
     fn elaborate(&mut self) {
         let mut elaborator = Elaborator::new(
             self.func,
-            self.domtree,
-            &self.domtree_children,
+            &self.domtree,
             self.loop_analysis,
             &mut self.remat_values,
             &mut self.stats,
diff --git a/cranelift/codegen/src/egraph/domtree.rs b/cranelift/codegen/src/egraph/domtree.rs
deleted file mode 100644
index aa76f6781..000000000
--- a/cranelift/codegen/src/egraph/domtree.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-//! Extended domtree with various traversal support.
-
-use crate::dominator_tree::DominatorTree;
-use crate::ir::{Block, Function};
-use cranelift_entity::{packed_option::PackedOption, SecondaryMap};
-
-#[derive(Clone, Debug)]
-/// Like a [`DominatorTree`], but with an explicit list of children,
-/// rather than parent pointers.
-pub(crate) struct DomTreeWithChildren {
-    nodes: SecondaryMap<Block, DomTreeNode>,
-    root: Block,
-}
-
-#[derive(Clone, Copy, Debug, Default)]
-struct DomTreeNode {
-    /// Points to the first child of the node, and implicitly to an entire
-    /// linked list of the children.
-    children: PackedOption<Block>,
-    /// Points to the next sibling, if any.
-    next: PackedOption<Block>,
-}
-
-impl DomTreeWithChildren {
-    pub(crate) fn new(func: &Function, domtree: &DominatorTree) -> DomTreeWithChildren {
-        let mut nodes: SecondaryMap<Block, DomTreeNode> =
-            SecondaryMap::with_capacity(func.dfg.num_blocks());
-
-        for block in func.layout.blocks() {
-            let Some(idom_inst) = domtree.idom(block) else {
-                continue;
-            };
-            let idom = func
-                .layout
-                .inst_block(idom_inst)
-                .expect("Dominating instruction should be part of a block");
-
-            // Insert at the front of nodes[idom].children
-            nodes[block].next = nodes[idom].children;
-            nodes[idom].children = block.into();
-        }
-
-        let root = func.layout.entry_block().unwrap();
-
-        Self { nodes, root }
-    }
-
-    pub(crate) fn root(&self) -> Block {
-        self.root
-    }
-
-    pub(crate) fn children<'a>(&'a self, block: Block) -> DomTreeChildIter<'a> {
-        let block = self.nodes[block].children;
-        DomTreeChildIter {
-            domtree: self,
-            block,
-        }
-    }
-}
-
-pub(crate) struct DomTreeChildIter<'a> {
-    domtree: &'a DomTreeWithChildren,
-    block: PackedOption<Block>,
-}
-
-impl<'a> Iterator for DomTreeChildIter<'a> {
-    type Item = Block;
-    fn next(&mut self) -> Option<Block> {
-        self.block.expand().map(|block| {
-            self.block = self.domtree.nodes[block].next;
-            block
-        })
-    }
-}
diff --git a/cranelift/codegen/src/egraph/elaborate.rs b/cranelift/codegen/src/egraph/elaborate.rs
index f2d02d0f6..0e3ca2859 100644
--- a/cranelift/codegen/src/egraph/elaborate.rs
+++ b/cranelift/codegen/src/egraph/elaborate.rs
@@ -2,9 +2,8 @@
 //! in CFG nodes.
 
 use super::cost::Cost;
-use super::domtree::DomTreeWithChildren;
 use super::Stats;
-use crate::dominator_tree::DominatorTree;
+use crate::dominator_tree::DominatorTreePreorder;
 use crate::fx::{FxHashMap, FxHashSet};
 use crate::hash_map::Entry as HashEntry;
 use crate::inst_predicates::is_pure_for_egraph;
@@ -18,8 +17,7 @@ use smallvec::{smallvec, SmallVec};
 
 pub(crate) struct Elaborator<'a> {
     func: &'a mut Function,
-    domtree: &'a DominatorTree,
-    domtree_children: &'a DomTreeWithChildren,
+    domtree: &'a DominatorTreePreorder,
     loop_analysis: &'a LoopAnalysis,
     /// Map from Value that is produced by a pure Inst (and was thus
     /// not in the side-effecting skeleton) to the value produced by
@@ -137,8 +135,7 @@ enum BlockStackEntry {
 impl<'a> Elaborator<'a> {
     pub(crate) fn new(
         func: &'a mut Function,
-        domtree: &'a DominatorTree,
-        domtree_children: &'a DomTreeWithChildren,
+        domtree: &'a DominatorTreePreorder,
         loop_analysis: &'a LoopAnalysis,
         remat_values: &'a FxHashSet<Value>,
         stats: &'a mut Stats,
@@ -150,7 +147,6 @@ impl<'a> Elaborator<'a> {
         Self {
             func,
             domtree,
-            domtree_children,
             loop_analysis,
             value_to_elaborated_value: ScopedHashMap::with_capacity(num_values),
             value_to_best_value,
@@ -557,11 +553,7 @@ impl<'a> Elaborator<'a> {
                             let data = &self.loop_stack[loop_hoist_level];
                             // `data.hoist_block` should dominate `before`'s block.
                             let before_block = self.func.layout.inst_block(before).unwrap();
-                            debug_assert!(self.domtree.dominates(
-                                data.hoist_block,
-                                before_block,
-                                &self.func.layout
-                            ));
+                            debug_assert!(self.domtree.dominates(data.hoist_block, before_block));
                             // Determine the instruction at which we
                             // insert in `data.hoist_block`.
                             let before = self.func.layout.last_inst(data.hoist_block).unwrap();
@@ -762,10 +754,9 @@ impl<'a> Elaborator<'a> {
         }
     }
 
-    fn elaborate_domtree(&mut self, domtree: &DomTreeWithChildren) {
-        let root = domtree.root();
+    fn elaborate_domtree(&mut self, domtree: &DominatorTreePreorder) {
         self.block_stack.push(BlockStackEntry::Elaborate {
-            block: root,
+            block: self.func.layout.entry_block().unwrap(),
             idom: None,
         });
 
@@ -808,7 +799,7 @@ impl<'a> Elaborator<'a> {
         self.stats.elaborate_func += 1;
         self.stats.elaborate_func_pre_insts += self.func.dfg.num_insts() as u64;
         self.compute_best_values();
-        self.elaborate_domtree(&self.domtree_children);
+        self.elaborate_domtree(&self.domtree);
         self.stats.elaborate_func_post_insts += self.func.dfg.num_insts() as u64;
     }
 }
diff --git a/cranelift/codegen/src/lib.rs b/cranelift/codegen/src/lib.rs
index 1908bdd3d..72b67f129 100644
--- a/cranelift/codegen/src/lib.rs
+++ b/cranelift/codegen/src/lib.rs
@@ -59,8 +59,8 @@ pub use crate::machinst::buffer::{
 };
 pub use crate::machinst::{
     CompiledCode, Final, MachBuffer, MachBufferFinalized, MachInst, MachInstEmit,
-    MachInstEmitState, MachLabel, RealReg, Reg, TextSectionBuilder, VCodeConstantData,
-    VCodeConstants, Writable,
+    MachInstEmitState, MachLabel, RealReg, Reg, RelocDistance, TextSectionBuilder,
+    VCodeConstantData, VCodeConstants, Writable,
 };
 
 mod alias_analysis;
diff --git a/crates/wasi-http/wit/deps/io/poll.wit b/crates/wasi-http/wit/deps/io/poll.wit
index ddc67f8b7..8139064c3 100644
--- a/crates/wasi-http/wit/deps/io/poll.wit
+++ b/crates/wasi-http/wit/deps/io/poll.wit
@@ -27,8 +27,9 @@ interface poll {
     /// The result `list<u32>` contains one or more indices of handles in the
     /// argument list that is ready for I/O.
     ///
-    /// If the list contains more elements than can be indexed with a `u32`
-    /// value, this function traps.
+    /// This function traps if either:
+    /// - the list is empty, or:
+    /// - the list contains more elements than can be indexed with a `u32` value.
     ///
     /// A timeout can be implemented by adding a pollable from the
     /// wasi-clocks API to the list.
diff --git a/crates/wasi/src/preview2/poll.rs b/crates/wasi/src/preview2/poll.rs
index 64be2420f..139d9c180 100644
--- a/crates/wasi/src/preview2/poll.rs
+++ b/crates/wasi/src/preview2/poll.rs
@@ -1,5 +1,5 @@
 use crate::preview2::{bindings::io::poll, WasiView};
-use anyhow::Result;
+use anyhow::{anyhow, Result};
 use std::any::Any;
 use std::collections::HashMap;
 use std::future::Future;
@@ -68,6 +68,10 @@ impl<T: WasiView> poll::Host for T {
     async fn poll(&mut self, pollables: Vec<Resource<Pollable>>) -> Result<Vec<u32>> {
         type ReadylistIndex = u32;
 
+        if pollables.is_empty() {
+            return Err(anyhow!("empty poll list"));
+        }
+
         let table = self.table();
 
         let mut table_futures: HashMap<u32, (MakeFuture, Vec<ReadylistIndex>)> = HashMap::new();
diff --git a/crates/wasi/wit/deps/io/poll.wit b/crates/wasi/wit/deps/io/poll.wit
index ddc67f8b7..8139064c3 100644
--- a/crates/wasi/wit/deps/io/poll.wit
+++ b/crates/wasi/wit/deps/io/poll.wit
@@ -27,8 +27,9 @@ interface poll {
     /// The result `list<u32>` contains one or more indices of handles in the
     /// argument list that is ready for I/O.
     ///
-    /// If the list contains more elements than can be indexed with a `u32`
-    /// value, this function traps.
+    /// This function traps if either:
+    /// - the list is empty, or:
+    /// - the list contains more elements than can be indexed with a `u32` value.
     ///
     /// A timeout can be implemented by adding a pollable from the
     /// wasi-clocks API to the list.
diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml
index 44c8bf49e..7032d5f4c 100644
--- a/supply-chain/audits.toml
+++ b/supply-chain/audits.toml
@@ -3552,12 +3552,60 @@ user-id = 1 # Alex Crichton (alexcrichton)
 start = "2019-03-04"
 end = "2024-07-14"
 
+[[trusted.wasm-encoder]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
+[[trusted.wasm-metadata]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
+[[trusted.wasm-mutate]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
+[[trusted.wasm-smith]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
+[[trusted.wasmparser]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
+[[trusted.wasmprinter]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
 [[trusted.wasmtime-wmemcheck]]
 criteria = "safe-to-deploy"
 user-id = 73222 # wasmtime-publish
 start = "2023-09-20"
 end = "2024-09-27"
 
+[[trusted.wast]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
+[[trusted.wat]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
 [[trusted.winapi-util]]
 criteria = "safe-to-deploy"
 user-id = 189 # Andrew Gallant (BurntSushi)
@@ -3642,8 +3690,20 @@ user-id = 6825 # Dan Gohman (sunfishcode)
 start = "2019-08-20"
 end = "2024-07-14"
 
+[[trusted.wit-component]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
+
 [[trusted.wit-parser]]
 criteria = "safe-to-deploy"
 user-id = 696 # Nick Fitzgerald (fitzgen)
 start = "2023-10-12"
 end = "2024-10-17"
+
+[[trusted.wit-parser]]
+criteria = "safe-to-deploy"
+user-id = 73222 # wasmtime-publish
+start = "2024-02-15"
+end = "2025-02-16"
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 25456a8db..5b08d0fbe 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -842,6 +842,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-encoder]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-metadata]]
 version = "0.10.20"
 when = "2024-02-12"
@@ -849,6 +855,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-metadata]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-mutate]]
 version = "0.2.48"
 when = "2024-02-12"
@@ -856,6 +868,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-mutate]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasm-smith]]
 version = "0.16.1"
 when = "2024-02-12"
@@ -863,6 +881,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-smith]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmparser]]
 version = "0.121.2"
 when = "2024-02-12"
@@ -870,6 +894,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmparser]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmprinter]]
 version = "0.2.80"
 when = "2024-02-12"
@@ -877,6 +907,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmprinter]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wasmtime]]
 version = "17.0.1"
 when = "2024-02-07"
@@ -1028,6 +1064,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wast]]
+version = "200.0.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wat]]
 version = "1.0.88"
 when = "2024-02-12"
@@ -1035,6 +1077,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wat]]
+version = "1.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wiggle]]
 version = "17.0.1"
 when = "2024-02-07"
@@ -1262,6 +1310,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-component]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[publisher.wit-parser]]
 version = "0.13.1"
 when = "2024-01-09"
@@ -1276,6 +1330,12 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-parser]]
+version = "0.200.0"
+when = "2024-02-15"
+user-id = 73222
+user-login = "wasmtime-publish"
+
 [[audits.embark-studios.wildcard-audits.spdx]]
 who = "Jake Shadle <opensource@embark-studios.com>"
 criteria = "safe-to-deploy"
diff --git a/winch/codegen/src/isa/x64/asm.rs b/winch/codegen/src/isa/x64/asm.rs
index 752feb621..a535407b7 100644
--- a/winch/codegen/src/isa/x64/asm.rs
+++ b/winch/codegen/src/isa/x64/asm.rs
@@ -22,7 +22,7 @@ use cranelift_codegen::{
         },
     },
     settings, Final, MachBuffer, MachBufferFinalized, MachInstEmit, MachInstEmitState, MachLabel,
-    VCodeConstantData, VCodeConstants, Writable,
+    RelocDistance, VCodeConstantData, VCodeConstants, Writable,
 };
 
 use super::address::Address;
@@ -1261,13 +1261,23 @@ impl Assembler {
     }
 
     /// Emit a call to a well-known libcall.
-    pub fn call_with_lib(&mut self, lib: LibCall) {
+    pub fn call_with_lib(&mut self, lib: LibCall, dst: Reg) {
         let dest = ExternalName::LibCall(lib);
-        self.emit(Inst::CallKnown {
-            dest,
-            opcode: Opcode::Call,
-            info: None,
+
+        // `use_colocated_libcalls` is never `true` from within Wasmtime,
+        // so always require loading the libcall to a register and use
+        // a `Far` relocation distance to ensure the right relocation when
+        // emitting to binary.
+        //
+        // See [wasmtime::engine::Engine::check_compatible_with_shared_flag] and
+        // [wasmtime_cranelift_shared::obj::ModuleTextBuilder::apend_func]
+        self.emit(Inst::LoadExtName {
+            dst: Writable::from_reg(dst.into()),
+            name: Box::new(dest),
+            offset: 0,
+            distance: RelocDistance::Far,
         });
+        self.call_with_reg(dst);
     }
 
     /// Emits a conditional jump to the given label.
diff --git a/winch/codegen/src/isa/x64/masm.rs b/winch/codegen/src/isa/x64/masm.rs
index fe919f0f5..ec98a4165 100644
--- a/winch/codegen/src/isa/x64/masm.rs
+++ b/winch/codegen/src/isa/x64/masm.rs
@@ -422,7 +422,7 @@ impl Masm for MacroAssembler {
         match callee {
             CalleeKind::Indirect(reg) => self.asm.call_with_reg(reg),
             CalleeKind::Direct(idx) => self.asm.call_with_index(idx),
-            CalleeKind::Known(lib) => self.asm.call_with_lib(lib),
+            CalleeKind::Known(lib) => self.asm.call_with_lib(lib, regs::scratch()),
         };
         total_stack
     }


Test patch:
diff --git a/crates/test-programs/src/bin/preview2_pollable_correct.rs b/crates/test-programs/src/bin/preview2_pollable_correct.rs
new file mode 100644
index 000000000..3ecc8a8e7
--- /dev/null
+++ b/crates/test-programs/src/bin/preview2_pollable_correct.rs
@@ -0,0 +1,12 @@
+use test_programs::wasi::cli::stdin;
+
+fn main() {
+    let stdin = stdin::get_stdin();
+    let p1 = stdin.subscribe();
+    let p2 = stdin.subscribe();
+
+    // Should work:
+    // - Exactly the same pollable passed in multiple times.
+    // - Distinct pollables for the same backing resource (stdin in this case).
+    test_programs::wasi::io::poll::poll(&[&p1, &p2, &p1, &p2]);
+}
diff --git a/crates/test-programs/src/bin/preview2_pollable_traps.rs b/crates/test-programs/src/bin/preview2_pollable_traps.rs
new file mode 100644
index 000000000..55e61a5c6
--- /dev/null
+++ b/crates/test-programs/src/bin/preview2_pollable_traps.rs
@@ -0,0 +1,4 @@
+fn main() {
+    // Polling an empty list should trap:
+    test_programs::wasi::io::poll::poll(&[]);
+}
diff --git a/crates/wasi/tests/all/async_.rs b/crates/wasi/tests/all/async_.rs
index 1aaabe0d5..063a23b03 100644
--- a/crates/wasi/tests/all/async_.rs
+++ b/crates/wasi/tests/all/async_.rs
@@ -359,6 +359,22 @@ async fn preview2_stream_pollable_traps() {
     )
 }
 #[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview2_pollable_correct() {
+    run(PREVIEW2_POLLABLE_CORRECT_COMPONENT, false)
+        .await
+        .unwrap()
+}
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview2_pollable_traps() {
+    let e = run(PREVIEW2_POLLABLE_TRAPS_COMPONENT, false)
+        .await
+        .unwrap_err();
+    assert_eq!(
+        format!("{}", e.source().expect("trap source")),
+        "empty poll list"
+    )
+}
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
 async fn preview2_adapter_badfd() {
     run(PREVIEW2_ADAPTER_BADFD_COMPONENT, false).await.unwrap()
 }
diff --git a/crates/wasi/tests/all/sync.rs b/crates/wasi/tests/all/sync.rs
index c12454643..d0446c444 100644
--- a/crates/wasi/tests/all/sync.rs
+++ b/crates/wasi/tests/all/sync.rs
@@ -298,6 +298,18 @@ fn preview2_stream_pollable_traps() {
     )
 }
 #[test_log::test]
+fn preview2_pollable_correct() {
+    run(PREVIEW2_POLLABLE_CORRECT_COMPONENT, false).unwrap()
+}
+#[test_log::test]
+fn preview2_pollable_traps() {
+    let e = run(PREVIEW2_POLLABLE_TRAPS_COMPONENT, false).unwrap_err();
+    assert_eq!(
+        format!("{}", e.source().expect("trap source")),
+        "empty poll list"
+    )
+}
+#[test_log::test]
 fn preview2_adapter_badfd() {
     run(PREVIEW2_ADAPTER_BADFD_COMPONENT, false).unwrap()
 }
diff --git a/tests/all/traps.rs b/tests/all/traps.rs
index 1cfc97ae6..e7f3596a2 100644
--- a/tests/all/traps.rs
+++ b/tests/all/traps.rs
@@ -307,8 +307,8 @@ fn trap_display_pretty() -> Result<()> {
     let run_func = instance.get_typed_func::<(), ()>(&mut store, "bar")?;
 
     let e = run_func.call(&mut store, ()).unwrap_err();
-    assert_eq!(
-        format!("{:?}", e),
+    let e = format!("{e:?}");
+    assert!(e.contains(
         "\
 error while executing at wasm backtrace:
     0:   0x23 - m!die
@@ -319,7 +319,7 @@ error while executing at wasm backtrace:
 Caused by:
     wasm trap: wasm `unreachable` instruction executed\
 "
-    );
+    ));
     Ok(())
 }
 
@@ -351,8 +351,8 @@ fn trap_display_multi_module() -> Result<()> {
     let bar2 = instance.get_typed_func::<(), ()>(&mut store, "bar2")?;
 
     let e = bar2.call(&mut store, ()).unwrap_err();
-    assert_eq!(
-        format!("{e:?}"),
+    let e = format!("{e:?}");
+    assert!(e.contains(
         "\
 error while executing at wasm backtrace:
     0:   0x23 - a!die
@@ -365,7 +365,7 @@ error while executing at wasm backtrace:
 Caused by:
     wasm trap: wasm `unreachable` instruction executed\
 "
-    );
+    ));
     Ok(())
 }
 
@@ -592,11 +592,10 @@ fn start_trap_pretty() -> Result<()> {
     let module = Module::new(store.engine(), wat)?;
     let e = match Instance::new(&mut store, &module, &[]) {
         Ok(_) => panic!("expected failure"),
-        Err(e) => e,
+        Err(e) => format!("{e:?}"),
     };
 
-    assert_eq!(
-        format!("{e:?}"),
+    assert!(e.contains(
         "\
 error while executing at wasm backtrace:
     0:   0x1d - m!die
@@ -607,7 +606,7 @@ error while executing at wasm backtrace:
 Caused by:
     wasm trap: wasm `unreachable` instruction executed\
 "
-    );
+    ));
     Ok(())
 }
 
@@ -800,8 +799,8 @@ fn no_hint_even_with_dwarf_info() -> Result<()> {
         "#,
     )?;
     let trap = Instance::new(&mut store, &module, &[]).unwrap_err();
-    assert_eq!(
-        format!("{trap:?}"),
+    let trap = format!("{trap:?}");
+    assert!(trap.contains(
         "\
 error while executing at wasm backtrace:
     0:   0x1a - <unknown>!start
@@ -809,7 +808,8 @@ error while executing at wasm backtrace:
 Caused by:
     wasm trap: wasm `unreachable` instruction executed\
 "
-    );
+    ));
+    assert!(!trap.contains("WASM_BACKTRACE_DETAILS"));
     Ok(())
 }
 
@@ -833,17 +833,16 @@ fn hint_with_dwarf_info() -> Result<()> {
         "#,
     )?;
     let trap = Instance::new(&mut store, &module, &[]).unwrap_err();
-    assert_eq!(
-        format!("{trap:?}"),
+    let trap = format!("{trap:?}");
+    assert!(trap.contains(
         "\
 error while executing at wasm backtrace:
     0:   0x1a - <unknown>!start
 note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
 
 Caused by:
-    wasm trap: wasm `unreachable` instruction executed\
-"
-    );
+    wasm trap: wasm `unreachable` instruction executed"
+    ));
     Ok(())
 }
 
diff --git a/winch/filetests/filetests/x64/f32_ceil/f32_ceil_param.wat b/winch/filetests/filetests/x64/f32_ceil/f32_ceil_param.wat
index dee7b1302..cf9c0b168 100644
--- a/winch/filetests/filetests/x64/f32_ceil/f32_ceil_param.wat
+++ b/winch/filetests/filetests/x64/f32_ceil/f32_ceil_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f30f1144240c         	movss	dword ptr [rsp + 0xc], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f3440f107c240c       	movss	xmm15, dword ptr [rsp + 0xc]
@@ -20,10 +20,12 @@
 ;;      	 f3440f113c24         	movss	dword ptr [rsp], xmm15
 ;;      	 4883ec0c             	sub	rsp, 0xc
 ;;      	 f30f1044240c         	movss	xmm0, dword ptr [rsp + 0xc]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c40c             	add	rsp, 0xc
 ;;      	 4883c404             	add	rsp, 4
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2	
diff --git a/winch/filetests/filetests/x64/f32_floor/f32_floor_param.wat b/winch/filetests/filetests/x64/f32_floor/f32_floor_param.wat
index 235979279..5724dacbe 100644
--- a/winch/filetests/filetests/x64/f32_floor/f32_floor_param.wat
+++ b/winch/filetests/filetests/x64/f32_floor/f32_floor_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f30f1144240c         	movss	dword ptr [rsp + 0xc], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f3440f107c240c       	movss	xmm15, dword ptr [rsp + 0xc]
@@ -20,10 +20,12 @@
 ;;      	 f3440f113c24         	movss	dword ptr [rsp], xmm15
 ;;      	 4883ec0c             	sub	rsp, 0xc
 ;;      	 f30f1044240c         	movss	xmm0, dword ptr [rsp + 0xc]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c40c             	add	rsp, 0xc
 ;;      	 4883c404             	add	rsp, 4
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2	
diff --git a/winch/filetests/filetests/x64/f32_nearest/f32_nearest_param.wat b/winch/filetests/filetests/x64/f32_nearest/f32_nearest_param.wat
index ab3f2c39e..c527b745d 100644
--- a/winch/filetests/filetests/x64/f32_nearest/f32_nearest_param.wat
+++ b/winch/filetests/filetests/x64/f32_nearest/f32_nearest_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f30f1144240c         	movss	dword ptr [rsp + 0xc], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f3440f107c240c       	movss	xmm15, dword ptr [rsp + 0xc]
@@ -20,10 +20,12 @@
 ;;      	 f3440f113c24         	movss	dword ptr [rsp], xmm15
 ;;      	 4883ec0c             	sub	rsp, 0xc
 ;;      	 f30f1044240c         	movss	xmm0, dword ptr [rsp + 0xc]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c40c             	add	rsp, 0xc
 ;;      	 4883c404             	add	rsp, 4
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2	
diff --git a/winch/filetests/filetests/x64/f32_trunc/f32_trunc_param.wat b/winch/filetests/filetests/x64/f32_trunc/f32_trunc_param.wat
index b7a36ae1f..dbe63ac49 100644
--- a/winch/filetests/filetests/x64/f32_trunc/f32_trunc_param.wat
+++ b/winch/filetests/filetests/x64/f32_trunc/f32_trunc_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f30f1144240c         	movss	dword ptr [rsp + 0xc], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f3440f107c240c       	movss	xmm15, dword ptr [rsp + 0xc]
@@ -20,10 +20,12 @@
 ;;      	 f3440f113c24         	movss	dword ptr [rsp], xmm15
 ;;      	 4883ec0c             	sub	rsp, 0xc
 ;;      	 f30f1044240c         	movss	xmm0, dword ptr [rsp + 0xc]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c40c             	add	rsp, 0xc
 ;;      	 4883c404             	add	rsp, 4
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2	
diff --git a/winch/filetests/filetests/x64/f64_ceil/f64_ceil_param.wat b/winch/filetests/filetests/x64/f64_ceil/f64_ceil_param.wat
index 7395b354c..f7b173c11 100644
--- a/winch/filetests/filetests/x64/f64_ceil/f64_ceil_param.wat
+++ b/winch/filetests/filetests/x64/f64_ceil/f64_ceil_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f20f11442408         	movsd	qword ptr [rsp + 8], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f2440f107c2408       	movsd	xmm15, qword ptr [rsp + 8]
@@ -20,10 +20,12 @@
 ;;      	 f2440f113c24         	movsd	qword ptr [rsp], xmm15
 ;;      	 4883ec08             	sub	rsp, 8
 ;;      	 f20f10442408         	movsd	xmm0, qword ptr [rsp + 8]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2	
diff --git a/winch/filetests/filetests/x64/f64_floor/f64_floor_param.wat b/winch/filetests/filetests/x64/f64_floor/f64_floor_param.wat
index 4e7c6c198..eed312b7c 100644
--- a/winch/filetests/filetests/x64/f64_floor/f64_floor_param.wat
+++ b/winch/filetests/filetests/x64/f64_floor/f64_floor_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f20f11442408         	movsd	qword ptr [rsp + 8], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f2440f107c2408       	movsd	xmm15, qword ptr [rsp + 8]
@@ -20,10 +20,12 @@
 ;;      	 f2440f113c24         	movsd	qword ptr [rsp], xmm15
 ;;      	 4883ec08             	sub	rsp, 8
 ;;      	 f20f10442408         	movsd	xmm0, qword ptr [rsp + 8]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2	
diff --git a/winch/filetests/filetests/x64/f64_nearest/f64_nearest_param.wat b/winch/filetests/filetests/x64/f64_nearest/f64_nearest_param.wat
index d4a1e0182..dbec0517b 100644
--- a/winch/filetests/filetests/x64/f64_nearest/f64_nearest_param.wat
+++ b/winch/filetests/filetests/x64/f64_nearest/f64_nearest_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f20f11442408         	movsd	qword ptr [rsp + 8], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f2440f107c2408       	movsd	xmm15, qword ptr [rsp + 8]
@@ -20,10 +20,12 @@
 ;;      	 f2440f113c24         	movsd	qword ptr [rsp], xmm15
 ;;      	 4883ec08             	sub	rsp, 8
 ;;      	 f20f10442408         	movsd	xmm0, qword ptr [rsp + 8]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2	
diff --git a/winch/filetests/filetests/x64/f64_trunc/f64_trunc_param.wat b/winch/filetests/filetests/x64/f64_trunc/f64_trunc_param.wat
index 87d9f5efb..3ba310800 100644
--- a/winch/filetests/filetests/x64/f64_trunc/f64_trunc_param.wat
+++ b/winch/filetests/filetests/x64/f64_trunc/f64_trunc_param.wat
@@ -12,7 +12,7 @@
 ;;      	 4d8b5e08             	mov	r11, qword ptr [r14 + 8]
 ;;      	 4d8b1b               	mov	r11, qword ptr [r11]
 ;;      	 4939e3               	cmp	r11, rsp
-;;      	 0f8738000000         	ja	0x50
+;;      	 0f8740000000         	ja	0x58
 ;;   18:	 f20f11442408         	movsd	qword ptr [rsp + 8], xmm0
 ;;      	 4c893424             	mov	qword ptr [rsp], r14
 ;;      	 f2440f107c2408       	movsd	xmm15, qword ptr [rsp + 8]
@@ -20,10 +20,12 @@
 ;;      	 f2440f113c24         	movsd	qword ptr [rsp], xmm15
 ;;      	 4883ec08             	sub	rsp, 8
 ;;      	 f20f10442408         	movsd	xmm0, qword ptr [rsp + 8]
-;;      	 e800000000           	call	0x42
+;;      	 49bb0000000000000000 	
+;; 				movabs	r11, 0
+;;      	 41ffd3               	call	r11
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c408             	add	rsp, 8
 ;;      	 4883c410             	add	rsp, 0x10
 ;;      	 5d                   	pop	rbp
 ;;      	 c3                   	ret	
-;;   50:	 0f0b                 	ud2	
+;;   58:	 0f0b                 	ud2