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