Repository: bytecodealliance/wasmtime
Pull request #5692 (2023-02-02 16:24:51)

Fix some wit-bindgen-related issues with generated bindings
More details in the commits, but some extra namespacing was added for methods and calculation of whether to generate owned or borrowed types was refactored and more specialized to Wasmtime now that it can.


Patch:
diff --git a/benches/instantiation.rs b/benches/instantiation.rs
index ae272c1fc..33a1e2f2b 100644
--- a/benches/instantiation.rs
+++ b/benches/instantiation.rs
@@ -46,7 +46,7 @@ fn bench_sequential(c: &mut Criterion, path: &Path) {
             let mut linker = Linker::new(&engine);
             wasmtime_wasi::add_to_linker(&mut linker, |cx| cx).unwrap();
             let pre = linker
-                .instantiate_pre(&mut store(&engine), &module)
+                .instantiate_pre(&module)
                 .expect("failed to pre-instantiate");
             (engine, pre)
         });
@@ -77,7 +77,7 @@ fn bench_parallel(c: &mut Criterion, path: &Path) {
             wasmtime_wasi::add_to_linker(&mut linker, |cx| cx).unwrap();
             let pre = Arc::new(
                 linker
-                    .instantiate_pre(&mut store(&engine), &module)
+                    .instantiate_pre(&module)
                     .expect("failed to pre-instantiate"),
             );
             (engine, pre)
diff --git a/crates/c-api/include/wasmtime/linker.h b/crates/c-api/include/wasmtime/linker.h
index edd52442d..453ef73d6 100644
--- a/crates/c-api/include/wasmtime/linker.h
+++ b/crates/c-api/include/wasmtime/linker.h
@@ -59,6 +59,7 @@ WASM_API_EXTERN void wasmtime_linker_allow_shadowing(wasmtime_linker_t* linker,
  * \brief Defines a new item in this linker.
  *
  * \param linker the linker the name is being defined in.
+ * \param store the store that the `item` is owned by.
  * \param module the module name the item is defined under.
  * \param module_len the byte length of `module`
  * \param name the field name the item is defined under
@@ -73,6 +74,7 @@ WASM_API_EXTERN void wasmtime_linker_allow_shadowing(wasmtime_linker_t* linker,
  */
 WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_define(
     wasmtime_linker_t *linker,
+    wasmtime_context_t *store,
     const char *module,
     size_t module_len,
     const char *name,
diff --git a/crates/c-api/src/linker.rs b/crates/c-api/src/linker.rs
index d5ad429fd..31a5aeed4 100644
--- a/crates/c-api/src/linker.rs
+++ b/crates/c-api/src/linker.rs
@@ -1,6 +1,6 @@
 use crate::{
     bad_utf8, handle_result, wasm_engine_t, wasm_functype_t, wasm_trap_t, wasmtime_error_t,
-    wasmtime_extern_t, wasmtime_module_t, CStoreContextMut,
+    wasmtime_extern_t, wasmtime_module_t, CStoreContext, CStoreContextMut,
 };
 use std::ffi::c_void;
 use std::mem::MaybeUninit;
@@ -41,6 +41,7 @@ macro_rules! to_str {
 #[no_mangle]
 pub unsafe extern "C" fn wasmtime_linker_define(
     linker: &mut wasmtime_linker_t,
+    store: CStoreContext<'_>,
     module: *const u8,
     module_len: usize,
     name: *const u8,
@@ -51,7 +52,7 @@ pub unsafe extern "C" fn wasmtime_linker_define(
     let module = to_str!(module, module_len);
     let name = to_str!(name, name_len);
     let item = item.to_extern();
-    handle_result(linker.define(module, name, item), |_linker| ())
+    handle_result(linker.define(&store, module, name, item), |_linker| ())
 }
 
 #[no_mangle]
diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs
index e453b2054..2ed29e6a3 100644
--- a/crates/fuzzing/src/oracles.rs
+++ b/crates/fuzzing/src/oracles.rs
@@ -544,45 +544,40 @@ pub fn table_ops(
         // test case.
         const MAX_GCS: usize = 5;
 
-        linker
-            .define(
-                "",
-                "gc",
-                // NB: use `Func::new` so that this can still compile on the old x86
-                // backend, where `IntoFunc` isn't implemented for multi-value
-                // returns.
-                Func::new(
-                    &mut store,
-                    FuncType::new(
-                        vec![],
-                        vec![ValType::ExternRef, ValType::ExternRef, ValType::ExternRef],
-                    ),
-                    {
-                        let num_dropped = num_dropped.clone();
-                        let expected_drops = expected_drops.clone();
-                        let num_gcs = num_gcs.clone();
-                        move |mut caller: Caller<'_, StoreLimits>, _params, results| {
-                            log::info!("table_ops: GC");
-                            if num_gcs.fetch_add(1, SeqCst) < MAX_GCS {
-                                caller.gc();
-                            }
-
-                            let a = ExternRef::new(CountDrops(num_dropped.clone()));
-                            let b = ExternRef::new(CountDrops(num_dropped.clone()));
-                            let c = ExternRef::new(CountDrops(num_dropped.clone()));
-
-                            log::info!("table_ops: make_refs() -> ({:p}, {:p}, {:p})", a, b, c);
-
-                            expected_drops.fetch_add(3, SeqCst);
-                            results[0] = Some(a).into();
-                            results[1] = Some(b).into();
-                            results[2] = Some(c).into();
-                            Ok(())
-                        }
-                    },
-                ),
-            )
-            .unwrap();
+        // NB: use `Func::new` so that this can still compile on the old x86
+        // backend, where `IntoFunc` isn't implemented for multi-value
+        // returns.
+        let func = Func::new(
+            &mut store,
+            FuncType::new(
+                vec![],
+                vec![ValType::ExternRef, ValType::ExternRef, ValType::ExternRef],
+            ),
+            {
+                let num_dropped = num_dropped.clone();
+                let expected_drops = expected_drops.clone();
+                let num_gcs = num_gcs.clone();
+                move |mut caller: Caller<'_, StoreLimits>, _params, results| {
+                    log::info!("table_ops: GC");
+                    if num_gcs.fetch_add(1, SeqCst) < MAX_GCS {
+                        caller.gc();
+                    }
+
+                    let a = ExternRef::new(CountDrops(num_dropped.clone()));
+                    let b = ExternRef::new(CountDrops(num_dropped.clone()));
+                    let c = ExternRef::new(CountDrops(num_dropped.clone()));
+
+                    log::info!("table_ops: make_refs() -> ({:p}, {:p}, {:p})", a, b, c);
+
+                    expected_drops.fetch_add(3, SeqCst);
+                    results[0] = Some(a).into();
+                    results[1] = Some(b).into();
+                    results[2] = Some(c).into();
+                    Ok(())
+                }
+            },
+        );
+        linker.define(&store, "", "gc", func).unwrap();
 
         linker
             .func_wrap("", "take_refs", {
@@ -624,37 +619,29 @@ pub fn table_ops(
             })
             .unwrap();
 
-        linker
-            .define(
-                "",
-                "make_refs",
-                // NB: use `Func::new` so that this can still compile on the old
-                // x86 backend, where `IntoFunc` isn't implemented for
-                // multi-value returns.
-                Func::new(
-                    &mut store,
-                    FuncType::new(
-                        vec![],
-                        vec![ValType::ExternRef, ValType::ExternRef, ValType::ExternRef],
-                    ),
-                    {
-                        let num_dropped = num_dropped.clone();
-                        let expected_drops = expected_drops.clone();
-                        move |_caller, _params, results| {
-                            log::info!("table_ops: make_refs");
-                            expected_drops.fetch_add(3, SeqCst);
-                            results[0] =
-                                Some(ExternRef::new(CountDrops(num_dropped.clone()))).into();
-                            results[1] =
-                                Some(ExternRef::new(CountDrops(num_dropped.clone()))).into();
-                            results[2] =
-                                Some(ExternRef::new(CountDrops(num_dropped.clone()))).into();
-                            Ok(())
-                        }
-                    },
-                ),
-            )
-            .unwrap();
+        // NB: use `Func::new` so that this can still compile on the old
+        // x86 backend, where `IntoFunc` isn't implemented for
+        // multi-value returns.
+        let func = Func::new(
+            &mut store,
+            FuncType::new(
+                vec![],
+                vec![ValType::ExternRef, ValType::ExternRef, ValType::ExternRef],
+            ),
+            {
+                let num_dropped = num_dropped.clone();
+                let expected_drops = expected_drops.clone();
+                move |_caller, _params, results| {
+                    log::info!("table_ops: make_refs");
+                    expected_drops.fetch_add(3, SeqCst);
+                    results[0] = Some(ExternRef::new(CountDrops(num_dropped.clone()))).into();
+                    results[1] = Some(ExternRef::new(CountDrops(num_dropped.clone()))).into();
+                    results[2] = Some(ExternRef::new(CountDrops(num_dropped.clone()))).into();
+                    Ok(())
+                }
+            },
+        );
+        linker.define(&store, "", "make_refs", func).unwrap();
 
         let instance = linker.instantiate(&mut store, &module).unwrap();
         let run = instance.get_func(&mut store, "run").unwrap();
diff --git a/crates/fuzzing/src/oracles/dummy.rs b/crates/fuzzing/src/oracles/dummy.rs
index 7e9601560..df4ec5662 100644
--- a/crates/fuzzing/src/oracles/dummy.rs
+++ b/crates/fuzzing/src/oracles/dummy.rs
@@ -8,12 +8,9 @@ pub fn dummy_linker<'module, T>(store: &mut Store<T>, module: &Module) -> Result
     let mut linker = Linker::new(store.engine());
     linker.allow_shadowing(true);
     for import in module.imports() {
+        let extern_ = dummy_extern(store, import.ty())?;
         linker
-            .define(
-                import.module(),
-                import.name(),
-                dummy_extern(store, import.ty())?,
-            )
+            .define(&store, import.module(), import.name(), extern_)
             .unwrap();
     }
     Ok(linker)
diff --git a/crates/wasmtime/src/component/instance.rs b/crates/wasmtime/src/component/instance.rs
index 1064f02e8..5c00b8bc3 100644
--- a/crates/wasmtime/src/component/instance.rs
+++ b/crates/wasmtime/src/component/instance.rs
@@ -1,6 +1,7 @@
 use crate::component::func::HostFunc;
 use crate::component::{Component, ComponentNamedList, Func, Lift, Lower, TypedFunc};
 use crate::instance::OwnedImports;
+use crate::linker::DefinitionType;
 use crate::store::{StoreOpaque, Stored};
 use crate::{AsContextMut, Module, StoreContextMut};
 use anyhow::{anyhow, Context, Result};
@@ -439,13 +440,13 @@ impl<'a> Instantiator<'a> {
         }
 
         let val = unsafe { crate::Extern::from_wasmtime_export(export, store) };
+        let ty = DefinitionType::from(store, &val);
         crate::types::matching::MatchCx {
-            store,
             engine: store.engine(),
             signatures: module.signatures(),
             types: module.types(),
         }
-        .extern_(&expected, &val)
+        .definition(&expected, &ty)
         .expect("unexpected typecheck failure");
     }
 }
diff --git a/crates/wasmtime/src/externals.rs b/crates/wasmtime/src/externals.rs
index 50eb51139..152ec6439 100644
--- a/crates/wasmtime/src/externals.rs
+++ b/crates/wasmtime/src/externals.rs
@@ -138,16 +138,6 @@ impl Extern {
             Extern::Table(t) => store.store_data().contains(t.0),
         }
     }
-
-    pub(crate) fn desc(&self) -> &'static str {
-        match self {
-            Extern::Func(_) => "function",
-            Extern::Table(_) => "table",
-            Extern::Memory(_) => "memory",
-            Extern::SharedMemory(_) => "shared memory",
-            Extern::Global(_) => "global",
-        }
-    }
 }
 
 impl From<Func> for Extern {
@@ -233,8 +223,8 @@ impl Global {
     /// )?;
     ///
     /// let mut linker = Linker::new(&engine);
-    /// linker.define("", "i32-const", i32_const)?;
-    /// linker.define("", "f64-mut", f64_mut)?;
+    /// linker.define(&store, "", "i32-const", i32_const)?;
+    /// linker.define(&store, "", "f64-mut", f64_mut)?;
     ///
     /// let instance = linker.instantiate(&mut store, &module)?;
     /// // ...
diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs
index 045dad494..cbb2f0b2a 100644
--- a/crates/wasmtime/src/instance.rs
+++ b/crates/wasmtime/src/instance.rs
@@ -1,4 +1,4 @@
-use crate::linker::Definition;
+use crate::linker::{Definition, DefinitionType};
 use crate::store::{InstanceId, StoreOpaque, Stored};
 use crate::types::matching;
 use crate::{
@@ -157,7 +157,10 @@ impl Instance {
                 bail!("cross-`Store` instantiation is not currently supported");
             }
         }
-        typecheck(store, module, imports, |cx, ty, item| cx.extern_(ty, item))?;
+        typecheck(module, imports, |cx, ty, item| {
+            let item = DefinitionType::from(store, item);
+            cx.definition(ty, &item)
+        })?;
         let mut owned_imports = OwnedImports::new(module);
         for import in imports {
             owned_imports.push(import, store);
@@ -679,19 +682,8 @@ impl<T> InstancePre<T> {
     /// This method is unsafe as the `T` of the `InstancePre<T>` is not
     /// guaranteed to be the same as the `T` within the `Store`, the caller must
     /// verify that.
-    pub(crate) unsafe fn new(
-        store: &mut StoreOpaque,
-        module: &Module,
-        items: Vec<Definition>,
-    ) -> Result<InstancePre<T>> {
-        for import in items.iter() {
-            if !import.comes_from_same_store(store) {
-                bail!("cross-`Store` instantiation is not currently supported");
-            }
-        }
-        typecheck(store, module, &items, |cx, ty, item| {
-            cx.definition(ty, item)
-        })?;
+    pub(crate) unsafe fn new(module: &Module, items: Vec<Definition>) -> Result<InstancePre<T>> {
+        typecheck(module, &items, |cx, ty, item| cx.definition(ty, &item.ty()))?;
 
         let host_funcs = items
             .iter()
@@ -813,7 +805,6 @@ fn pre_instantiate_raw(
 }
 
 fn typecheck<I>(
-    store: &mut StoreOpaque,
     module: &Module,
     imports: &[I],
     check: impl Fn(&matching::MatchCx<'_>, &EntityType, &I) -> Result<()>,
@@ -826,8 +817,7 @@ fn typecheck<I>(
     let cx = matching::MatchCx {
         signatures: module.signatures(),
         types: module.types(),
-        store: store,
-        engine: store.engine(),
+        engine: module.engine(),
     };
     for ((name, field, expected_ty), actual) in env_module.imports().zip(imports) {
         check(&cx, &expected_ty, actual)
diff --git a/crates/wasmtime/src/linker.rs b/crates/wasmtime/src/linker.rs
index 3f4782434..0cda89000 100644
--- a/crates/wasmtime/src/linker.rs
+++ b/crates/wasmtime/src/linker.rs
@@ -2,8 +2,8 @@ use crate::func::HostFunc;
 use crate::instance::InstancePre;
 use crate::store::StoreOpaque;
 use crate::{
-    AsContextMut, Caller, Engine, Extern, ExternType, Func, FuncType, ImportType, Instance,
-    IntoFunc, Module, StoreContextMut, Val, ValRaw,
+    AsContext, AsContextMut, Caller, Engine, Extern, ExternType, Func, FuncType, ImportType,
+    Instance, IntoFunc, Module, StoreContextMut, Val, ValRaw,
 };
 use anyhow::{bail, Context, Result};
 use log::warn;
@@ -113,10 +113,25 @@ struct ImportKey {
 
 #[derive(Clone)]
 pub(crate) enum Definition {
-    Extern(Extern),
+    Extern(Extern, DefinitionType),
     HostFunc(Arc<HostFunc>),
 }
 
+/// This is a sort of slimmed down `ExternType` which notably doesn't have a
+/// `FuncType`, which is an allocation, and additionally retains the current
+/// size of the table/memory.
+#[derive(Clone)]
+pub(crate) enum DefinitionType {
+    Func(wasmtime_runtime::VMSharedSignatureIndex),
+    Global(wasmtime_environ::Global),
+    // Note that tables and memories store not only the original type
+    // information but additionally the current size of the table/memory, as
+    // this is used during linking since the min size specified in the type may
+    // no longer be the current size of the table/memory.
+    Table(wasmtime_environ::Table, u32),
+    Memory(wasmtime_environ::Memory, u64),
+}
+
 macro_rules! generate_wrap_async_func {
     ($num:tt $($args:ident)*) => (paste::paste!{
         /// Asynchronous analog of [`Linker::func_wrap`].
@@ -296,7 +311,7 @@ impl<T> Linker<T> {
     /// let mut linker = Linker::new(&engine);
     /// let ty = GlobalType::new(ValType::I32, Mutability::Const);
     /// let global = Global::new(&mut store, ty, Val::I32(0x1234))?;
-    /// linker.define("host", "offset", global)?;
+    /// linker.define(&store, "host", "offset", global)?;
     ///
     /// let wat = r#"
     ///     (module
@@ -312,12 +327,14 @@ impl<T> Linker<T> {
     /// ```
     pub fn define(
         &mut self,
+        store: impl AsContext<Data = T>,
         module: &str,
         name: &str,
         item: impl Into<Extern>,
     ) -> Result<&mut Self> {
+        let store = store.as_context();
         let key = self.import_key(module, Some(name));
-        self.insert(key, Definition::Extern(item.into()))?;
+        self.insert(key, Definition::new(store.0, item.into()))?;
         Ok(self)
     }
 
@@ -327,9 +344,15 @@ impl<T> Linker<T> {
     /// This is only relevant when working with the module linking proposal
     /// where one-level names are allowed (in addition to two-level names).
     /// Otherwise this method need not be used.
-    pub fn define_name(&mut self, name: &str, item: impl Into<Extern>) -> Result<&mut Self> {
+    pub fn define_name(
+        &mut self,
+        store: impl AsContext<Data = T>,
+        name: &str,
+        item: impl Into<Extern>,
+    ) -> Result<&mut Self> {
+        let store = store.as_context();
         let key = self.import_key(name, None);
-        self.insert(key, Definition::Extern(item.into()))?;
+        self.insert(key, Definition::new(store.0, item.into()))?;
         Ok(self)
     }
 
@@ -542,9 +565,18 @@ impl<T> Linker<T> {
         module_name: &str,
         instance: Instance,
     ) -> Result<&mut Self> {
-        for export in instance.exports(store.as_context_mut()) {
-            let key = self.import_key(module_name, Some(export.name()));
-            self.insert(key, Definition::Extern(export.into_extern()))?;
+        let mut store = store.as_context_mut();
+        let exports = instance
+            .exports(&mut store)
+            .map(|e| {
+                (
+                    self.import_key(module_name, Some(e.name())),
+                    e.into_extern(),
+                )
+            })
+            .collect::<Vec<_>>();
+        for (key, export) in exports {
+            self.insert(key, Definition::new(store.0, export))?;
         }
         Ok(self)
     }
@@ -814,11 +846,11 @@ impl<T> Linker<T> {
         let mut store = store.as_context_mut();
         for export in module.exports() {
             if let Some(func_ty) = export.ty().func() {
-                let instance_pre = self.instantiate_pre(&mut store, module)?;
+                let instance_pre = self.instantiate_pre(module)?;
                 let export_name = export.name().to_owned();
                 let func = mk_func(&mut store, func_ty, export_name, instance_pre);
                 let key = self.import_key(module_name, Some(export.name()));
-                self.insert(key, Definition::Extern(func.into()))?;
+                self.insert(key, Definition::new(store.0, func.into()))?;
             } else if export.name() == "memory" && export.ty().memory().is_some() {
                 // Allow an exported "memory" memory for now.
             } else if export.name() == "__indirect_function_table" && export.ty().table().is_some()
@@ -1003,7 +1035,8 @@ impl<T> Linker<T> {
         mut store: impl AsContextMut<Data = T>,
         module: &Module,
     ) -> Result<Instance> {
-        self.instantiate_pre(&mut store, module)?.instantiate(store)
+        self._instantiate_pre(module, Some(store.as_context_mut().0))?
+            .instantiate(store)
     }
 
     /// Attempts to instantiate the `module` provided. This is the same as
@@ -1018,14 +1051,13 @@ impl<T> Linker<T> {
     where
         T: Send,
     {
-        self.instantiate_pre(&mut store, module)?
+        self._instantiate_pre(module, Some(store.as_context_mut().0))?
             .instantiate_async(store)
             .await
     }
 
     /// Performs all checks necessary for instantiating `module` with this
-    /// linker within `store`, except that instantiation doesn't actually
-    /// finish.
+    /// linker, except that instantiation doesn't actually finish.
     ///
     /// This method is used for front-loading type-checking information as well
     /// as collecting the imports to use to instantiate a module with. The
@@ -1060,7 +1092,7 @@ impl<T> Linker<T> {
     ///     )
     /// "#;
     /// let module = Module::new(&engine, wat)?;
-    /// let instance_pre = linker.instantiate_pre(&mut store, &module)?;
+    /// let instance_pre = linker.instantiate_pre(&module)?;
     ///
     /// // Finish instantiation after the type-checking has all completed...
     /// let instance = instance_pre.instantiate(&mut store)?;
@@ -1078,17 +1110,36 @@ impl<T> Linker<T> {
     /// # Ok(())
     /// # }
     /// ```
-    pub fn instantiate_pre(
+    pub fn instantiate_pre(&self, module: &Module) -> Result<InstancePre<T>> {
+        self._instantiate_pre(module, None)
+    }
+
+    /// This is split out to optionally take a `store` so that when the
+    /// `.instantiate` API is used we can get fresh up-to-date type information
+    /// for memories and their current size, if necessary.
+    ///
+    /// Note that providing a `store` here is not required for correctness
+    /// per-se. If one is not provided, such as the with the `instantiate_pre`
+    /// API, then the type information used for memories and tables will reflect
+    /// their size when inserted into the linker rather than their current size.
+    /// This isn't expected to be much of a problem though since
+    /// per-store-`Linker` types are likely using `.instantiate(..)` and
+    /// per-`Engine` linkers don't have memories/tables in them.
+    fn _instantiate_pre(
         &self,
-        mut store: impl AsContextMut<Data = T>,
         module: &Module,
+        store: Option<&StoreOpaque>,
     ) -> Result<InstancePre<T>> {
-        let store = store.as_context_mut().0;
-        let imports = module
+        let mut imports = module
             .imports()
             .map(|import| self._get_by_import(&import))
-            .collect::<Result<_, _>>()?;
-        unsafe { InstancePre::new(store, module, imports) }
+            .collect::<Result<Vec<_>, _>>()?;
+        if let Some(store) = store {
+            for import in imports.iter_mut() {
+                import.update_size(store);
+            }
+        }
+        unsafe { InstancePre::new(module, imports) }
     }
 
     /// Returns an iterator over all items defined in this `Linker`, in
@@ -1217,12 +1268,24 @@ impl<T> Default for Linker<T> {
 }
 
 impl Definition {
+    fn new(store: &StoreOpaque, item: Extern) -> Definition {
+        let ty = DefinitionType::from(store, &item);
+        Definition::Extern(item, ty)
+    }
+
+    pub(crate) fn ty(&self) -> DefinitionType {
+        match self {
+            Definition::Extern(_, ty) => ty.clone(),
+            Definition::HostFunc(func) => DefinitionType::Func(func.sig_index()),
+        }
+    }
+
     /// Note the unsafety here is due to calling `HostFunc::to_func`. The
     /// requirement here is that the `T` that was originally used to create the
     /// `HostFunc` matches the `T` on the store.
     pub(crate) unsafe fn to_extern(&self, store: &mut StoreOpaque) -> Extern {
         match self {
-            Definition::Extern(e) => e.clone(),
+            Definition::Extern(e, _) => e.clone(),
             Definition::HostFunc(func) => func.to_func(store).into(),
         }
     }
@@ -1231,17 +1294,56 @@ impl Definition {
     /// `HostFunc::to_func_store_rooted`.
     pub(crate) unsafe fn to_extern_store_rooted(&self, store: &mut StoreOpaque) -> Extern {
         match self {
-            Definition::Extern(e) => e.clone(),
+            Definition::Extern(e, _) => e.clone(),
             Definition::HostFunc(func) => func.to_func_store_rooted(store).into(),
         }
     }
 
     pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
         match self {
-            Definition::Extern(e) => e.comes_from_same_store(store),
+            Definition::Extern(e, _) => e.comes_from_same_store(store),
             Definition::HostFunc(_func) => true,
         }
     }
+
+    fn update_size(&mut self, store: &StoreOpaque) {
+        match self {
+            Definition::Extern(Extern::Memory(m), DefinitionType::Memory(_, size)) => {
+                *size = m.internal_size(store);
+            }
+            Definition::Extern(Extern::SharedMemory(m), DefinitionType::Memory(_, size)) => {
+                *size = m.size();
+            }
+            Definition::Extern(Extern::Table(m), DefinitionType::Table(_, size)) => {
+                *size = m.internal_size(store);
+            }
+            _ => {}
+        }
+    }
+}
+
+impl DefinitionType {
+    pub(crate) fn from(store: &StoreOpaque, item: &Extern) -> DefinitionType {
+        let data = store.store_data();
+        match item {
+            Extern::Func(f) => DefinitionType::Func(f.sig_index(data)),
+            Extern::Table(t) => DefinitionType::Table(*t.wasmtime_ty(data), t.internal_size(store)),
+            Extern::Global(t) => DefinitionType::Global(*t.wasmtime_ty(data)),
+            Extern::Memory(t) => {
+                DefinitionType::Memory(*t.wasmtime_ty(data), t.internal_size(store))
+            }
+            Extern::SharedMemory(t) => DefinitionType::Memory(*t.ty().wasmtime_memory(), t.size()),
+        }
+    }
+
+    pub(crate) fn desc(&self) -> &'static str {
+        match self {
+            DefinitionType::Func(_) => "function",
+            DefinitionType::Table(..) => "table",
+            DefinitionType::Memory(..) => "memory",
+            DefinitionType::Global(_) => "global",
+        }
+    }
 }
 
 /// Modules can be interpreted either as Commands or Reactors.
diff --git a/crates/wasmtime/src/types/matching.rs b/crates/wasmtime/src/types/matching.rs
index 4e2047359..11b460fa7 100644
--- a/crates/wasmtime/src/types/matching.rs
+++ b/crates/wasmtime/src/types/matching.rs
@@ -1,6 +1,5 @@
-use crate::linker::Definition;
-use crate::store::StoreOpaque;
-use crate::{signatures::SignatureCollection, Engine, Extern};
+use crate::linker::DefinitionType;
+use crate::{signatures::SignatureCollection, Engine};
 use anyhow::{anyhow, bail, Result};
 use wasmtime_environ::{
     EntityType, Global, Memory, ModuleTypes, SignatureIndex, Table, WasmFuncType, WasmType,
@@ -10,47 +9,10 @@ use wasmtime_runtime::VMSharedSignatureIndex;
 pub struct MatchCx<'a> {
     pub signatures: &'a SignatureCollection,
     pub types: &'a ModuleTypes,
-    pub store: &'a StoreOpaque,
     pub engine: &'a Engine,
 }
 
 impl MatchCx<'_> {
-    pub fn global(&self, expected: &Global, actual: &crate::Global) -> Result<()> {
-        global_ty(expected, actual.wasmtime_ty(self.store.store_data()))
-    }
-
-    pub fn table(&self, expected: &Table, actual: &crate::Table) -> Result<()> {
-        table_ty(
-            expected,
-            actual.wasmtime_ty(self.store.store_data()),
-            Some(actual.internal_size(self.store)),
-        )
-    }
-
-    pub fn memory(&self, expected: &Memory, actual: &crate::Memory) -> Result<()> {
-        memory_ty(
-            expected,
-            actual.wasmtime_ty(self.store.store_data()),
-            Some(actual.internal_size(self.store)),
-        )
-    }
-
-    pub fn shared_memory(&self, expected: &Memory, actual: &crate::SharedMemory) -> Result<()> {
-        memory_ty(expected, actual.ty().wasmtime_memory(), Some(actual.size()))
-    }
-
-    pub fn func(&self, expected: SignatureIndex, actual: &crate::Func) -> Result<()> {
-        self.vmshared_signature_index(expected, actual.sig_index(self.store.store_data()))
-    }
-
-    pub(crate) fn host_func(
-        &self,
-        expected: SignatureIndex,
-        actual: &crate::func::HostFunc,
-    ) -> Result<()> {
-        self.vmshared_signature_index(expected, actual.sig_index())
-    }
-
     pub fn vmshared_signature_index(
         &self,
         expected: SignatureIndex,
@@ -79,39 +41,31 @@ impl MatchCx<'_> {
     }
 
     /// Validates that the `expected` type matches the type of `actual`
-    pub fn extern_(&self, expected: &EntityType, actual: &Extern) -> Result<()> {
+    pub(crate) fn definition(&self, expected: &EntityType, actual: &DefinitionType) -> Result<()> {
         match expected {
             EntityType::Global(expected) => match actual {
-                Extern::Global(actual) => self.global(expected, actual),
+                DefinitionType::Global(actual) => global_ty(expected, actual),
                 _ => bail!("expected global, but found {}", actual.desc()),
             },
             EntityType::Table(expected) => match actual {
-                Extern::Table(actual) => self.table(expected, actual),
+                DefinitionType::Table(actual, cur_size) => {
+                    table_ty(expected, actual, Some(*cur_size))
+                }
                 _ => bail!("expected table, but found {}", actual.desc()),
             },
             EntityType::Memory(expected) => match actual {
-                Extern::Memory(actual) => self.memory(expected, actual),
-                Extern::SharedMemory(actual) => self.shared_memory(expected, actual),
+                DefinitionType::Memory(actual, cur_size) => {
+                    memory_ty(expected, actual, Some(*cur_size))
+                }
                 _ => bail!("expected memory, but found {}", actual.desc()),
             },
             EntityType::Function(expected) => match actual {
-                Extern::Func(actual) => self.func(*expected, actual),
+                DefinitionType::Func(actual) => self.vmshared_signature_index(*expected, *actual),
                 _ => bail!("expected func, but found {}", actual.desc()),
             },
             EntityType::Tag(_) => unimplemented!(),
         }
     }
-
-    /// Validates that the `expected` type matches the type of `actual`
-    pub(crate) fn definition(&self, expected: &EntityType, actual: &Definition) -> Result<()> {
-        match actual {
-            Definition::Extern(e) => self.extern_(expected, e),
-            Definition::HostFunc(f) => match expected {
-                EntityType::Function(expected) => self.host_func(*expected, f),
-                _ => bail!("expected {}, but found func", entity_desc(expected)),
-            },
-        }
-    }
 }
 
 #[cfg_attr(not(feature = "component-model"), allow(dead_code))]
diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs
index 3b01aad4a..f08011fb5 100644
--- a/crates/wit-bindgen/src/lib.rs
+++ b/crates/wit-bindgen/src/lib.rs
@@ -101,7 +101,7 @@ impl Wasmtime {
 
     fn import(&mut self, resolve: &Resolve, name: &str, item: &WorldItem) {
         let snake = name.to_snake_case();
-        let mut gen = InterfaceGenerator::new(self, resolve, TypeMode::Owned);
+        let mut gen = InterfaceGenerator::new(self, resolve);
         let import = match item {
             WorldItem::Function(func) => {
                 gen.generate_function_trait_sig(TypeOwner::None, &func);
@@ -139,7 +139,7 @@ impl Wasmtime {
 
     fn export(&mut self, resolve: &Resolve, name: &str, item: &WorldItem) {
         let snake = name.to_snake_case();
-        let mut gen = InterfaceGenerator::new(self, resolve, TypeMode::AllBorrowed("'a"));
+        let mut gen = InterfaceGenerator::new(self, resolve);
         let (ty, getter) = match item {
             WorldItem::Function(func) => {
                 gen.define_rust_guest_export(None, func);
@@ -450,21 +450,15 @@ struct InterfaceGenerator<'a> {
     src: Source,
     gen: &'a mut Wasmtime,
     resolve: &'a Resolve,
-    default_param_mode: TypeMode,
     current_interface: Option<InterfaceId>,
 }
 
 impl<'a> InterfaceGenerator<'a> {
-    fn new(
-        gen: &'a mut Wasmtime,
-        resolve: &'a Resolve,
-        default_param_mode: TypeMode,
-    ) -> InterfaceGenerator<'a> {
+    fn new(gen: &'a mut Wasmtime, resolve: &'a Resolve) -> InterfaceGenerator<'a> {
         InterfaceGenerator {
             src: Source::default(),
             gen,
             resolve,
-            default_param_mode,
             current_interface: None,
         }
     }
@@ -1159,7 +1153,7 @@ impl<'a> InterfaceGenerator<'a> {
         self.rustdoc(&func.docs);
         uwrite!(
             self.src,
-            "pub {async_} fn {}<S: wasmtime::AsContextMut>(&self, mut store: S, ",
+            "pub {async_} fn call_{}<S: wasmtime::AsContextMut>(&self, mut store: S, ",
             func.name.to_snake_case(),
         );
         for (i, param) in func.params.iter().enumerate() {
@@ -1351,10 +1345,6 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
         self.current_interface
     }
 
-    fn default_param_mode(&self) -> TypeMode {
-        self.default_param_mode
-    }
-
     fn push_str(&mut self, s: &str) {
         self.src.push_str(s);
     }
diff --git a/crates/wit-bindgen/src/rust.rs b/crates/wit-bindgen/src/rust.rs
index bd936b0ef..7253106b3 100644
--- a/crates/wit-bindgen/src/rust.rs
+++ b/crates/wit-bindgen/src/rust.rs
@@ -15,7 +15,6 @@ pub trait RustGenerator<'a> {
 
     fn push_str(&mut self, s: &str);
     fn info(&self, ty: TypeId) -> TypeInfo;
-    fn default_param_mode(&self) -> TypeMode;
     fn current_interface(&self) -> Option<InterfaceId>;
 
     fn print_ty(&mut self, ty: &Type, mode: TypeMode) {
@@ -209,10 +208,10 @@ pub trait RustGenerator<'a> {
     fn modes_of(&self, ty: TypeId) -> Vec<(String, TypeMode)> {
         let info = self.info(ty);
         let mut result = Vec::new();
-        if info.param {
-            result.push((self.param_name(ty), self.default_param_mode()));
+        if info.borrowed {
+            result.push((self.param_name(ty), TypeMode::AllBorrowed("'a")));
         }
-        if info.result && (!info.param || self.uses_two_names(&info)) {
+        if info.owned && (!info.borrowed || self.uses_two_names(&info)) {
             result.push((self.result_name(ty), TypeMode::Owned));
         }
         return result;
@@ -358,13 +357,7 @@ pub trait RustGenerator<'a> {
     }
 
     fn uses_two_names(&self, info: &TypeInfo) -> bool {
-        info.has_list
-            && info.param
-            && info.result
-            && match self.default_param_mode() {
-                TypeMode::AllBorrowed(_) => true,
-                TypeMode::Owned => false,
-            }
+        info.has_list && info.borrowed && info.owned
     }
 
     fn lifetime_for(&self, info: &TypeInfo, mode: TypeMode) -> Option<&'static str> {
diff --git a/crates/wit-bindgen/src/types.rs b/crates/wit-bindgen/src/types.rs
index c449f513f..4b2765f86 100644
--- a/crates/wit-bindgen/src/types.rs
+++ b/crates/wit-bindgen/src/types.rs
@@ -8,13 +8,14 @@ pub struct Types {
 
 #[derive(Default, Clone, Copy, Debug, PartialEq)]
 pub struct TypeInfo {
-    /// Whether or not this type is ever used (transitively) within the
-    /// parameter of a function.
-    pub param: bool,
+    /// Whether or not this type is ever used (transitively) within a borrowed
+    /// context, or a parameter to an export function.
+    pub borrowed: bool,
 
-    /// Whether or not this type is ever used (transitively) within the
-    /// result of a function.
-    pub result: bool,
+    /// Whether or not this type is ever used (transitively) within an owned
+    /// context, such as the result of an exported function or in the params or
+    /// results of an imported function.
+    pub owned: bool,
 
     /// Whether or not this type is ever used (transitively) within the
     /// error case in the result of a function.
@@ -26,8 +27,8 @@ pub struct TypeInfo {
 
 impl std::ops::BitOrAssign for TypeInfo {
     fn bitor_assign(&mut self, rhs: Self) {
-        self.param |= rhs.param;
-        self.result |= rhs.result;
+        self.borrowed |= rhs.borrowed;
+        self.owned |= rhs.owned;
         self.error |= rhs.error;
         self.has_list |= rhs.has_list;
     }
@@ -36,9 +37,14 @@ impl std::ops::BitOrAssign for TypeInfo {
 impl Types {
     pub fn analyze(&mut self, resolve: &Resolve, world: WorldId) {
         let world = &resolve.worlds[world];
-        for (_, item) in world.imports.iter().chain(world.exports.iter()) {
+        for (import, (_, item)) in world
+            .imports
+            .iter()
+            .map(|i| (true, i))
+            .chain(world.exports.iter().map(|i| (false, i)))
+        {
             match item {
-                WorldItem::Function(f) => self.type_info_func(resolve, f),
+                WorldItem::Function(f) => self.type_info_func(resolve, f, import),
                 WorldItem::Interface(id) => {
                     let iface = &resolve.interfaces[*id];
 
@@ -46,21 +52,26 @@ impl Types {
                         self.type_id_info(resolve, *t);
                     }
                     for (_, f) in iface.functions.iter() {
-                        self.type_info_func(resolve, f);
+                        self.type_info_func(resolve, f, import);
                     }
                 }
             }
         }
     }
 
-    fn type_info_func(&mut self, resolve: &Resolve, func: &Function) {
+    fn type_info_func(&mut self, resolve: &Resolve, func: &Function, import: bool) {
         let mut live = LiveTypes::default();
         for (_, ty) in func.params.iter() {
             self.type_info(resolve, ty);
             live.add_type(resolve, ty);
         }
         for id in live.iter() {
-            self.type_info.get_mut(&id).unwrap().param = true;
+            let info = self.type_info.get_mut(&id).unwrap();
+            if import {
+                info.owned = true;
+            } else {
+                info.borrowed = true;
+            }
         }
         let mut live = LiveTypes::default();
         for ty in func.results.iter_types() {
@@ -68,7 +79,7 @@ impl Types {
             live.add_type(resolve, ty);
         }
         for id in live.iter() {
-            self.type_info.get_mut(&id).unwrap().result = true;
+            self.type_info.get_mut(&id).unwrap().owned = true;
         }
 
         for ty in func.results.iter_types() {
diff --git a/winch/codegen/src/isa/reg.rs b/winch/codegen/src/isa/reg.rs
index d4a55c11a..c7e47897e 100644
--- a/winch/codegen/src/isa/reg.rs
+++ b/winch/codegen/src/isa/reg.rs
@@ -27,11 +27,6 @@ impl Reg {
         Self::new(PReg::new(enc, RegClass::Float))
     }
 
-    /// Get the class of the underlying register.
-    pub fn class(self) -> RegClass {
-        self.0.class()
-    }
-
     /// Get the encoding of the underlying register.
     pub fn hw_enc(self) -> u8 {
         self.0.hw_enc() as u8
diff --git a/winch/codegen/src/isa/x64/abi.rs b/winch/codegen/src/isa/x64/abi.rs
index 7c5060969..cf7dc2eb5 100644
--- a/winch/codegen/src/isa/x64/abi.rs
+++ b/winch/codegen/src/isa/x64/abi.rs
@@ -40,6 +40,15 @@ impl ABI for X64ABI {
     }
 
     fn arg_base_offset(&self) -> u8 {
+        // Two 8-byte slots, one for the return address and another
+        // one for the frame pointer.
+        // ┌──────────┬───────── Argument base
+        // │   Ret    │
+        // │   Addr   │
+        // ├──────────┼
+        // │          │
+        // │   FP     │
+        // └──────────┴
         16
     }
 
diff --git a/winch/codegen/src/isa/x64/masm.rs b/winch/codegen/src/isa/x64/masm.rs
index 520f46db1..3f73aaf64 100644
--- a/winch/codegen/src/isa/x64/masm.rs
+++ b/winch/codegen/src/isa/x64/masm.rs
@@ -124,6 +124,8 @@ impl Masm for MacroAssembler {
     }
 
     fn epilogue(&mut self, locals_size: u32) {
+        assert!(self.sp_offset == locals_size);
+
         let rsp = rsp();
         if locals_size > 0 {
             self.asm.add_ir(locals_size as i32, rsp, OperandSize::S64);
diff --git a/winch/codegen/src/isa/x64/regs.rs b/winch/codegen/src/isa/x64/regs.rs
index 2e78c1b28..18710024f 100644
--- a/winch/codegen/src/isa/x64/regs.rs
+++ b/winch/codegen/src/isa/x64/regs.rs
@@ -142,97 +142,3 @@ const NON_ALLOCATABLE_GPR: u32 = (1 << ENC_RBP) | (1 << ENC_RSP) | (1 << ENC_R11
 
 /// Bitmask to represent the available general purpose registers.
 pub(crate) const ALL_GPR: u32 = ALLOCATABLE_GPR & !NON_ALLOCATABLE_GPR;
-
-// Temporarily removing the % from the register name
-// for debugging purposes only until winch gets disasm
-// support.
-pub(crate) fn reg_name(reg: Reg, size: u8) -> &'static str {
-    match reg.class() {
-        RegClass::Int => match (reg.hw_enc() as u8, size) {
-            (ENC_RAX, 8) => "rax",
-            (ENC_RAX, 4) => "eax",
-            (ENC_RAX, 2) => "ax",
-            (ENC_RAX, 1) => "al",
-            (ENC_RBX, 8) => "rbx",
-            (ENC_RBX, 4) => "ebx",
-            (ENC_RBX, 2) => "bx",
-            (ENC_RBX, 1) => "bl",
-            (ENC_RCX, 8) => "rcx",
-            (ENC_RCX, 4) => "ecx",
-            (ENC_RCX, 2) => "cx",
-            (ENC_RCX, 1) => "cl",
-            (ENC_RDX, 8) => "rdx",
-            (ENC_RDX, 4) => "edx",
-            (ENC_RDX, 2) => "dx",
-            (ENC_RDX, 1) => "dl",
-            (ENC_RSI, 8) => "rsi",
-            (ENC_RSI, 4) => "esi",
-            (ENC_RSI, 2) => "si",
-            (ENC_RSI, 1) => "sil",
-            (ENC_RDI, 8) => "rdi",
-            (ENC_RDI, 4) => "edi",
-            (ENC_RDI, 2) => "di",
-            (ENC_RDI, 1) => "dil",
-            (ENC_RBP, 8) => "rbp",
-            (ENC_RBP, 4) => "ebp",
-            (ENC_RBP, 2) => "bp",
-            (ENC_RBP, 1) => "bpl",
-            (ENC_RSP, 8) => "rsp",
-            (ENC_RSP, 4) => "esp",
-            (ENC_RSP, 2) => "sp",
-            (ENC_RSP, 1) => "spl",
-            (ENC_R8, 8) => "r8",
-            (ENC_R8, 4) => "r8d",
-            (ENC_R8, 2) => "r8w",
-            (ENC_R8, 1) => "r8b",
-            (ENC_R9, 8) => "r9",
-            (ENC_R9, 4) => "r9d",
-            (ENC_R9, 2) => "r9w",
-            (ENC_R9, 1) => "r9b",
-            (ENC_R10, 8) => "r10",
-            (ENC_R10, 4) => "r10d",
-            (ENC_R10, 2) => "r10w",
-            (ENC_R10, 1) => "r10b",
-            (ENC_R11, 8) => "r11",
-            (ENC_R11, 4) => "r11d",
-            (ENC_R11, 2) => "r11w",
-            (ENC_R11, 1) => "r11b",
-            (ENC_R12, 8) => "r12",
-            (ENC_R12, 4) => "r12d",
-            (ENC_R12, 2) => "r12w",
-            (ENC_R12, 1) => "r12b",
-            (ENC_R13, 8) => "r13",
-            (ENC_R13, 4) => "r13d",
-            (ENC_R13, 2) => "r13w",
-            (ENC_R13, 1) => "r13b",
-            (ENC_R14, 8) => "r14",
-            (ENC_R14, 4) => "r14d",
-            (ENC_R14, 2) => "r14w",
-            (ENC_R14, 1) => "r14b",
-            (ENC_R15, 8) => "r15",
-            (ENC_R15, 4) => "r15d",
-            (ENC_R15, 2) => "r15w",
-            (ENC_R15, 1) => "r15b",
-            _ => panic!("Invalid Reg: {:?}", reg),
-        },
-        RegClass::Float => match reg.hw_enc() {
-            0 => "xmm0",
-            1 => "xmm1",
-            2 => "xmm2",
-            3 => "xmm3",
-            4 => "xmm4",
-            5 => "xmm5",
-            6 => "xmm6",
-            7 => "xmm7",
-            8 => "xmm8",
-            9 => "xmm9",
-            10 => "xmm10",
-            11 => "xmm11",
-            12 => "xmm12",
-            13 => "xmm13",
-            14 => "xmm14",
-            15 => "xmm15",
-            _ => panic!("Invalid Reg: {:?}", reg),
-        },
-    }
-}
diff --git a/winch/codegen/src/regalloc.rs b/winch/codegen/src/regalloc.rs
index 8d29f77a5..0d67808ee 100644
--- a/winch/codegen/src/regalloc.rs
+++ b/winch/codegen/src/regalloc.rs
@@ -134,9 +134,7 @@ impl RegAlloc {
                     .get_local(*index)
                     .expect("valid local at slot");
                 let addr = context.masm.local_address(&slot);
-                context
-                    .masm
-                    .store(RegImm::reg(self.scratch), addr, slot.ty.into());
+                context.masm.load(addr, self.scratch, slot.ty.into());
                 let offset = context.masm.push(self.scratch);
                 *v = Val::Memory(offset);
             }


Test patch:
diff --git a/crates/component-macro/tests/codegen/function-new.wit b/crates/component-macro/tests/codegen/function-new.wit
new file mode 100644
index 000000000..fed79c663
--- /dev/null
+++ b/crates/component-macro/tests/codegen/function-new.wit
@@ -0,0 +1,3 @@
+default world foo {
+  export new: func()
+}
diff --git a/crates/component-macro/tests/codegen/share-types.wit b/crates/component-macro/tests/codegen/share-types.wit
new file mode 100644
index 000000000..106ee7093
--- /dev/null
+++ b/crates/component-macro/tests/codegen/share-types.wit
@@ -0,0 +1,19 @@
+interface http-types{
+  record request {
+    method: string
+  }
+  record response {
+    body: string
+  }
+}
+
+default world http-interface {
+  export http-handler: interface {
+    use self.http-types.{request,response}
+    handle-request: func(request: request) -> response
+  }
+  import http-fetch: interface {
+    use self.http-types.{request,response}
+    fetch-request: func(request: request) -> response
+  }
+}
diff --git a/crates/wast/src/spectest.rs b/crates/wast/src/spectest.rs
index f7ff59d55..b699d24aa 100644
--- a/crates/wast/src/spectest.rs
+++ b/crates/wast/src/spectest.rs
@@ -24,32 +24,32 @@ pub fn link_spectest<T>(
 
     let ty = GlobalType::new(ValType::I32, Mutability::Const);
     let g = Global::new(&mut *store, ty, Val::I32(666))?;
-    linker.define("spectest", "global_i32", g)?;
+    linker.define(&mut *store, "spectest", "global_i32", g)?;
 
     let ty = GlobalType::new(ValType::I64, Mutability::Const);
     let g = Global::new(&mut *store, ty, Val::I64(666))?;
-    linker.define("spectest", "global_i64", g)?;
+    linker.define(&mut *store, "spectest", "global_i64", g)?;
 
     let ty = GlobalType::new(ValType::F32, Mutability::Const);
     let g = Global::new(&mut *store, ty, Val::F32(0x4426_8000))?;
-    linker.define("spectest", "global_f32", g)?;
+    linker.define(&mut *store, "spectest", "global_f32", g)?;
 
     let ty = GlobalType::new(ValType::F64, Mutability::Const);
     let g = Global::new(&mut *store, ty, Val::F64(0x4084_d000_0000_0000))?;
-    linker.define("spectest", "global_f64", g)?;
+    linker.define(&mut *store, "spectest", "global_f64", g)?;
 
     let ty = TableType::new(ValType::FuncRef, 10, Some(20));
     let table = Table::new(&mut *store, ty, Val::FuncRef(None))?;
-    linker.define("spectest", "table", table)?;
+    linker.define(&mut *store, "spectest", "table", table)?;
 
     let ty = MemoryType::new(1, Some(2));
     let memory = Memory::new(&mut *store, ty)?;
-    linker.define("spectest", "memory", memory)?;
+    linker.define(&mut *store, "spectest", "memory", memory)?;
 
     if use_shared_memory {
         let ty = MemoryType::shared(1, 1);
         let memory = Memory::new(&mut *store, ty)?;
-        linker.define("spectest", "shared_memory", memory)?;
+        linker.define(&mut *store, "spectest", "shared_memory", memory)?;
     }
 
     Ok(())
diff --git a/tests/all/call_hook.rs b/tests/all/call_hook.rs
index 7184f06db..4dc741734 100644
--- a/tests/all/call_hook.rs
+++ b/tests/all/call_hook.rs
@@ -262,7 +262,7 @@ async fn call_linked_func_async() -> Result<(), Error> {
 
     let mut linker = Linker::new(&engine);
 
-    linker.define("host", "f", f)?;
+    linker.define(&mut store, "host", "f", f)?;
 
     let wat = r#"
         (module
diff --git a/tests/all/component_model/bindgen.rs b/tests/all/component_model/bindgen.rs
index 8b41cb485..ddadec891 100644
--- a/tests/all/component_model/bindgen.rs
+++ b/tests/all/component_model/bindgen.rs
@@ -46,8 +46,8 @@ mod no_imports {
         let linker = Linker::new(&engine);
         let mut store = Store::new(&engine, ());
         let (no_imports, _) = NoImports::instantiate(&mut store, &component, &linker)?;
-        no_imports.bar(&mut store)?;
-        no_imports.foo().foo(&mut store)?;
+        no_imports.call_bar(&mut store)?;
+        no_imports.foo().call_foo(&mut store)?;
         Ok(())
     }
 }
@@ -108,7 +108,7 @@ mod one_import {
         foo::add_to_linker(&mut linker, |f: &mut MyImports| f)?;
         let mut store = Store::new(&engine, MyImports::default());
         let (one_import, _) = OneImport::instantiate(&mut store, &component, &linker)?;
-        one_import.bar(&mut store)?;
+        one_import.call_bar(&mut store)?;
         assert!(store.data().hit);
         Ok(())
     }
diff --git a/tests/all/component_model/bindgen/results.rs b/tests/all/component_model/bindgen/results.rs
index 82e318948..321eed9fd 100644
--- a/tests/all/component_model/bindgen/results.rs
+++ b/tests/all/component_model/bindgen/results.rs
@@ -80,19 +80,22 @@ mod empty_error {
 
         assert_eq!(
             results
-                .empty_error(&mut store, 0.0)
+                .call_empty_error(&mut store, 0.0)
                 .expect("no trap")
                 .expect("no error returned"),
             0.0
         );
 
         results
-            .empty_error(&mut store, 1.0)
+            .call_empty_error(&mut store, 1.0)
             .expect("no trap")
             .err()
             .expect("() error returned");
 
-        let e = results.empty_error(&mut store, 2.0).err().expect("trap");
+        let e = results
+            .call_empty_error(&mut store, 2.0)
+            .err()
+            .expect("trap");
         assert_eq!(
             format!("{}", e.source().expect("trap message is stored in source")),
             "empty_error: trap"
@@ -188,20 +191,23 @@ mod string_error {
 
         assert_eq!(
             results
-                .string_error(&mut store, 0.0)
+                .call_string_error(&mut store, 0.0)
                 .expect("no trap")
                 .expect("no error returned"),
             0.0
         );
 
         let e = results
-            .string_error(&mut store, 1.0)
+            .call_string_error(&mut store, 1.0)
             .expect("no trap")
             .err()
             .expect("error returned");
         assert_eq!(e, "string_error: error");
 
-        let e = results.string_error(&mut store, 2.0).err().expect("trap");
+        let e = results
+            .call_string_error(&mut store, 2.0)
+            .err()
+            .expect("trap");
         assert_eq!(
             format!("{}", e.source().expect("trap message is stored in source")),
             "string_error: trap"
@@ -328,7 +334,7 @@ mod enum_error {
         assert_eq!(
             results
                 .foo()
-                .enum_error(&mut store, 0.0)
+                .call_enum_error(&mut store, 0.0)
                 .expect("no trap")
                 .expect("no error returned"),
             0.0
@@ -336,7 +342,7 @@ mod enum_error {
 
         let e = results
             .foo()
-            .enum_error(&mut store, 1.0)
+            .call_enum_error(&mut store, 1.0)
             .expect("no trap")
             .err()
             .expect("error returned");
@@ -344,7 +350,7 @@ mod enum_error {
 
         let e = results
             .foo()
-            .enum_error(&mut store, 2.0)
+            .call_enum_error(&mut store, 2.0)
             .err()
             .expect("trap");
         assert_eq!(
@@ -458,7 +464,7 @@ mod record_error {
         assert_eq!(
             results
                 .foo()
-                .record_error(&mut store, 0.0)
+                .call_record_error(&mut store, 0.0)
                 .expect("no trap")
                 .expect("no error returned"),
             0.0
@@ -466,7 +472,7 @@ mod record_error {
 
         let e = results
             .foo()
-            .record_error(&mut store, 1.0)
+            .call_record_error(&mut store, 1.0)
             .expect("no trap")
             .err()
             .expect("error returned");
@@ -480,7 +486,7 @@ mod record_error {
 
         let e = results
             .foo()
-            .record_error(&mut store, 2.0)
+            .call_record_error(&mut store, 2.0)
             .err()
             .expect("trap");
         assert_eq!(
@@ -594,7 +600,7 @@ mod variant_error {
         assert_eq!(
             results
                 .foo()
-                .variant_error(&mut store, 0.0)
+                .call_variant_error(&mut store, 0.0)
                 .expect("no trap")
                 .expect("no error returned"),
             0.0
@@ -602,7 +608,7 @@ mod variant_error {
 
         let e = results
             .foo()
-            .variant_error(&mut store, 1.0)
+            .call_variant_error(&mut store, 1.0)
             .expect("no trap")
             .err()
             .expect("error returned");
@@ -616,7 +622,7 @@ mod variant_error {
 
         let e = results
             .foo()
-            .variant_error(&mut store, 2.0)
+            .call_variant_error(&mut store, 2.0)
             .err()
             .expect("trap");
         assert_eq!(
diff --git a/tests/all/linker.rs b/tests/all/linker.rs
index 0f1c38c6c..4048f6894 100644
--- a/tests/all/linker.rs
+++ b/tests/all/linker.rs
@@ -56,36 +56,36 @@ fn link_twice_bad() -> Result<()> {
     // globals
     let ty = GlobalType::new(ValType::I32, Mutability::Const);
     let global = Global::new(&mut store, ty, Val::I32(0))?;
-    linker.define("g", "1", global.clone())?;
-    assert!(linker.define("g", "1", global.clone()).is_err());
+    linker.define(&mut store, "g", "1", global.clone())?;
+    assert!(linker.define(&mut store, "g", "1", global.clone()).is_err());
 
     let ty = GlobalType::new(ValType::I32, Mutability::Var);
     let global = Global::new(&mut store, ty, Val::I32(0))?;
-    linker.define("g", "2", global.clone())?;
-    assert!(linker.define("g", "2", global.clone()).is_err());
+    linker.define(&mut store, "g", "2", global.clone())?;
+    assert!(linker.define(&mut store, "g", "2", global.clone()).is_err());
 
     let ty = GlobalType::new(ValType::I64, Mutability::Const);
     let global = Global::new(&mut store, ty, Val::I64(0))?;
-    linker.define("g", "3", global.clone())?;
-    assert!(linker.define("g", "3", global.clone()).is_err());
+    linker.define(&mut store, "g", "3", global.clone())?;
+    assert!(linker.define(&mut store, "g", "3", global.clone()).is_err());
 
     // memories
     let ty = MemoryType::new(1, None);
     let memory = Memory::new(&mut store, ty)?;
-    linker.define("m", "", memory.clone())?;
-    assert!(linker.define("m", "", memory.clone()).is_err());
+    linker.define(&mut store, "m", "", memory.clone())?;
+    assert!(linker.define(&mut store, "m", "", memory.clone()).is_err());
     let ty = MemoryType::new(2, None);
     let memory = Memory::new(&mut store, ty)?;
-    assert!(linker.define("m", "", memory.clone()).is_err());
+    assert!(linker.define(&mut store, "m", "", memory.clone()).is_err());
 
     // tables
     let ty = TableType::new(ValType::FuncRef, 1, None);
     let table = Table::new(&mut store, ty, Val::FuncRef(None))?;
-    linker.define("t", "", table.clone())?;
-    assert!(linker.define("t", "", table.clone()).is_err());
+    linker.define(&mut store, "t", "", table.clone())?;
+    assert!(linker.define(&mut store, "t", "", table.clone()).is_err());
     let ty = TableType::new(ValType::FuncRef, 2, None);
     let table = Table::new(&mut store, ty, Val::FuncRef(None))?;
-    assert!(linker.define("t", "", table.clone()).is_err());
+    assert!(linker.define(&mut store, "t", "", table.clone()).is_err());
     Ok(())
 }
 
@@ -100,11 +100,8 @@ fn function_interposition() -> Result<()> {
     )?;
     for _ in 0..4 {
         let instance = linker.instantiate(&mut store, &module)?;
-        linker.define(
-            "red",
-            "green",
-            instance.get_export(&mut store, "green").unwrap().clone(),
-        )?;
+        let green = instance.get_export(&mut store, "green").unwrap().clone();
+        linker.define(&mut store, "red", "green", green)?;
         module = Module::new(
             store.engine(),
             r#"(module
@@ -137,11 +134,8 @@ fn function_interposition_renamed() -> Result<()> {
     )?;
     for _ in 0..4 {
         let instance = linker.instantiate(&mut store, &module)?;
-        linker.define(
-            "red",
-            "green",
-            instance.get_export(&mut store, "export").unwrap().clone(),
-        )?;
+        let export = instance.get_export(&mut store, "export").unwrap().clone();
+        linker.define(&mut store, "red", "green", export)?;
         module = Module::new(
             store.engine(),
             r#"(module
@@ -334,7 +328,7 @@ fn instance_pre() -> Result<()> {
     linker.func_wrap("", "", || {})?;
 
     let module = Module::new(&engine, r#"(module (import "" "" (func)))"#)?;
-    let instance_pre = linker.instantiate_pre(&mut Store::new(&engine, ()), &module)?;
+    let instance_pre = linker.instantiate_pre(&module)?;
     instance_pre.instantiate(&mut Store::new(&engine, ()))?;
     instance_pre.instantiate(&mut Store::new(&engine, ()))?;
 
@@ -344,7 +338,7 @@ fn instance_pre() -> Result<()> {
         GlobalType::new(ValType::I32, Mutability::Const),
         1.into(),
     )?;
-    linker.define("", "g", global)?;
+    linker.define(&mut store, "", "g", global)?;
 
     let module = Module::new(
         &engine,
@@ -353,7 +347,7 @@ fn instance_pre() -> Result<()> {
             (import "" "g" (global i32))
         )"#,
     )?;
-    let instance_pre = linker.instantiate_pre(&mut store, &module)?;
+    let instance_pre = linker.instantiate_pre(&module)?;
     instance_pre.instantiate(&mut store)?;
     instance_pre.instantiate(&mut store)?;
     Ok(())
diff --git a/winch/filetests/filetests/x64/basic_add.wat b/winch/filetests/filetests/x64/basic_add.wat
new file mode 100644
index 000000000..3a2f2cb7b
--- /dev/null
+++ b/winch/filetests/filetests/x64/basic_add.wat
@@ -0,0 +1,16 @@
+;;! target = "x86_64"
+
+(module
+    (export "main" (func $main))
+
+    (func $main (result i32)
+	(i32.const 10)
+	(i32.const 20)
+	i32.add)
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 b80a000000           	mov	eax, 0xa
+;;    9:	 83c014               	add	eax, 0x14
+;;    c:	 5d                   	pop	rbp
+;;    d:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/basic_add_with_locals.wat b/winch/filetests/filetests/x64/basic_add_with_locals.wat
new file mode 100644
index 000000000..4bd237d99
--- /dev/null
+++ b/winch/filetests/filetests/x64/basic_add_with_locals.wat
@@ -0,0 +1,32 @@
+;;! target = "x86_64"
+
+(module
+  (export "main" (func $main))
+
+  (func $main (result i32)
+        (local $foo i32)  
+        (local $bar i32)
+        (i32.const 10)
+        (local.set $foo)
+        (i32.const 20)
+        (local.set $bar)
+
+        (local.get $foo)
+        (local.get $bar)
+        i32.add)
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec08             	sub	rsp, 8
+;;    8:	 48c7042400000000     	mov	qword ptr [rsp], 0
+;;   10:	 b80a000000           	mov	eax, 0xa
+;;   15:	 89442404             	mov	dword ptr [rsp + 4], eax
+;;   19:	 b814000000           	mov	eax, 0x14
+;;   1e:	 890424               	mov	dword ptr [rsp], eax
+;;   21:	 8b0424               	mov	eax, dword ptr [rsp]
+;;   24:	 8b4c2404             	mov	ecx, dword ptr [rsp + 4]
+;;   28:	 01c1                 	add	ecx, eax
+;;   2a:	 4889c8               	mov	rax, rcx
+;;   2d:	 4883c408             	add	rsp, 8
+;;   31:	 5d                   	pop	rbp
+;;   32:	 c3                   	ret	
diff --git a/winch/filetests/filetests/x64/basic_add_with_params.wat b/winch/filetests/filetests/x64/basic_add_with_params.wat
new file mode 100644
index 000000000..d3809ac3a
--- /dev/null
+++ b/winch/filetests/filetests/x64/basic_add_with_params.wat
@@ -0,0 +1,22 @@
+;;! target = "x86_64"
+
+(module
+  (export "main" (func $main))
+
+  (func $main (param i32) (param i32) (result i32)
+        (local.get 0)
+        (local.get 1)
+        i32.add)
+)
+;;    0:	 55                   	push	rbp
+;;    1:	 4889e5               	mov	rbp, rsp
+;;    4:	 4883ec08             	sub	rsp, 8
+;;    8:	 897c2404             	mov	dword ptr [rsp + 4], edi
+;;    c:	 893424               	mov	dword ptr [rsp], esi
+;;    f:	 8b0424               	mov	eax, dword ptr [rsp]
+;;   12:	 8b4c2404             	mov	ecx, dword ptr [rsp + 4]
+;;   16:	 01c1                 	add	ecx, eax
+;;   18:	 4889c8               	mov	rax, rcx
+;;   1b:	 4883c408             	add	rsp, 8
+;;   1f:	 5d                   	pop	rbp
+;;   20:	 c3                   	ret