dusk_wasmtime/runtime/
linker.rs

1use crate::func::HostFunc;
2use crate::instance::InstancePre;
3use crate::store::StoreOpaque;
4use crate::{
5    AsContext, AsContextMut, Caller, Engine, Extern, ExternType, Func, FuncType, ImportType,
6    Instance, IntoFunc, Module, StoreContextMut, Val, ValRaw, ValType,
7};
8use anyhow::{bail, Context, Result};
9use log::warn;
10use std::collections::hash_map::{Entry, HashMap};
11#[cfg(feature = "async")]
12use std::future::Future;
13use std::marker;
14#[cfg(feature = "async")]
15use std::pin::Pin;
16use std::sync::Arc;
17
18/// Structure used to link wasm modules/instances together.
19///
20/// This structure is used to assist in instantiating a [`Module`]. A [`Linker`]
21/// is a way of performing name resolution to make instantiating a module easier
22/// than specifying positional imports to [`Instance::new`]. [`Linker`] is a
23/// name-based resolver where names are dynamically defined and then used to
24/// instantiate a [`Module`].
25///
26/// An important method is [`Linker::instantiate`] which takes a module to
27/// instantiate into the provided store. This method will automatically select
28/// all the right imports for the [`Module`] to be instantiated, and will
29/// otherwise return an error if an import isn't satisfied.
30///
31/// ## Name Resolution
32///
33/// As mentioned previously, `Linker` is a form of name resolver. It will be
34/// using the string-based names of imports on a module to attempt to select a
35/// matching item to hook up to it. This name resolution has two-levels of
36/// namespaces, a module level and a name level. Each item is defined within a
37/// module and then has its own name. This basically follows the wasm standard
38/// for modularization.
39///
40/// Names in a `Linker` cannot be defined twice, but allowing duplicates by
41/// shadowing the previous definition can be controlled with the
42/// [`Linker::allow_shadowing`] method.
43///
44/// ## Commands and Reactors
45///
46/// The [`Linker`] type provides conveniences for working with WASI Commands and
47/// Reactors through the [`Linker::module`] method. This will automatically
48/// handle instantiation and calling `_start` and such as appropriate
49/// depending on the inferred type of module.
50///
51/// ## Type parameter `T`
52///
53/// It's worth pointing out that the type parameter `T` on [`Linker<T>`] does
54/// not represent that `T` is stored within a [`Linker`]. Rather the `T` is used
55/// to ensure that linker-defined functions and stores instantiated into all use
56/// the same matching `T` as host state.
57///
58/// ## Multiple `Store`s
59///
60/// The [`Linker`] type is designed to be compatible, in some scenarios, with
61/// instantiation in multiple [`Store`]s. Specifically host-defined functions
62/// created in [`Linker`] with [`Linker::func_new`], [`Linker::func_wrap`], and
63/// their async versions are compatible to instantiate into any [`Store`]. This
64/// enables programs which want to instantiate lots of modules to create one
65/// [`Linker`] value at program start up and use that continuously for each
66/// [`Store`] created over the lifetime of the program.
67///
68/// Note that once [`Store`]-owned items, such as [`Global`], are defined witin
69/// a [`Linker`] then it is no longer compatible with any [`Store`]. At that
70/// point only the [`Store`] that owns the [`Global`] can be used to instantiate
71/// modules.
72///
73/// ## Multiple `Engine`s
74///
75/// The [`Linker`] type is not compatible with usage between multiple [`Engine`]
76/// values. An [`Engine`] is provided when a [`Linker`] is created and only
77/// stores and items which originate from that [`Engine`] can be used with this
78/// [`Linker`]. If more than one [`Engine`] is used with a [`Linker`] then that
79/// may cause a panic at runtime, similar to how if a [`Func`] is used with the
80/// wrong [`Store`] that can also panic at runtime.
81///
82/// [`Store`]: crate::Store
83/// [`Global`]: crate::Global
84pub struct Linker<T> {
85    engine: Engine,
86    string2idx: HashMap<Arc<str>, usize>,
87    strings: Vec<Arc<str>>,
88    map: HashMap<ImportKey, Definition>,
89    allow_shadowing: bool,
90    allow_unknown_exports: bool,
91    _marker: marker::PhantomData<fn() -> T>,
92}
93
94impl<T> Clone for Linker<T> {
95    fn clone(&self) -> Linker<T> {
96        Linker {
97            engine: self.engine.clone(),
98            string2idx: self.string2idx.clone(),
99            strings: self.strings.clone(),
100            map: self.map.clone(),
101            allow_shadowing: self.allow_shadowing,
102            allow_unknown_exports: self.allow_unknown_exports,
103            _marker: self._marker,
104        }
105    }
106}
107
108#[derive(Copy, Clone, Hash, PartialEq, Eq)]
109struct ImportKey {
110    name: usize,
111    module: usize,
112}
113
114#[derive(Clone)]
115pub(crate) enum Definition {
116    Extern(Extern, DefinitionType),
117    HostFunc(Arc<HostFunc>),
118}
119
120/// This is a sort of slimmed down `ExternType` which notably doesn't have a
121/// `FuncType`, which is an allocation, and additionally retains the current
122/// size of the table/memory.
123#[derive(Clone)]
124pub(crate) enum DefinitionType {
125    Func(wasmtime_runtime::VMSharedTypeIndex),
126    Global(wasmtime_environ::Global),
127    // Note that tables and memories store not only the original type
128    // information but additionally the current size of the table/memory, as
129    // this is used during linking since the min size specified in the type may
130    // no longer be the current size of the table/memory.
131    Table(wasmtime_environ::Table, u32),
132    Memory(wasmtime_environ::Memory, u64),
133}
134
135macro_rules! generate_wrap_async_func {
136    ($num:tt $($args:ident)*) => (paste::paste!{
137        /// Asynchronous analog of [`Linker::func_wrap`].
138        ///
139        /// For more information also see
140        /// [`Func::wrapN_async`](crate::Func::wrap1_async).
141        #[allow(non_snake_case)]
142        #[cfg(feature = "async")]
143        #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
144        pub fn [<func_wrap $num _async>]<$($args,)* R>(
145            &mut self,
146            module: &str,
147            name: &str,
148            func: impl for<'a> Fn(Caller<'a, T>, $($args),*) -> Box<dyn Future<Output = R> + Send + 'a> + Send + Sync + 'static,
149        ) -> Result<&mut Self>
150        where
151            $($args: crate::WasmTy,)*
152            R: crate::WasmRet,
153        {
154            assert!(
155                self.engine.config().async_support,
156                concat!(
157                    "cannot use `func_wrap",
158                    $num,
159                    "_async` without enabling async support on the config",
160                ),
161            );
162            self.func_wrap(module, name, move |mut caller: Caller<'_, T>, $($args: $args),*| {
163                let async_cx = caller.store.as_context_mut().0.async_cx().expect("Attempt to start async function on dying fiber");
164                let mut future = Pin::from(func(caller, $($args),*));
165                match unsafe { async_cx.block_on(future.as_mut()) } {
166                    Ok(ret) => ret.into_fallible(),
167                    Err(e) => R::fallible_from_error(e),
168                }
169            })
170        }
171    })
172}
173
174impl<T> Linker<T> {
175    /// Creates a new [`Linker`].
176    ///
177    /// The linker will define functions within the context of the `engine`
178    /// provided and can only instantiate modules for a [`Store`][crate::Store]
179    /// that is also defined within the same [`Engine`]. Usage of stores with
180    /// different [`Engine`]s may cause a panic when used with this [`Linker`].
181    pub fn new(engine: &Engine) -> Linker<T> {
182        Linker {
183            engine: engine.clone(),
184            map: HashMap::new(),
185            string2idx: HashMap::new(),
186            strings: Vec::new(),
187            allow_shadowing: false,
188            allow_unknown_exports: false,
189            _marker: marker::PhantomData,
190        }
191    }
192
193    /// Returns the [`Engine`] this is connected to.
194    pub fn engine(&self) -> &Engine {
195        &self.engine
196    }
197
198    /// Configures whether this [`Linker`] will shadow previous duplicate
199    /// definitions of the same signature.
200    ///
201    /// By default a [`Linker`] will disallow duplicate definitions of the same
202    /// signature. This method, however, can be used to instead allow duplicates
203    /// and have the latest definition take precedence when linking modules.
204    ///
205    /// # Examples
206    ///
207    /// ```
208    /// # use wasmtime::*;
209    /// # fn main() -> anyhow::Result<()> {
210    /// # let engine = Engine::default();
211    /// let mut linker = Linker::<()>::new(&engine);
212    /// linker.func_wrap("", "", || {})?;
213    ///
214    /// // by default, duplicates are disallowed
215    /// assert!(linker.func_wrap("", "", || {}).is_err());
216    ///
217    /// // but shadowing can be configured to be allowed as well
218    /// linker.allow_shadowing(true);
219    /// linker.func_wrap("", "", || {})?;
220    /// # Ok(())
221    /// # }
222    /// ```
223    pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
224        self.allow_shadowing = allow;
225        self
226    }
227
228    /// Configures whether this [`Linker`] will allow unknown exports from
229    /// command modules.
230    ///
231    /// By default a [`Linker`] will error when unknown exports are encountered
232    /// in a command module while using [`Linker::module`].
233    ///
234    /// This method can be used to allow unknown exports from command modules.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// # use wasmtime::*;
240    /// # fn main() -> anyhow::Result<()> {
241    /// # let engine = Engine::default();
242    /// # let module = Module::new(&engine, "(module)")?;
243    /// # let mut store = Store::new(&engine, ());
244    /// let mut linker = Linker::new(&engine);
245    /// linker.allow_unknown_exports(true);
246    /// linker.module(&mut store, "mod", &module)?;
247    /// # Ok(())
248    /// # }
249    /// ```
250    pub fn allow_unknown_exports(&mut self, allow: bool) -> &mut Self {
251        self.allow_unknown_exports = allow;
252        self
253    }
254
255    /// Implement any imports of the given [`Module`] with a function which traps.
256    ///
257    /// By default a [`Linker`] will error when unknown imports are encountered
258    /// in a command module while using [`Linker::module`]. Use this function
259    /// when
260    ///
261    /// This method can be used to allow unknown imports from command modules.
262    ///
263    /// # Examples
264    ///
265    /// ```
266    /// # use wasmtime::*;
267    /// # fn main() -> anyhow::Result<()> {
268    /// # let engine = Engine::default();
269    /// # let module = Module::new(&engine, "(module (import \"unknown\" \"import\" (func)))")?;
270    /// # let mut store = Store::new(&engine, ());
271    /// let mut linker = Linker::new(&engine);
272    /// linker.define_unknown_imports_as_traps(&module)?;
273    /// linker.instantiate(&mut store, &module)?;
274    /// # Ok(())
275    /// # }
276    /// ```
277    #[cfg(any(feature = "cranelift", feature = "winch"))]
278    #[cfg_attr(docsrs, doc(cfg(any(feature = "cranelift", feature = "winch"))))]
279    pub fn define_unknown_imports_as_traps(&mut self, module: &Module) -> anyhow::Result<()> {
280        for import in module.imports() {
281            if let Err(import_err) = self._get_by_import(&import) {
282                if let ExternType::Func(func_ty) = import_err.ty() {
283                    self.func_new(import.module(), import.name(), func_ty, move |_, _, _| {
284                        bail!(import_err.clone());
285                    })?;
286                }
287            }
288        }
289        Ok(())
290    }
291
292    /// Implement any function imports of the [`Module`] with a function that
293    /// ignores its arguments and returns default values.
294    ///
295    /// Default values are either zero or null, depending on the value type.
296    ///
297    /// This method can be used to allow unknown imports from command modules.
298    ///
299    /// # Example
300    ///
301    /// ```
302    /// # use wasmtime::*;
303    /// # fn main() -> anyhow::Result<()> {
304    /// # let engine = Engine::default();
305    /// # let module = Module::new(&engine, "(module (import \"unknown\" \"import\" (func)))")?;
306    /// # let mut store = Store::new(&engine, ());
307    /// let mut linker = Linker::new(&engine);
308    /// linker.define_unknown_imports_as_default_values(&module)?;
309    /// linker.instantiate(&mut store, &module)?;
310    /// # Ok(())
311    /// # }
312    /// ```
313    #[cfg(any(feature = "cranelift", feature = "winch"))]
314    #[cfg_attr(docsrs, doc(cfg(any(feature = "cranelift", feature = "winch"))))]
315    pub fn define_unknown_imports_as_default_values(
316        &mut self,
317        module: &Module,
318    ) -> anyhow::Result<()> {
319        use crate::HeapType;
320
321        for import in module.imports() {
322            if let Err(import_err) = self._get_by_import(&import) {
323                if let ExternType::Func(func_ty) = import_err.ty() {
324                    let result_tys: Vec<_> = func_ty.results().collect();
325
326                    for ty in &result_tys {
327                        if ty.as_ref().map_or(false, |r| !r.is_nullable()) {
328                            bail!("no default value exists for type `{ty}`")
329                        }
330                    }
331
332                    self.func_new(
333                        import.module(),
334                        import.name(),
335                        func_ty,
336                        move |_caller, _args, results| {
337                            for (result, ty) in results.iter_mut().zip(&result_tys) {
338                                *result = match ty {
339                                    ValType::I32 => Val::I32(0),
340                                    ValType::I64 => Val::I64(0),
341                                    ValType::F32 => Val::F32(0.0_f32.to_bits()),
342                                    ValType::F64 => Val::F64(0.0_f64.to_bits()),
343                                    ValType::V128 => Val::V128(0_u128.into()),
344                                    ValType::Ref(r) => {
345                                        debug_assert!(r.is_nullable());
346                                        match r.heap_type() {
347                                            HeapType::Func
348                                            | HeapType::Concrete(_)
349                                            | HeapType::NoFunc => Val::null_func_ref(),
350                                            HeapType::Extern => Val::null_extern_ref(),
351                                            HeapType::Any | HeapType::I31 | HeapType::None => {
352                                                Val::null_any_ref()
353                                            }
354                                        }
355                                    }
356                                };
357                            }
358                            Ok(())
359                        },
360                    )?;
361                }
362            }
363        }
364        Ok(())
365    }
366
367    /// Defines a new item in this [`Linker`].
368    ///
369    /// This method will add a new definition, by name, to this instance of
370    /// [`Linker`]. The `module` and `name` provided are what to name the
371    /// `item`.
372    ///
373    /// # Errors
374    ///
375    /// Returns an error if the `module` and `name` already identify an item
376    /// of the same type as the `item` provided and if shadowing is disallowed.
377    /// For more information see the documentation on [`Linker`].
378    ///
379    /// # Examples
380    ///
381    /// ```
382    /// # use wasmtime::*;
383    /// # fn main() -> anyhow::Result<()> {
384    /// # let engine = Engine::default();
385    /// # let mut store = Store::new(&engine, ());
386    /// let mut linker = Linker::new(&engine);
387    /// let ty = GlobalType::new(ValType::I32, Mutability::Const);
388    /// let global = Global::new(&mut store, ty, Val::I32(0x1234))?;
389    /// linker.define(&store, "host", "offset", global)?;
390    ///
391    /// let wat = r#"
392    ///     (module
393    ///         (import "host" "offset" (global i32))
394    ///         (memory 1)
395    ///         (data (global.get 0) "foo")
396    ///     )
397    /// "#;
398    /// let module = Module::new(&engine, wat)?;
399    /// linker.instantiate(&mut store, &module)?;
400    /// # Ok(())
401    /// # }
402    /// ```
403    pub fn define(
404        &mut self,
405        store: impl AsContext<Data = T>,
406        module: &str,
407        name: &str,
408        item: impl Into<Extern>,
409    ) -> Result<&mut Self> {
410        let store = store.as_context();
411        let key = self.import_key(module, Some(name));
412        self.insert(key, Definition::new(store.0, item.into()))?;
413        Ok(self)
414    }
415
416    /// Same as [`Linker::define`], except only the name of the import is
417    /// provided, not a module name as well.
418    ///
419    /// This is only relevant when working with the module linking proposal
420    /// where one-level names are allowed (in addition to two-level names).
421    /// Otherwise this method need not be used.
422    pub fn define_name(
423        &mut self,
424        store: impl AsContext<Data = T>,
425        name: &str,
426        item: impl Into<Extern>,
427    ) -> Result<&mut Self> {
428        let store = store.as_context();
429        let key = self.import_key(name, None);
430        self.insert(key, Definition::new(store.0, item.into()))?;
431        Ok(self)
432    }
433
434    /// Creates a [`Func::new`]-style function named in this linker.
435    ///
436    /// For more information see [`Linker::func_wrap`].
437    ///
438    /// # Panics
439    ///
440    /// Panics if the given function type is not associated with the same engine
441    /// as this linker.
442    #[cfg(any(feature = "cranelift", feature = "winch"))]
443    #[cfg_attr(docsrs, doc(cfg(any(feature = "cranelift", feature = "winch"))))]
444    pub fn func_new(
445        &mut self,
446        module: &str,
447        name: &str,
448        ty: FuncType,
449        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<()> + Send + Sync + 'static,
450    ) -> Result<&mut Self> {
451        assert!(ty.comes_from_same_engine(self.engine()));
452        let func = HostFunc::new(&self.engine, ty, func);
453        let key = self.import_key(module, Some(name));
454        self.insert(key, Definition::HostFunc(Arc::new(func)))?;
455        Ok(self)
456    }
457
458    /// Creates a [`Func::new_unchecked`]-style function named in this linker.
459    ///
460    /// For more information see [`Linker::func_wrap`].
461    ///
462    /// # Panics
463    ///
464    /// Panics if the given function type is not associated with the same engine
465    /// as this linker.
466    #[cfg(any(feature = "cranelift", feature = "winch"))]
467    #[cfg_attr(docsrs, doc(cfg(any(feature = "cranelift", feature = "winch"))))]
468    pub unsafe fn func_new_unchecked(
469        &mut self,
470        module: &str,
471        name: &str,
472        ty: FuncType,
473        func: impl Fn(Caller<'_, T>, &mut [ValRaw]) -> Result<()> + Send + Sync + 'static,
474    ) -> Result<&mut Self> {
475        assert!(ty.comes_from_same_engine(self.engine()));
476        let func = HostFunc::new_unchecked(&self.engine, ty, func);
477        let key = self.import_key(module, Some(name));
478        self.insert(key, Definition::HostFunc(Arc::new(func)))?;
479        Ok(self)
480    }
481
482    /// Creates a [`Func::new_async`]-style function named in this linker.
483    ///
484    /// For more information see [`Linker::func_wrap`].
485    ///
486    /// # Panics
487    ///
488    /// This method panics in the following situations:
489    ///
490    /// * This linker is not associated with an [async
491    ///   config](crate::Config::async_support).
492    ///
493    /// * If the given function type is not associated with the same engine as
494    ///   this linker.
495    #[cfg(all(feature = "async", feature = "cranelift"))]
496    #[cfg_attr(docsrs, doc(cfg(all(feature = "async", feature = "cranelift"))))]
497    pub fn func_new_async<F>(
498        &mut self,
499        module: &str,
500        name: &str,
501        ty: FuncType,
502        func: F,
503    ) -> Result<&mut Self>
504    where
505        F: for<'a> Fn(
506                Caller<'a, T>,
507                &'a [Val],
508                &'a mut [Val],
509            ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
510            + Send
511            + Sync
512            + 'static,
513    {
514        assert!(
515            self.engine.config().async_support,
516            "cannot use `func_new_async` without enabling async support in the config"
517        );
518        assert!(ty.comes_from_same_engine(self.engine()));
519        self.func_new(module, name, ty, move |mut caller, params, results| {
520            let async_cx = caller
521                .store
522                .as_context_mut()
523                .0
524                .async_cx()
525                .expect("Attempt to spawn new function on dying fiber");
526            let mut future = Pin::from(func(caller, params, results));
527            match unsafe { async_cx.block_on(future.as_mut()) } {
528                Ok(Ok(())) => Ok(()),
529                Ok(Err(trap)) | Err(trap) => Err(trap),
530            }
531        })
532    }
533
534    /// Define a host function within this linker.
535    ///
536    /// For information about how the host function operates, see
537    /// [`Func::wrap`]. That includes information about translating Rust types
538    /// to WebAssembly native types.
539    ///
540    /// This method creates a host-provided function in this linker under the
541    /// provided name. This method is distinct in its capability to create a
542    /// [`Store`](crate::Store)-independent function. This means that the
543    /// function defined here can be used to instantiate instances in multiple
544    /// different stores, or in other words the function can be loaded into
545    /// different stores.
546    ///
547    /// Note that the capability mentioned here applies to all other
548    /// host-function-defining-methods on [`Linker`] as well. All of them can be
549    /// used to create instances of [`Func`] within multiple stores. In a
550    /// multithreaded program, for example, this means that the host functions
551    /// could be called concurrently if different stores are executing on
552    /// different threads.
553    ///
554    /// # Errors
555    ///
556    /// Returns an error if the `module` and `name` already identify an item
557    /// of the same type as the `item` provided and if shadowing is disallowed.
558    /// For more information see the documentation on [`Linker`].
559    ///
560    /// # Examples
561    ///
562    /// ```
563    /// # use wasmtime::*;
564    /// # fn main() -> anyhow::Result<()> {
565    /// # let engine = Engine::default();
566    /// let mut linker = Linker::new(&engine);
567    /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
568    /// linker.func_wrap("host", "log_i32", |x: i32| println!("{}", x))?;
569    /// linker.func_wrap("host", "log_str", |caller: Caller<'_, ()>, ptr: i32, len: i32| {
570    ///     // ...
571    /// })?;
572    ///
573    /// let wat = r#"
574    ///     (module
575    ///         (import "host" "double" (func (param i32) (result i32)))
576    ///         (import "host" "log_i32" (func (param i32)))
577    ///         (import "host" "log_str" (func (param i32 i32)))
578    ///     )
579    /// "#;
580    /// let module = Module::new(&engine, wat)?;
581    ///
582    /// // instantiate in multiple different stores
583    /// for _ in 0..10 {
584    ///     let mut store = Store::new(&engine, ());
585    ///     linker.instantiate(&mut store, &module)?;
586    /// }
587    /// # Ok(())
588    /// # }
589    /// ```
590    pub fn func_wrap<Params, Args>(
591        &mut self,
592        module: &str,
593        name: &str,
594        func: impl IntoFunc<T, Params, Args>,
595    ) -> Result<&mut Self> {
596        let func = HostFunc::wrap(&self.engine, func);
597        let key = self.import_key(module, Some(name));
598        self.insert(key, Definition::HostFunc(Arc::new(func)))?;
599        Ok(self)
600    }
601
602    for_each_function_signature!(generate_wrap_async_func);
603
604    /// Convenience wrapper to define an entire [`Instance`] in this linker.
605    ///
606    /// This function is a convenience wrapper around [`Linker::define`] which
607    /// will define all exports on `instance` into this linker. The module name
608    /// for each export is `module_name`, and the name for each export is the
609    /// name in the instance itself.
610    ///
611    /// Note that when this API is used the [`Linker`] is no longer compatible
612    /// with multi-[`Store`][crate::Store] instantiation because the items
613    /// defined within this store will belong to the `store` provided, and only
614    /// the `store` provided.
615    ///
616    /// # Errors
617    ///
618    /// Returns an error if the any item is redefined twice in this linker (for
619    /// example the same `module_name` was already defined) and shadowing is
620    /// disallowed, or if `instance` comes from a different
621    /// [`Store`](crate::Store) than this [`Linker`] originally was created
622    /// with.
623    ///
624    /// # Panics
625    ///
626    /// Panics if `instance` does not belong to `store`.
627    ///
628    /// # Examples
629    ///
630    /// ```
631    /// # use wasmtime::*;
632    /// # fn main() -> anyhow::Result<()> {
633    /// # let engine = Engine::default();
634    /// # let mut store = Store::new(&engine, ());
635    /// let mut linker = Linker::new(&engine);
636    ///
637    /// // Instantiate a small instance...
638    /// let wat = r#"(module (func (export "run") ))"#;
639    /// let module = Module::new(&engine, wat)?;
640    /// let instance = linker.instantiate(&mut store, &module)?;
641    ///
642    /// // ... and inform the linker that the name of this instance is
643    /// // `instance1`. This defines the `instance1::run` name for our next
644    /// // module to use.
645    /// linker.instance(&mut store, "instance1", instance)?;
646    ///
647    /// let wat = r#"
648    ///     (module
649    ///         (import "instance1" "run" (func $instance1_run))
650    ///         (func (export "run")
651    ///             call $instance1_run
652    ///         )
653    ///     )
654    /// "#;
655    /// let module = Module::new(&engine, wat)?;
656    /// let instance = linker.instantiate(&mut store, &module)?;
657    /// # Ok(())
658    /// # }
659    /// ```
660    pub fn instance(
661        &mut self,
662        mut store: impl AsContextMut<Data = T>,
663        module_name: &str,
664        instance: Instance,
665    ) -> Result<&mut Self> {
666        let mut store = store.as_context_mut();
667        let exports = instance
668            .exports(&mut store)
669            .map(|e| {
670                (
671                    self.import_key(module_name, Some(e.name())),
672                    e.into_extern(),
673                )
674            })
675            .collect::<Vec<_>>();
676        for (key, export) in exports {
677            self.insert(key, Definition::new(store.0, export))?;
678        }
679        Ok(self)
680    }
681
682    /// Define automatic instantiations of a [`Module`] in this linker.
683    ///
684    /// This automatically handles [Commands and Reactors] instantiation and
685    /// initialization.
686    ///
687    /// Exported functions of a Command module may be called directly, however
688    /// instead of having a single instance which is reused for each call,
689    /// each call creates a new instance, which lives for the duration of the
690    /// call. The imports of the Command are resolved once, and reused for
691    /// each instantiation, so all dependencies need to be present at the time
692    /// when `Linker::module` is called.
693    ///
694    /// For Reactors, a single instance is created, and an initialization
695    /// function is called, and then its exports may be called.
696    ///
697    /// Ordinary modules which don't declare themselves to be either Commands
698    /// or Reactors are treated as Reactors without any initialization calls.
699    ///
700    /// [Commands and Reactors]: https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md#current-unstable-abi
701    ///
702    /// # Errors
703    ///
704    /// Returns an error if the any item is redefined twice in this linker (for
705    /// example the same `module_name` was already defined) and shadowing is
706    /// disallowed, if `instance` comes from a different
707    /// [`Store`](crate::Store) than this [`Linker`] originally was created
708    /// with, or if a Reactor initialization function traps.
709    ///
710    /// # Panics
711    ///
712    /// Panics if any item used to instantiate the provided [`Module`] is not
713    /// owned by `store`, or if the `store` provided comes from a different
714    /// [`Engine`] than this [`Linker`].
715    ///
716    /// # Examples
717    ///
718    /// ```
719    /// # use wasmtime::*;
720    /// # fn main() -> anyhow::Result<()> {
721    /// # let engine = Engine::default();
722    /// # let mut store = Store::new(&engine, ());
723    /// let mut linker = Linker::new(&engine);
724    ///
725    /// // Instantiate a small instance and inform the linker that the name of
726    /// // this instance is `instance1`. This defines the `instance1::run` name
727    /// // for our next module to use.
728    /// let wat = r#"(module (func (export "run") ))"#;
729    /// let module = Module::new(&engine, wat)?;
730    /// linker.module(&mut store, "instance1", &module)?;
731    ///
732    /// let wat = r#"
733    ///     (module
734    ///         (import "instance1" "run" (func $instance1_run))
735    ///         (func (export "run")
736    ///             call $instance1_run
737    ///         )
738    ///     )
739    /// "#;
740    /// let module = Module::new(&engine, wat)?;
741    /// let instance = linker.instantiate(&mut store, &module)?;
742    /// # Ok(())
743    /// # }
744    /// ```
745    ///
746    /// For a Command, a new instance is created for each call.
747    ///
748    /// ```
749    /// # use wasmtime::*;
750    /// # fn main() -> anyhow::Result<()> {
751    /// # let engine = Engine::default();
752    /// # let mut store = Store::new(&engine, ());
753    /// let mut linker = Linker::new(&engine);
754    ///
755    /// // Create a Command that attempts to count the number of times it is run, but is
756    /// // foiled by each call getting a new instance.
757    /// let wat = r#"
758    ///     (module
759    ///         (global $counter (mut i32) (i32.const 0))
760    ///         (func (export "_start")
761    ///             (global.set $counter (i32.add (global.get $counter) (i32.const 1)))
762    ///         )
763    ///         (func (export "read_counter") (result i32)
764    ///             (global.get $counter)
765    ///         )
766    ///     )
767    /// "#;
768    /// let module = Module::new(&engine, wat)?;
769    /// linker.module(&mut store, "commander", &module)?;
770    /// let run = linker.get_default(&mut store, "")?
771    ///     .typed::<(), ()>(&store)?
772    ///     .clone();
773    /// run.call(&mut store, ())?;
774    /// run.call(&mut store, ())?;
775    /// run.call(&mut store, ())?;
776    ///
777    /// let wat = r#"
778    ///     (module
779    ///         (import "commander" "_start" (func $commander_start))
780    ///         (import "commander" "read_counter" (func $commander_read_counter (result i32)))
781    ///         (func (export "run") (result i32)
782    ///             call $commander_start
783    ///             call $commander_start
784    ///             call $commander_start
785    ///             call $commander_read_counter
786    ///         )
787    ///     )
788    /// "#;
789    /// let module = Module::new(&engine, wat)?;
790    /// linker.module(&mut store, "", &module)?;
791    /// let run = linker.get(&mut store, "", "run").unwrap().into_func().unwrap();
792    /// let count = run.typed::<(), i32>(&store)?.call(&mut store, ())?;
793    /// assert_eq!(count, 0, "a Command should get a fresh instance on each invocation");
794    ///
795    /// # Ok(())
796    /// # }
797    /// ```
798    #[cfg(any(feature = "cranelift", feature = "winch"))]
799    #[cfg_attr(docsrs, doc(cfg(any(feature = "cranelift", feature = "winch"))))]
800    pub fn module(
801        &mut self,
802        mut store: impl AsContextMut<Data = T>,
803        module_name: &str,
804        module: &Module,
805    ) -> Result<&mut Self>
806    where
807        T: 'static,
808    {
809        // NB: this is intended to function the same as `Linker::module_async`,
810        // they should be kept in sync.
811
812        // This assert isn't strictly necessary since it'll bottom out in the
813        // `HostFunc::to_func` method anyway. This is placed earlier for this
814        // function though to prevent the functions created here from delaying
815        // the panic until they're called.
816        assert!(
817            Engine::same(&self.engine, store.as_context().engine()),
818            "different engines for this linker and the store provided"
819        );
820        match ModuleKind::categorize(module)? {
821            ModuleKind::Command => {
822                self.command(
823                    store,
824                    module_name,
825                    module,
826                    |store, func_ty, export_name, instance_pre| {
827                        Func::new(
828                            store,
829                            func_ty.clone(),
830                            move |mut caller, params, results| {
831                                // Create a new instance for this command execution.
832                                let instance = instance_pre.instantiate(&mut caller)?;
833
834                                // `unwrap()` everything here because we know the instance contains a
835                                // function export with the given name and signature because we're
836                                // iterating over the module it was instantiated from.
837                                instance
838                                    .get_export(&mut caller, &export_name)
839                                    .unwrap()
840                                    .into_func()
841                                    .unwrap()
842                                    .call(&mut caller, params, results)?;
843
844                                Ok(())
845                            },
846                        )
847                    },
848                )
849            }
850            ModuleKind::Reactor => {
851                let instance = self.instantiate(&mut store, &module)?;
852
853                if let Some(export) = instance.get_export(&mut store, "_initialize") {
854                    if let Extern::Func(func) = export {
855                        func.typed::<(), ()>(&store)
856                            .and_then(|f| f.call(&mut store, ()).map_err(Into::into))
857                            .context("calling the Reactor initialization function")?;
858                    }
859                }
860
861                self.instance(store, module_name, instance)
862            }
863        }
864    }
865
866    /// Define automatic instantiations of a [`Module`] in this linker.
867    ///
868    /// This is the same as [`Linker::module`], except for async `Store`s.
869    #[cfg(all(feature = "async", feature = "cranelift"))]
870    #[cfg_attr(docsrs, doc(cfg(all(feature = "async", feature = "cranelift"))))]
871    pub async fn module_async(
872        &mut self,
873        mut store: impl AsContextMut<Data = T>,
874        module_name: &str,
875        module: &Module,
876    ) -> Result<&mut Self>
877    where
878        T: Send + 'static,
879    {
880        // NB: this is intended to function the same as `Linker::module`, they
881        // should be kept in sync.
882        assert!(
883            Engine::same(&self.engine, store.as_context().engine()),
884            "different engines for this linker and the store provided"
885        );
886        match ModuleKind::categorize(module)? {
887            ModuleKind::Command => self.command(
888                store,
889                module_name,
890                module,
891                |store, func_ty, export_name, instance_pre| {
892                    let upvars = Arc::new((instance_pre, export_name));
893                    Func::new_async(
894                        store,
895                        func_ty.clone(),
896                        move |mut caller, params, results| {
897                            let upvars = upvars.clone();
898                            Box::new(async move {
899                                let (instance_pre, export_name) = &*upvars;
900                                let instance = instance_pre.instantiate_async(&mut caller).await?;
901
902                                instance
903                                    .get_export(&mut caller, &export_name)
904                                    .unwrap()
905                                    .into_func()
906                                    .unwrap()
907                                    .call_async(&mut caller, params, results)
908                                    .await?;
909                                Ok(())
910                            })
911                        },
912                    )
913                },
914            ),
915            ModuleKind::Reactor => {
916                let instance = self.instantiate_async(&mut store, &module).await?;
917
918                if let Some(export) = instance.get_export(&mut store, "_initialize") {
919                    if let Extern::Func(func) = export {
920                        let func = func
921                            .typed::<(), ()>(&store)
922                            .context("loading the Reactor initialization function")?;
923                        func.call_async(&mut store, ())
924                            .await
925                            .context("calling the Reactor initialization function")?;
926                    }
927                }
928
929                self.instance(store, module_name, instance)
930            }
931        }
932    }
933
934    fn command(
935        &mut self,
936        mut store: impl AsContextMut<Data = T>,
937        module_name: &str,
938        module: &Module,
939        mk_func: impl Fn(&mut StoreContextMut<T>, &FuncType, String, InstancePre<T>) -> Func,
940    ) -> Result<&mut Self>
941    where
942        T: 'static,
943    {
944        let mut store = store.as_context_mut();
945        for export in module.exports() {
946            if let Some(func_ty) = export.ty().func() {
947                let instance_pre = self.instantiate_pre(module)?;
948                let export_name = export.name().to_owned();
949                let func = mk_func(&mut store, func_ty, export_name, instance_pre);
950                let key = self.import_key(module_name, Some(export.name()));
951                self.insert(key, Definition::new(store.0, func.into()))?;
952            } else if export.name() == "memory" && export.ty().memory().is_some() {
953                // Allow an exported "memory" memory for now.
954            } else if export.name() == "__indirect_function_table" && export.ty().table().is_some()
955            {
956                // Allow an exported "__indirect_function_table" table for now.
957            } else if export.name() == "table" && export.ty().table().is_some() {
958                // Allow an exported "table" table for now.
959            } else if export.name() == "__data_end" && export.ty().global().is_some() {
960                // Allow an exported "__data_end" memory for compatibility with toolchains
961                // which use --export-dynamic, which unfortunately doesn't work the way
962                // we want it to.
963                warn!("command module exporting '__data_end' is deprecated");
964            } else if export.name() == "__heap_base" && export.ty().global().is_some() {
965                // Allow an exported "__data_end" memory for compatibility with toolchains
966                // which use --export-dynamic, which unfortunately doesn't work the way
967                // we want it to.
968                warn!("command module exporting '__heap_base' is deprecated");
969            } else if export.name() == "__dso_handle" && export.ty().global().is_some() {
970                // Allow an exported "__dso_handle" memory for compatibility with toolchains
971                // which use --export-dynamic, which unfortunately doesn't work the way
972                // we want it to.
973                warn!("command module exporting '__dso_handle' is deprecated")
974            } else if export.name() == "__rtti_base" && export.ty().global().is_some() {
975                // Allow an exported "__rtti_base" memory for compatibility with
976                // AssemblyScript.
977                warn!("command module exporting '__rtti_base' is deprecated; pass `--runtime half` to the AssemblyScript compiler");
978            } else if !self.allow_unknown_exports {
979                bail!("command export '{}' is not a function", export.name());
980            }
981        }
982
983        Ok(self)
984    }
985
986    /// Aliases one item's name as another.
987    ///
988    /// This method will alias an item with the specified `module` and `name`
989    /// under a new name of `as_module` and `as_name`.
990    ///
991    /// # Errors
992    ///
993    /// Returns an error if any shadowing violations happen while defining new
994    /// items, or if the original item wasn't defined.
995    pub fn alias(
996        &mut self,
997        module: &str,
998        name: &str,
999        as_module: &str,
1000        as_name: &str,
1001    ) -> Result<&mut Self> {
1002        let src = self.import_key(module, Some(name));
1003        let dst = self.import_key(as_module, Some(as_name));
1004        match self.map.get(&src).cloned() {
1005            Some(item) => self.insert(dst, item)?,
1006            None => bail!("no item named `{}::{}` defined", module, name),
1007        }
1008        Ok(self)
1009    }
1010
1011    /// Aliases one module's name as another.
1012    ///
1013    /// This method will alias all currently defined under `module` to also be
1014    /// defined under the name `as_module` too.
1015    ///
1016    /// # Errors
1017    ///
1018    /// Returns an error if any shadowing violations happen while defining new
1019    /// items.
1020    pub fn alias_module(&mut self, module: &str, as_module: &str) -> Result<()> {
1021        let module = self.intern_str(module);
1022        let as_module = self.intern_str(as_module);
1023        let items = self
1024            .map
1025            .iter()
1026            .filter(|(key, _def)| key.module == module)
1027            .map(|(key, def)| (key.name, def.clone()))
1028            .collect::<Vec<_>>();
1029        for (name, item) in items {
1030            self.insert(
1031                ImportKey {
1032                    module: as_module,
1033                    name,
1034                },
1035                item,
1036            )?;
1037        }
1038        Ok(())
1039    }
1040
1041    fn insert(&mut self, key: ImportKey, item: Definition) -> Result<()> {
1042        match self.map.entry(key) {
1043            Entry::Occupied(_) if !self.allow_shadowing => {
1044                let module = &self.strings[key.module];
1045                let desc = match self.strings.get(key.name) {
1046                    Some(name) => format!("{}::{}", module, name),
1047                    None => module.to_string(),
1048                };
1049                bail!("import of `{}` defined twice", desc)
1050            }
1051            Entry::Occupied(mut o) => {
1052                o.insert(item);
1053            }
1054            Entry::Vacant(v) => {
1055                v.insert(item);
1056            }
1057        }
1058        Ok(())
1059    }
1060
1061    fn import_key(&mut self, module: &str, name: Option<&str>) -> ImportKey {
1062        ImportKey {
1063            module: self.intern_str(module),
1064            name: name
1065                .map(|name| self.intern_str(name))
1066                .unwrap_or(usize::max_value()),
1067        }
1068    }
1069
1070    fn intern_str(&mut self, string: &str) -> usize {
1071        if let Some(idx) = self.string2idx.get(string) {
1072            return *idx;
1073        }
1074        let string: Arc<str> = string.into();
1075        let idx = self.strings.len();
1076        self.strings.push(string.clone());
1077        self.string2idx.insert(string, idx);
1078        idx
1079    }
1080
1081    /// Attempts to instantiate the `module` provided.
1082    ///
1083    /// This method will attempt to assemble a list of imports that correspond
1084    /// to the imports required by the [`Module`] provided. This list
1085    /// of imports is then passed to [`Instance::new`] to continue the
1086    /// instantiation process.
1087    ///
1088    /// Each import of `module` will be looked up in this [`Linker`] and must
1089    /// have previously been defined. If it was previously defined with an
1090    /// incorrect signature or if it was not previously defined then an error
1091    /// will be returned because the import can not be satisfied.
1092    ///
1093    /// Per the WebAssembly spec, instantiation includes running the module's
1094    /// start function, if it has one (not to be confused with the `_start`
1095    /// function, which is not run).
1096    ///
1097    /// # Errors
1098    ///
1099    /// This method can fail because an import may not be found, or because
1100    /// instantiation itself may fail. For information on instantiation
1101    /// failures see [`Instance::new`]. If an import is not found, the error
1102    /// may be downcast to an [`UnknownImportError`].
1103    ///
1104    ///
1105    /// # Panics
1106    ///
1107    /// Panics if any item used to instantiate `module` is not owned by
1108    /// `store`. Additionally this will panic if the [`Engine`] that the `store`
1109    /// belongs to is different than this [`Linker`].
1110    ///
1111    /// # Examples
1112    ///
1113    /// ```
1114    /// # use wasmtime::*;
1115    /// # fn main() -> anyhow::Result<()> {
1116    /// # let engine = Engine::default();
1117    /// # let mut store = Store::new(&engine, ());
1118    /// let mut linker = Linker::new(&engine);
1119    /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
1120    ///
1121    /// let wat = r#"
1122    ///     (module
1123    ///         (import "host" "double" (func (param i32) (result i32)))
1124    ///     )
1125    /// "#;
1126    /// let module = Module::new(&engine, wat)?;
1127    /// linker.instantiate(&mut store, &module)?;
1128    /// # Ok(())
1129    /// # }
1130    /// ```
1131    pub fn instantiate(
1132        &self,
1133        mut store: impl AsContextMut<Data = T>,
1134        module: &Module,
1135    ) -> Result<Instance> {
1136        self._instantiate_pre(module, Some(store.as_context_mut().0))?
1137            .instantiate(store)
1138    }
1139
1140    /// Attempts to instantiate the `module` provided. This is the same as
1141    /// [`Linker::instantiate`], except for async `Store`s.
1142    #[cfg(feature = "async")]
1143    #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
1144    pub async fn instantiate_async(
1145        &self,
1146        mut store: impl AsContextMut<Data = T>,
1147        module: &Module,
1148    ) -> Result<Instance>
1149    where
1150        T: Send,
1151    {
1152        self._instantiate_pre(module, Some(store.as_context_mut().0))?
1153            .instantiate_async(store)
1154            .await
1155    }
1156
1157    /// Performs all checks necessary for instantiating `module` with this
1158    /// linker, except that instantiation doesn't actually finish.
1159    ///
1160    /// This method is used for front-loading type-checking information as well
1161    /// as collecting the imports to use to instantiate a module with. The
1162    /// returned [`InstancePre`] represents a ready-to-be-instantiated module,
1163    /// which can also be instantiated multiple times if desired.
1164    ///
1165    /// # Errors
1166    ///
1167    /// Returns an error which may be downcast to an [`UnknownImportError`] if
1168    /// the module has any unresolvable imports.
1169    ///
1170    /// # Examples
1171    ///
1172    /// ```
1173    /// # use wasmtime::*;
1174    /// # fn main() -> anyhow::Result<()> {
1175    /// # let engine = Engine::default();
1176    /// # let mut store = Store::new(&engine, ());
1177    /// let mut linker = Linker::new(&engine);
1178    /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
1179    ///
1180    /// let wat = r#"
1181    ///     (module
1182    ///         (import "host" "double" (func (param i32) (result i32)))
1183    ///     )
1184    /// "#;
1185    /// let module = Module::new(&engine, wat)?;
1186    /// let instance_pre = linker.instantiate_pre(&module)?;
1187    ///
1188    /// // Finish instantiation after the type-checking has all completed...
1189    /// let instance = instance_pre.instantiate(&mut store)?;
1190    ///
1191    /// // ... and we can even continue to keep instantiating if desired!
1192    /// instance_pre.instantiate(&mut store)?;
1193    /// instance_pre.instantiate(&mut store)?;
1194    ///
1195    /// // Note that functions defined in a linker with `func_wrap` and similar
1196    /// // constructors are not owned by any particular `Store`, so we can also
1197    /// // instantiate our `instance_pre` in other stores because no imports
1198    /// // belong to the original store.
1199    /// let mut new_store = Store::new(&engine, ());
1200    /// instance_pre.instantiate(&mut new_store)?;
1201    /// # Ok(())
1202    /// # }
1203    /// ```
1204    pub fn instantiate_pre(&self, module: &Module) -> Result<InstancePre<T>> {
1205        self._instantiate_pre(module, None)
1206    }
1207
1208    /// This is split out to optionally take a `store` so that when the
1209    /// `.instantiate` API is used we can get fresh up-to-date type information
1210    /// for memories and their current size, if necessary.
1211    ///
1212    /// Note that providing a `store` here is not required for correctness
1213    /// per-se. If one is not provided, such as the with the `instantiate_pre`
1214    /// API, then the type information used for memories and tables will reflect
1215    /// their size when inserted into the linker rather than their current size.
1216    /// This isn't expected to be much of a problem though since
1217    /// per-store-`Linker` types are likely using `.instantiate(..)` and
1218    /// per-`Engine` linkers don't have memories/tables in them.
1219    fn _instantiate_pre(
1220        &self,
1221        module: &Module,
1222        store: Option<&StoreOpaque>,
1223    ) -> Result<InstancePre<T>> {
1224        let mut imports = module
1225            .imports()
1226            .map(|import| self._get_by_import(&import))
1227            .collect::<Result<Vec<_>, _>>()?;
1228        if let Some(store) = store {
1229            for import in imports.iter_mut() {
1230                import.update_size(store);
1231            }
1232        }
1233        unsafe { InstancePre::new(module, imports) }
1234    }
1235
1236    /// Returns an iterator over all items defined in this `Linker`, in
1237    /// arbitrary order.
1238    ///
1239    /// The iterator returned will yield 3-tuples where the first two elements
1240    /// are the module name and item name for the external item, and the third
1241    /// item is the item itself that is defined.
1242    ///
1243    /// Note that multiple `Extern` items may be defined for the same
1244    /// module/name pair.
1245    ///
1246    /// # Panics
1247    ///
1248    /// This function will panic if the `store` provided does not come from the
1249    /// same [`Engine`] that this linker was created with.
1250    pub fn iter<'a: 'p, 'p>(
1251        &'a self,
1252        mut store: impl AsContextMut<Data = T> + 'p,
1253    ) -> impl Iterator<Item = (&str, &str, Extern)> + 'p {
1254        self.map.iter().map(move |(key, item)| {
1255            let store = store.as_context_mut();
1256            (
1257                &*self.strings[key.module],
1258                &*self.strings[key.name],
1259                // Should be safe since `T` is connecting the linker and store
1260                unsafe { item.to_extern(store.0) },
1261            )
1262        })
1263    }
1264
1265    /// Looks up a previously defined value in this [`Linker`], identified by
1266    /// the names provided.
1267    ///
1268    /// Returns `None` if this name was not previously defined in this
1269    /// [`Linker`].
1270    ///
1271    /// # Panics
1272    ///
1273    /// This function will panic if the `store` provided does not come from the
1274    /// same [`Engine`] that this linker was created with.
1275    pub fn get(
1276        &self,
1277        mut store: impl AsContextMut<Data = T>,
1278        module: &str,
1279        name: &str,
1280    ) -> Option<Extern> {
1281        let store = store.as_context_mut().0;
1282        // Should be safe since `T` is connecting the linker and store
1283        Some(unsafe { self._get(module, name)?.to_extern(store) })
1284    }
1285
1286    fn _get(&self, module: &str, name: &str) -> Option<&Definition> {
1287        let key = ImportKey {
1288            module: *self.string2idx.get(module)?,
1289            name: *self.string2idx.get(name)?,
1290        };
1291        self.map.get(&key)
1292    }
1293
1294    /// Looks up a value in this `Linker` which matches the `import` type
1295    /// provided.
1296    ///
1297    /// Returns `None` if no match was found.
1298    ///
1299    /// # Panics
1300    ///
1301    /// This function will panic if the `store` provided does not come from the
1302    /// same [`Engine`] that this linker was created with.
1303    pub fn get_by_import(
1304        &self,
1305        mut store: impl AsContextMut<Data = T>,
1306        import: &ImportType,
1307    ) -> Option<Extern> {
1308        let store = store.as_context_mut().0;
1309        // Should be safe since `T` is connecting the linker and store
1310        Some(unsafe { self._get_by_import(import).ok()?.to_extern(store) })
1311    }
1312
1313    fn _get_by_import(&self, import: &ImportType) -> Result<Definition, UnknownImportError> {
1314        match self._get(import.module(), import.name()) {
1315            Some(item) => Ok(item.clone()),
1316            None => Err(UnknownImportError::new(import)),
1317        }
1318    }
1319
1320    /// Returns the "default export" of a module.
1321    ///
1322    /// An export with an empty string is considered to be a "default export".
1323    /// "_start" is also recognized for compatibility.
1324    ///
1325    /// # Panics
1326    ///
1327    /// Panics if the default function found is not owned by `store`. This
1328    /// function will also panic if the `store` provided does not come from the
1329    /// same [`Engine`] that this linker was created with.
1330    pub fn get_default(
1331        &self,
1332        mut store: impl AsContextMut<Data = T>,
1333        module: &str,
1334    ) -> Result<Func> {
1335        if let Some(external) = self.get(&mut store, module, "") {
1336            if let Extern::Func(func) = external {
1337                return Ok(func.clone());
1338            }
1339            bail!("default export in '{}' is not a function", module);
1340        }
1341
1342        // For compatibility, also recognize "_start".
1343        if let Some(external) = self.get(&mut store, module, "_start") {
1344            if let Extern::Func(func) = external {
1345                return Ok(func.clone());
1346            }
1347            bail!("`_start` in '{}' is not a function", module);
1348        }
1349
1350        // Otherwise return a no-op function.
1351        Ok(Func::wrap(store, || {}))
1352    }
1353}
1354
1355impl<T> Default for Linker<T> {
1356    fn default() -> Linker<T> {
1357        Linker::new(&Engine::default())
1358    }
1359}
1360
1361impl Definition {
1362    fn new(store: &StoreOpaque, item: Extern) -> Definition {
1363        let ty = DefinitionType::from(store, &item);
1364        Definition::Extern(item, ty)
1365    }
1366
1367    pub(crate) fn ty(&self) -> DefinitionType {
1368        match self {
1369            Definition::Extern(_, ty) => ty.clone(),
1370            Definition::HostFunc(func) => DefinitionType::Func(func.sig_index()),
1371        }
1372    }
1373
1374    /// Note the unsafety here is due to calling `HostFunc::to_func`. The
1375    /// requirement here is that the `T` that was originally used to create the
1376    /// `HostFunc` matches the `T` on the store.
1377    pub(crate) unsafe fn to_extern(&self, store: &mut StoreOpaque) -> Extern {
1378        match self {
1379            Definition::Extern(e, _) => e.clone(),
1380            Definition::HostFunc(func) => func.to_func(store).into(),
1381        }
1382    }
1383
1384    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
1385        match self {
1386            Definition::Extern(e, _) => e.comes_from_same_store(store),
1387            Definition::HostFunc(_func) => true,
1388        }
1389    }
1390
1391    fn update_size(&mut self, store: &StoreOpaque) {
1392        match self {
1393            Definition::Extern(Extern::Memory(m), DefinitionType::Memory(_, size)) => {
1394                *size = m.internal_size(store);
1395            }
1396            Definition::Extern(Extern::SharedMemory(m), DefinitionType::Memory(_, size)) => {
1397                *size = m.size();
1398            }
1399            Definition::Extern(Extern::Table(m), DefinitionType::Table(_, size)) => {
1400                *size = m.internal_size(store);
1401            }
1402            _ => {}
1403        }
1404    }
1405}
1406
1407impl DefinitionType {
1408    pub(crate) fn from(store: &StoreOpaque, item: &Extern) -> DefinitionType {
1409        let data = store.store_data();
1410        match item {
1411            Extern::Func(f) => DefinitionType::Func(f.type_index(data)),
1412            Extern::Table(t) => DefinitionType::Table(*t.wasmtime_ty(data), t.internal_size(store)),
1413            Extern::Global(t) => DefinitionType::Global(*t.wasmtime_ty(data)),
1414            Extern::Memory(t) => {
1415                DefinitionType::Memory(*t.wasmtime_ty(data), t.internal_size(store))
1416            }
1417            Extern::SharedMemory(t) => DefinitionType::Memory(*t.ty().wasmtime_memory(), t.size()),
1418        }
1419    }
1420
1421    pub(crate) fn desc(&self) -> &'static str {
1422        match self {
1423            DefinitionType::Func(_) => "function",
1424            DefinitionType::Table(..) => "table",
1425            DefinitionType::Memory(..) => "memory",
1426            DefinitionType::Global(_) => "global",
1427        }
1428    }
1429}
1430
1431/// Modules can be interpreted either as Commands or Reactors.
1432enum ModuleKind {
1433    /// The instance is a Command, meaning an instance is created for each
1434    /// exported function and lives for the duration of the function call.
1435    Command,
1436
1437    /// The instance is a Reactor, meaning one instance is created which
1438    /// may live across multiple calls.
1439    Reactor,
1440}
1441
1442impl ModuleKind {
1443    /// Determine whether the given module is a Command or a Reactor.
1444    fn categorize(module: &Module) -> Result<ModuleKind> {
1445        let command_start = module.get_export("_start");
1446        let reactor_start = module.get_export("_initialize");
1447        match (command_start, reactor_start) {
1448            (Some(command_start), None) => {
1449                if let Some(_) = command_start.func() {
1450                    Ok(ModuleKind::Command)
1451                } else {
1452                    bail!("`_start` must be a function")
1453                }
1454            }
1455            (None, Some(reactor_start)) => {
1456                if let Some(_) = reactor_start.func() {
1457                    Ok(ModuleKind::Reactor)
1458                } else {
1459                    bail!("`_initialize` must be a function")
1460                }
1461            }
1462            (None, None) => {
1463                // Module declares neither of the recognized functions, so treat
1464                // it as a reactor with no initialization function.
1465                Ok(ModuleKind::Reactor)
1466            }
1467            (Some(_), Some(_)) => {
1468                // Module declares itself to be both a Command and a Reactor.
1469                bail!("Program cannot be both a Command and a Reactor")
1470            }
1471        }
1472    }
1473}
1474
1475/// Error for an unresolvable import.
1476///
1477/// Returned - wrapped in an [`anyhow::Error`] - by [`Linker::instantiate`] and
1478/// related methods for modules with unresolvable imports.
1479#[derive(Clone, Debug)]
1480pub struct UnknownImportError {
1481    module: String,
1482    name: String,
1483    ty: ExternType,
1484}
1485
1486impl UnknownImportError {
1487    fn new(import: &ImportType) -> Self {
1488        Self {
1489            module: import.module().to_string(),
1490            name: import.name().to_string(),
1491            ty: import.ty(),
1492        }
1493    }
1494
1495    /// Returns the module name that the unknown import was expected to come from.
1496    pub fn module(&self) -> &str {
1497        &self.module
1498    }
1499
1500    /// Returns the field name of the module that the unknown import was expected to come from.
1501    pub fn name(&self) -> &str {
1502        &self.name
1503    }
1504
1505    /// Returns the type of the unknown import.
1506    pub fn ty(&self) -> ExternType {
1507        self.ty.clone()
1508    }
1509}
1510
1511impl std::fmt::Display for UnknownImportError {
1512    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1513        write!(
1514            f,
1515            "unknown import: `{}::{}` has not been defined",
1516            self.module, self.name,
1517        )
1518    }
1519}
1520
1521impl std::error::Error for UnknownImportError {}