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