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