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 log::warn;
16
17/// Structure used to link wasm modules/instances together.
18///
19/// This structure is used to assist in instantiating a [`Module`]. A [`Linker`]
20/// is a way of performing name resolution to make instantiating a module easier
21/// than specifying positional imports to [`Instance::new`]. [`Linker`] is a
22/// name-based resolver where names are dynamically defined and then used to
23/// instantiate a [`Module`].
24///
25/// An important method is [`Linker::instantiate`] which takes a module to
26/// instantiate into the provided store. This method will automatically select
27/// all the right imports for the [`Module`] to be instantiated, and will
28/// otherwise return an error if an import isn't satisfied.
29///
30/// ## Name Resolution
31///
32/// As mentioned previously, `Linker` is a form of name resolver. It will be
33/// using the string-based names of imports on a module to attempt to select a
34/// matching item to hook up to it. This name resolution has two-levels of
35/// namespaces, a module level and a name level. Each item is defined within a
36/// module and then has its own name. This basically follows the wasm standard
37/// for modularization.
38///
39/// Names in a `Linker` cannot be defined twice, but allowing duplicates by
40/// shadowing the previous definition can be controlled with the
41/// [`Linker::allow_shadowing`] method.
42///
43/// ## Commands and Reactors
44///
45/// The [`Linker`] type provides conveniences for working with WASI Commands and
46/// Reactors through the [`Linker::module`] method. This will automatically
47/// handle instantiation and calling `_start` and such as appropriate
48/// depending on the inferred type of module.
49///
50/// ## Type parameter `T`
51///
52/// It's worth pointing out that the type parameter `T` on [`Linker<T>`] does
53/// not represent that `T` is stored within a [`Linker`]. Rather the `T` is used
54/// to ensure that linker-defined functions and stores instantiated into all use
55/// the same matching `T` as host state.
56///
57/// ## Multiple `Store`s
58///
59/// The [`Linker`] type is designed to be compatible, in some scenarios, with
60/// instantiation in multiple [`Store`]s. Specifically host-defined functions
61/// created in [`Linker`] with [`Linker::func_new`], [`Linker::func_wrap`], and
62/// their async versions are compatible to instantiate into any [`Store`]. This
63/// enables programs which want to instantiate lots of modules to create one
64/// [`Linker`] value at program start up and use that continuously for each
65/// [`Store`] created over the lifetime of the program.
66///
67/// Note that once [`Store`]-owned items, such as [`Global`], are defined within
68/// a [`Linker`] then it is no longer compatible with any [`Store`]. At that
69/// point only the [`Store`] that owns the [`Global`] can be used to instantiate
70/// modules.
71///
72/// ## Multiple `Engine`s
73///
74/// The [`Linker`] type is not compatible with usage between multiple [`Engine`]
75/// values. An [`Engine`] is provided when a [`Linker`] is created and only
76/// stores and items which originate from that [`Engine`] can be used with this
77/// [`Linker`]. If more than one [`Engine`] is used with a [`Linker`] then that
78/// may cause a panic at runtime, similar to how if a [`Func`] is used with the
79/// wrong [`Store`] that can also panic at runtime.
80///
81/// [`Store`]: crate::Store
82/// [`Global`]: crate::Global
83pub struct Linker<T> {
84 engine: Engine,
85 string2idx: HashMap<Arc<str>, usize>,
86 strings: Vec<Arc<str>>,
87 map: HashMap<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 string2idx: self.string2idx.clone(),
104 strings: self.strings.clone(),
105 map: self.map.clone(),
106 allow_shadowing: self.allow_shadowing,
107 allow_unknown_exports: self.allow_unknown_exports,
108 _marker: self._marker,
109 }
110 }
111}
112
113#[derive(Copy, Clone, Hash, PartialEq, Eq)]
114struct ImportKey {
115 name: usize,
116 module: usize,
117}
118
119#[derive(Clone)]
120pub(crate) enum Definition {
121 Extern(Extern, DefinitionType),
122 HostFunc(Arc<HostFunc>),
123}
124
125/// This is a sort of slimmed down `ExternType` which notably doesn't have a
126/// `FuncType`, which is an allocation, and additionally retains the current
127/// size of the table/memory.
128#[derive(Clone, Debug)]
129pub(crate) enum DefinitionType {
130 Func(wasmtime_environ::VMSharedTypeIndex),
131 Global(wasmtime_environ::Global),
132 // Note that tables and memories store not only the original type
133 // information but additionally the current size of the table/memory, as
134 // this is used during linking since the min size specified in the type may
135 // no longer be the current size of the table/memory.
136 Table(wasmtime_environ::Table, u64),
137 Memory(wasmtime_environ::Memory, u64),
138 Tag(wasmtime_environ::Tag),
139}
140
141impl<T> Linker<T> {
142 /// Creates a new [`Linker`].
143 ///
144 /// The linker will define functions within the context of the `engine`
145 /// provided and can only instantiate modules for a [`Store`][crate::Store]
146 /// that is also defined within the same [`Engine`]. Usage of stores with
147 /// different [`Engine`]s may cause a panic when used with this [`Linker`].
148 pub fn new(engine: &Engine) -> Linker<T> {
149 Linker {
150 engine: engine.clone(),
151 map: HashMap::new(),
152 string2idx: HashMap::new(),
153 strings: Vec::new(),
154 allow_shadowing: false,
155 allow_unknown_exports: false,
156 _marker: marker::PhantomData,
157 }
158 }
159
160 /// Returns the [`Engine`] this is connected to.
161 pub fn engine(&self) -> &Engine {
162 &self.engine
163 }
164
165 /// Configures whether this [`Linker`] will shadow previous duplicate
166 /// definitions of the same signature.
167 ///
168 /// By default a [`Linker`] will disallow duplicate definitions of the same
169 /// signature. This method, however, can be used to instead allow duplicates
170 /// and have the latest definition take precedence when linking modules.
171 ///
172 /// # Examples
173 ///
174 /// ```
175 /// # use wasmtime::*;
176 /// # fn main() -> Result<()> {
177 /// # let engine = Engine::default();
178 /// let mut linker = Linker::<()>::new(&engine);
179 /// linker.func_wrap("", "", || {})?;
180 ///
181 /// // by default, duplicates are disallowed
182 /// assert!(linker.func_wrap("", "", || {}).is_err());
183 ///
184 /// // but shadowing can be configured to be allowed as well
185 /// linker.allow_shadowing(true);
186 /// linker.func_wrap("", "", || {})?;
187 /// # Ok(())
188 /// # }
189 /// ```
190 pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
191 self.allow_shadowing = allow;
192 self
193 }
194
195 /// Configures whether this [`Linker`] will allow unknown exports from
196 /// command modules.
197 ///
198 /// By default a [`Linker`] will error when unknown exports are encountered
199 /// in a command module while using [`Linker::module`].
200 ///
201 /// This method can be used to allow unknown exports from command modules.
202 ///
203 /// # Examples
204 ///
205 /// ```
206 /// # use wasmtime::*;
207 /// # fn main() -> Result<()> {
208 /// # let engine = Engine::default();
209 /// # let module = Module::new(&engine, "(module)")?;
210 /// # let mut store = Store::new(&engine, ());
211 /// let mut linker = Linker::new(&engine);
212 /// linker.allow_unknown_exports(true);
213 /// linker.module(&mut store, "mod", &module)?;
214 /// # Ok(())
215 /// # }
216 /// ```
217 pub fn allow_unknown_exports(&mut self, allow: bool) -> &mut Self {
218 self.allow_unknown_exports = allow;
219 self
220 }
221
222 /// Implement any imports of the given [`Module`] with a function which traps.
223 ///
224 /// By default a [`Linker`] will error when unknown imports are encountered
225 /// in a command module while using [`Linker::module`].
226 ///
227 /// This method can be used to allow unknown imports from command modules.
228 ///
229 /// # Examples
230 ///
231 /// ```
232 /// # use wasmtime::*;
233 /// # fn main() -> Result<()> {
234 /// # let engine = Engine::default();
235 /// # let module = Module::new(&engine, "(module (import \"unknown\" \"import\" (func)))")?;
236 /// # let mut store = Store::new(&engine, ());
237 /// let mut linker = Linker::new(&engine);
238 /// linker.define_unknown_imports_as_traps(&module)?;
239 /// linker.instantiate(&mut store, &module)?;
240 /// # Ok(())
241 /// # }
242 /// ```
243 pub fn define_unknown_imports_as_traps(&mut self, module: &Module) -> Result<()>
244 where
245 T: 'static,
246 {
247 for import in module.imports() {
248 if let Err(import_err) = self._get_by_import(&import) {
249 if let ExternType::Func(func_ty) = import_err.ty() {
250 self.func_new(import.module(), import.name(), func_ty, move |_, _, _| {
251 bail!(import_err.clone());
252 })?;
253 }
254 }
255 }
256 Ok(())
257 }
258
259 /// Implement any function imports of the [`Module`] with a function that
260 /// ignores its arguments and returns default values.
261 ///
262 /// Default values are either zero or null, depending on the value type.
263 ///
264 /// This method can be used to allow unknown imports from command modules.
265 ///
266 /// # Example
267 ///
268 /// ```
269 /// # use wasmtime::*;
270 /// # fn main() -> Result<()> {
271 /// # let engine = Engine::default();
272 /// # let module = Module::new(&engine, "(module (import \"unknown\" \"import\" (func)))")?;
273 /// # let mut store = Store::new(&engine, ());
274 /// let mut linker = Linker::new(&engine);
275 /// linker.define_unknown_imports_as_default_values(&mut store, &module)?;
276 /// linker.instantiate(&mut store, &module)?;
277 /// # Ok(())
278 /// # }
279 /// ```
280 pub fn define_unknown_imports_as_default_values(
281 &mut self,
282 mut store: impl AsContextMut<Data = T>,
283 module: &Module,
284 ) -> Result<()>
285 where
286 T: 'static,
287 {
288 let mut store = store.as_context_mut();
289 for import in module.imports() {
290 if let Err(import_err) = self._get_by_import(&import) {
291 let default_extern =
292 import_err.ty().default_value(&mut store).with_context(|| {
293 format_err!(
294 "no default value exists for `{}::{}` with type `{:?}`",
295 import.module(),
296 import.name(),
297 import_err.ty(),
298 )
299 })?;
300 self.define(
301 store.as_context(),
302 import.module(),
303 import.name(),
304 default_extern,
305 )?;
306 }
307 }
308 Ok(())
309 }
310
311 /// Defines a new item in this [`Linker`].
312 ///
313 /// This method will add a new definition, by name, to this instance of
314 /// [`Linker`]. The `module` and `name` provided are what to name the
315 /// `item`.
316 ///
317 /// # Errors
318 ///
319 /// Returns an error if the `module` and `name` already identify an item
320 /// of the same type as the `item` provided and if shadowing is disallowed.
321 /// For more information see the documentation on [`Linker`].
322 ///
323 /// # Examples
324 ///
325 /// ```
326 /// # use wasmtime::*;
327 /// # fn main() -> Result<()> {
328 /// # let engine = Engine::default();
329 /// # let mut store = Store::new(&engine, ());
330 /// let mut linker = Linker::new(&engine);
331 /// let ty = GlobalType::new(ValType::I32, Mutability::Const);
332 /// let global = Global::new(&mut store, ty, Val::I32(0x1234))?;
333 /// linker.define(&store, "host", "offset", global)?;
334 ///
335 /// let wat = r#"
336 /// (module
337 /// (import "host" "offset" (global i32))
338 /// (memory 1)
339 /// (data (global.get 0) "foo")
340 /// )
341 /// "#;
342 /// let module = Module::new(&engine, wat)?;
343 /// linker.instantiate(&mut store, &module)?;
344 /// # Ok(())
345 /// # }
346 /// ```
347 pub fn define(
348 &mut self,
349 store: impl AsContext<Data = T>,
350 module: &str,
351 name: &str,
352 item: impl Into<Extern>,
353 ) -> Result<&mut Self>
354 where
355 T: 'static,
356 {
357 let store = store.as_context();
358 let key = self.import_key(module, Some(name));
359 self.insert(key, Definition::new(store.0, item.into()))?;
360 Ok(self)
361 }
362
363 /// Same as [`Linker::define`], except only the name of the import is
364 /// provided, not a module name as well.
365 ///
366 /// This is only relevant when working with the module linking proposal
367 /// where one-level names are allowed (in addition to two-level names).
368 /// Otherwise this method need not be used.
369 pub fn define_name(
370 &mut self,
371 store: impl AsContext<Data = T>,
372 name: &str,
373 item: impl Into<Extern>,
374 ) -> Result<&mut Self>
375 where
376 T: 'static,
377 {
378 let store = store.as_context();
379 let key = self.import_key(name, None);
380 self.insert(key, Definition::new(store.0, item.into()))?;
381 Ok(self)
382 }
383
384 fn func_insert(&mut self, module: &str, name: &str, func: HostFunc) -> Result<&mut Self>
385 where
386 T: 'static,
387 {
388 let key = self.import_key(module, Some(name));
389 self.insert(key, Definition::HostFunc(Arc::new(func)))?;
390 Ok(self)
391 }
392
393 /// Creates a [`Func::new`]-style function named in this linker.
394 ///
395 /// For more information see [`Linker::func_wrap`].
396 ///
397 /// # Panics
398 ///
399 /// Panics if the given function type is not associated with the same engine
400 /// as this linker.
401 pub fn func_new(
402 &mut self,
403 module: &str,
404 name: &str,
405 ty: FuncType,
406 func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<()> + Send + Sync + 'static,
407 ) -> Result<&mut Self>
408 where
409 T: 'static,
410 {
411 self.func_insert(module, name, HostFunc::new(&self.engine, ty, func))
412 }
413
414 /// Creates a [`Func::new_unchecked`]-style function named in this linker.
415 ///
416 /// For more information see [`Linker::func_wrap`].
417 ///
418 /// # Panics
419 ///
420 /// Panics if the given function type is not associated with the same engine
421 /// as this linker.
422 ///
423 /// # Safety
424 ///
425 /// See [`Func::new_unchecked`] for more safety information.
426 pub unsafe fn func_new_unchecked(
427 &mut self,
428 module: &str,
429 name: &str,
430 ty: FuncType,
431 func: impl Fn(Caller<'_, T>, &mut [ValRaw]) -> Result<()> + Send + Sync + 'static,
432 ) -> Result<&mut Self>
433 where
434 T: 'static,
435 {
436 // SAFETY: the contract of this function is the same as `new_unchecked`.
437 let func = unsafe { HostFunc::new_unchecked(&self.engine, ty, func) };
438 self.func_insert(module, name, func)
439 }
440
441 /// Creates a [`Func::new_async`]-style function named in this linker.
442 ///
443 /// For more information see [`Linker::func_wrap`].
444 ///
445 /// # Panics
446 ///
447 /// This method panics in the following situations:
448 ///
449 /// * This linker is not associated with an [async
450 /// config](crate::Config::async_support).
451 ///
452 /// * If the given function type is not associated with the same engine as
453 /// this linker.
454 #[cfg(feature = "async")]
455 pub fn func_new_async<F>(
456 &mut self,
457 module: &str,
458 name: &str,
459 ty: FuncType,
460 func: F,
461 ) -> Result<&mut Self>
462 where
463 F: for<'a> Fn(
464 Caller<'a, T>,
465 &'a [Val],
466 &'a mut [Val],
467 ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
468 + Send
469 + Sync
470 + 'static,
471 T: 'static,
472 {
473 assert!(
474 self.engine.config().async_support,
475 "cannot use `func_new_async` without enabling async support in the config"
476 );
477 self.func_insert(module, name, HostFunc::new_async(&self.engine, ty, func))
478 }
479
480 /// Define a host function within this linker.
481 ///
482 /// For information about how the host function operates, see
483 /// [`Func::wrap`]. That includes information about translating Rust types
484 /// to WebAssembly native types.
485 ///
486 /// This method creates a host-provided function in this linker under the
487 /// provided name. This method is distinct in its capability to create a
488 /// [`Store`](crate::Store)-independent function. This means that the
489 /// function defined here can be used to instantiate instances in multiple
490 /// different stores, or in other words the function can be loaded into
491 /// different stores.
492 ///
493 /// Note that the capability mentioned here applies to all other
494 /// host-function-defining-methods on [`Linker`] as well. All of them can be
495 /// used to create instances of [`Func`] within multiple stores. In a
496 /// multithreaded program, for example, this means that the host functions
497 /// could be called concurrently if different stores are executing on
498 /// different threads.
499 ///
500 /// # Errors
501 ///
502 /// Returns an error if the `module` and `name` already identify an item
503 /// of the same type as the `item` provided and if shadowing is disallowed.
504 /// For more information see the documentation on [`Linker`].
505 ///
506 /// # Examples
507 ///
508 /// ```
509 /// # use wasmtime::*;
510 /// # fn main() -> Result<()> {
511 /// # let engine = Engine::default();
512 /// let mut linker = Linker::new(&engine);
513 /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
514 /// linker.func_wrap("host", "log_i32", |x: i32| println!("{}", x))?;
515 /// linker.func_wrap("host", "log_str", |caller: Caller<'_, ()>, ptr: i32, len: i32| {
516 /// // ...
517 /// })?;
518 ///
519 /// let wat = r#"
520 /// (module
521 /// (import "host" "double" (func (param i32) (result i32)))
522 /// (import "host" "log_i32" (func (param i32)))
523 /// (import "host" "log_str" (func (param i32 i32)))
524 /// )
525 /// "#;
526 /// let module = Module::new(&engine, wat)?;
527 ///
528 /// // instantiate in multiple different stores
529 /// for _ in 0..10 {
530 /// let mut store = Store::new(&engine, ());
531 /// linker.instantiate(&mut store, &module)?;
532 /// }
533 /// # Ok(())
534 /// # }
535 /// ```
536 pub fn func_wrap<Params, Args>(
537 &mut self,
538 module: &str,
539 name: &str,
540 func: impl IntoFunc<T, Params, Args>,
541 ) -> Result<&mut Self>
542 where
543 T: 'static,
544 {
545 self.func_insert(module, name, HostFunc::wrap(&self.engine, func))
546 }
547
548 /// Asynchronous analog of [`Linker::func_wrap`].
549 #[cfg(feature = "async")]
550 pub fn func_wrap_async<F, Params: crate::WasmTyList, Args: crate::WasmRet>(
551 &mut self,
552 module: &str,
553 name: &str,
554 func: F,
555 ) -> Result<&mut Self>
556 where
557 F: for<'a> Fn(Caller<'a, T>, Params) -> Box<dyn Future<Output = Args> + Send + 'a>
558 + Send
559 + Sync
560 + 'static,
561 T: 'static,
562 {
563 assert!(
564 self.engine.config().async_support,
565 "cannot use `func_wrap_async` without enabling async support on the config",
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 = instance
637 .exports(&mut store)
638 .map(|e| {
639 (
640 self.import_key(module_name, Some(e.name())),
641 e.into_extern(),
642 )
643 })
644 .collect::<Vec<_>>();
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.intern_str(module);
990 let as_module = self.intern_str(as_module);
991 let items = self
992 .map
993 .iter()
994 .filter(|(key, _def)| key.module == module)
995 .map(|(key, def)| (key.name, def.clone()))
996 .collect::<Vec<_>>();
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 match self.map.entry(key) {
1011 Entry::Occupied(_) if !self.allow_shadowing => {
1012 let module = &self.strings[key.module];
1013 let desc = match self.strings.get(key.name) {
1014 Some(name) => format!("{module}::{name}"),
1015 None => module.to_string(),
1016 };
1017 bail!("import of `{desc}` defined twice")
1018 }
1019 Entry::Occupied(mut o) => {
1020 o.insert(item);
1021 }
1022 Entry::Vacant(v) => {
1023 v.insert(item);
1024 }
1025 }
1026 Ok(())
1027 }
1028
1029 fn import_key(&mut self, module: &str, name: Option<&str>) -> ImportKey {
1030 ImportKey {
1031 module: self.intern_str(module),
1032 name: name
1033 .map(|name| self.intern_str(name))
1034 .unwrap_or(usize::max_value()),
1035 }
1036 }
1037
1038 fn intern_str(&mut self, string: &str) -> usize {
1039 if let Some(idx) = self.string2idx.get(string) {
1040 return *idx;
1041 }
1042 let string: Arc<str> = string.into();
1043 let idx = self.strings.len();
1044 self.strings.push(string.clone());
1045 self.string2idx.insert(string, idx);
1046 idx
1047 }
1048
1049 /// Attempts to instantiate the `module` provided.
1050 ///
1051 /// This method will attempt to assemble a list of imports that correspond
1052 /// to the imports required by the [`Module`] provided. This list
1053 /// of imports is then passed to [`Instance::new`] to continue the
1054 /// instantiation process.
1055 ///
1056 /// Each import of `module` will be looked up in this [`Linker`] and must
1057 /// have previously been defined. If it was previously defined with an
1058 /// incorrect signature or if it was not previously defined then an error
1059 /// will be returned because the import can not be satisfied.
1060 ///
1061 /// Per the WebAssembly spec, instantiation includes running the module's
1062 /// start function, if it has one (not to be confused with the `_start`
1063 /// function, which is not run).
1064 ///
1065 /// # Errors
1066 ///
1067 /// This method can fail because an import may not be found, or because
1068 /// instantiation itself may fail. For information on instantiation
1069 /// failures see [`Instance::new`]. If an import is not found, the error
1070 /// may be downcast to an [`UnknownImportError`].
1071 ///
1072 ///
1073 /// # Panics
1074 ///
1075 /// Panics if any item used to instantiate `module` is not owned by
1076 /// `store`. Additionally this will panic if the [`Engine`] that the `store`
1077 /// belongs to is different than this [`Linker`].
1078 ///
1079 /// # Examples
1080 ///
1081 /// ```
1082 /// # use wasmtime::*;
1083 /// # fn main() -> Result<()> {
1084 /// # let engine = Engine::default();
1085 /// # let mut store = Store::new(&engine, ());
1086 /// let mut linker = Linker::new(&engine);
1087 /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
1088 ///
1089 /// let wat = r#"
1090 /// (module
1091 /// (import "host" "double" (func (param i32) (result i32)))
1092 /// )
1093 /// "#;
1094 /// let module = Module::new(&engine, wat)?;
1095 /// linker.instantiate(&mut store, &module)?;
1096 /// # Ok(())
1097 /// # }
1098 /// ```
1099 pub fn instantiate(
1100 &self,
1101 mut store: impl AsContextMut<Data = T>,
1102 module: &Module,
1103 ) -> Result<Instance>
1104 where
1105 T: 'static,
1106 {
1107 self._instantiate_pre(module, Some(store.as_context_mut().0))?
1108 .instantiate(store)
1109 }
1110
1111 /// Attempts to instantiate the `module` provided. This is the same as
1112 /// [`Linker::instantiate`], except for async `Store`s.
1113 #[cfg(feature = "async")]
1114 pub async fn instantiate_async(
1115 &self,
1116 mut store: impl AsContextMut<Data = T>,
1117 module: &Module,
1118 ) -> Result<Instance>
1119 where
1120 T: Send + 'static,
1121 {
1122 self._instantiate_pre(module, Some(store.as_context_mut().0))?
1123 .instantiate_async(store)
1124 .await
1125 }
1126
1127 /// Performs all checks necessary for instantiating `module` with this
1128 /// linker, except that instantiation doesn't actually finish.
1129 ///
1130 /// This method is used for front-loading type-checking information as well
1131 /// as collecting the imports to use to instantiate a module with. The
1132 /// returned [`InstancePre`] represents a ready-to-be-instantiated module,
1133 /// which can also be instantiated multiple times if desired.
1134 ///
1135 /// # Errors
1136 ///
1137 /// Returns an error which may be downcast to an [`UnknownImportError`] if
1138 /// the module has any unresolvable imports.
1139 ///
1140 /// # Examples
1141 ///
1142 /// ```
1143 /// # use wasmtime::*;
1144 /// # fn main() -> Result<()> {
1145 /// # let engine = Engine::default();
1146 /// # let mut store = Store::new(&engine, ());
1147 /// let mut linker = Linker::new(&engine);
1148 /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
1149 ///
1150 /// let wat = r#"
1151 /// (module
1152 /// (import "host" "double" (func (param i32) (result i32)))
1153 /// )
1154 /// "#;
1155 /// let module = Module::new(&engine, wat)?;
1156 /// let instance_pre = linker.instantiate_pre(&module)?;
1157 ///
1158 /// // Finish instantiation after the type-checking has all completed...
1159 /// let instance = instance_pre.instantiate(&mut store)?;
1160 ///
1161 /// // ... and we can even continue to keep instantiating if desired!
1162 /// instance_pre.instantiate(&mut store)?;
1163 /// instance_pre.instantiate(&mut store)?;
1164 ///
1165 /// // Note that functions defined in a linker with `func_wrap` and similar
1166 /// // constructors are not owned by any particular `Store`, so we can also
1167 /// // instantiate our `instance_pre` in other stores because no imports
1168 /// // belong to the original store.
1169 /// let mut new_store = Store::new(&engine, ());
1170 /// instance_pre.instantiate(&mut new_store)?;
1171 /// # Ok(())
1172 /// # }
1173 /// ```
1174 pub fn instantiate_pre(&self, module: &Module) -> Result<InstancePre<T>>
1175 where
1176 T: 'static,
1177 {
1178 self._instantiate_pre(module, None)
1179 }
1180
1181 /// This is split out to optionally take a `store` so that when the
1182 /// `.instantiate` API is used we can get fresh up-to-date type information
1183 /// for memories and their current size, if necessary.
1184 ///
1185 /// Note that providing a `store` here is not required for correctness
1186 /// per-se. If one is not provided, such as the with the `instantiate_pre`
1187 /// API, then the type information used for memories and tables will reflect
1188 /// their size when inserted into the linker rather than their current size.
1189 /// This isn't expected to be much of a problem though since
1190 /// per-store-`Linker` types are likely using `.instantiate(..)` and
1191 /// per-`Engine` linkers don't have memories/tables in them.
1192 fn _instantiate_pre(
1193 &self,
1194 module: &Module,
1195 store: Option<&StoreOpaque>,
1196 ) -> Result<InstancePre<T>>
1197 where
1198 T: 'static,
1199 {
1200 let mut imports = module
1201 .imports()
1202 .map(|import| self._get_by_import(&import))
1203 .collect::<Result<Vec<_>, _>>()?;
1204 if let Some(store) = store {
1205 for import in imports.iter_mut() {
1206 import.update_size(store);
1207 }
1208 }
1209 unsafe { InstancePre::new(module, imports) }
1210 }
1211
1212 /// Returns an iterator over all items defined in this `Linker`, in
1213 /// arbitrary order.
1214 ///
1215 /// The iterator returned will yield 3-tuples where the first two elements
1216 /// are the module name and item name for the external item, and the third
1217 /// item is the item itself that is defined.
1218 ///
1219 /// Note that multiple `Extern` items may be defined for the same
1220 /// module/name pair.
1221 ///
1222 /// # Panics
1223 ///
1224 /// This function will panic if the `store` provided does not come from the
1225 /// same [`Engine`] that this linker was created with.
1226 pub fn iter<'a: 'p, 'p>(
1227 &'a self,
1228 mut store: impl AsContextMut<Data = T> + 'p,
1229 ) -> impl Iterator<Item = (&'a str, &'a str, Extern)> + 'p
1230 where
1231 T: 'static,
1232 {
1233 self.map.iter().map(move |(key, item)| {
1234 let store = store.as_context_mut();
1235 (
1236 &*self.strings[key.module],
1237 &*self.strings[key.name],
1238 // Should be safe since `T` is connecting the linker and store
1239 unsafe { item.to_extern(store.0) },
1240 )
1241 })
1242 }
1243
1244 /// Looks up a previously defined value in this [`Linker`], identified by
1245 /// the names provided.
1246 ///
1247 /// Returns `None` if this name was not previously defined in this
1248 /// [`Linker`].
1249 ///
1250 /// # Panics
1251 ///
1252 /// This function will panic if the `store` provided does not come from the
1253 /// same [`Engine`] that this linker was created with.
1254 pub fn get(
1255 &self,
1256 mut store: impl AsContextMut<Data = T>,
1257 module: &str,
1258 name: &str,
1259 ) -> Option<Extern>
1260 where
1261 T: 'static,
1262 {
1263 let store = store.as_context_mut().0;
1264 // Should be safe since `T` is connecting the linker and store
1265 Some(unsafe { self._get(module, name)?.to_extern(store) })
1266 }
1267
1268 fn _get(&self, module: &str, name: &str) -> Option<&Definition> {
1269 let key = ImportKey {
1270 module: *self.string2idx.get(module)?,
1271 name: *self.string2idx.get(name)?,
1272 };
1273 self.map.get(&key)
1274 }
1275
1276 /// Looks up a value in this `Linker` which matches the `import` type
1277 /// provided.
1278 ///
1279 /// Returns `None` if no match was found.
1280 ///
1281 /// # Panics
1282 ///
1283 /// This function will panic if the `store` provided does not come from the
1284 /// same [`Engine`] that this linker was created with.
1285 pub fn get_by_import(
1286 &self,
1287 mut store: impl AsContextMut<Data = T>,
1288 import: &ImportType,
1289 ) -> Option<Extern>
1290 where
1291 T: 'static,
1292 {
1293 let store = store.as_context_mut().0;
1294 // Should be safe since `T` is connecting the linker and store
1295 Some(unsafe { self._get_by_import(import).ok()?.to_extern(store) })
1296 }
1297
1298 fn _get_by_import(&self, import: &ImportType) -> Result<Definition, UnknownImportError> {
1299 match self._get(import.module(), import.name()) {
1300 Some(item) => Ok(item.clone()),
1301 None => Err(UnknownImportError::new(import)),
1302 }
1303 }
1304
1305 /// Returns the "default export" of a module.
1306 ///
1307 /// An export with an empty string is considered to be a "default export".
1308 /// "_start" is also recognized for compatibility.
1309 ///
1310 /// # Panics
1311 ///
1312 /// Panics if the default function found is not owned by `store`. This
1313 /// function will also panic if the `store` provided does not come from the
1314 /// same [`Engine`] that this linker was created with.
1315 pub fn get_default(&self, mut store: impl AsContextMut<Data = T>, module: &str) -> Result<Func>
1316 where
1317 T: 'static,
1318 {
1319 if let Some(external) = self.get(&mut store, module, "") {
1320 if let Extern::Func(func) = external {
1321 return Ok(func);
1322 }
1323 bail!("default export in '{module}' is not a function");
1324 }
1325
1326 // For compatibility, also recognize "_start".
1327 if let Some(external) = self.get(&mut store, module, "_start") {
1328 if let Extern::Func(func) = external {
1329 return Ok(func);
1330 }
1331 bail!("`_start` in '{module}' is not a function");
1332 }
1333
1334 // Otherwise return a no-op function.
1335 Ok(Func::wrap(store, || {}))
1336 }
1337}
1338
1339impl<T: 'static> Default for Linker<T> {
1340 fn default() -> Linker<T> {
1341 Linker::new(&Engine::default())
1342 }
1343}
1344
1345impl Definition {
1346 fn new(store: &StoreOpaque, item: Extern) -> Definition {
1347 let ty = DefinitionType::from(store, &item);
1348 Definition::Extern(item, ty)
1349 }
1350
1351 pub(crate) fn ty(&self) -> DefinitionType {
1352 match self {
1353 Definition::Extern(_, ty) => ty.clone(),
1354 Definition::HostFunc(func) => DefinitionType::Func(func.sig_index()),
1355 }
1356 }
1357
1358 /// Inserts this definition into the `store` provided.
1359 ///
1360 /// # Safety
1361 ///
1362 /// Note the unsafety here is due to calling `HostFunc::to_func`. The
1363 /// requirement here is that the `T` that was originally used to create the
1364 /// `HostFunc` matches the `T` on the store.
1365 pub(crate) unsafe fn to_extern(&self, store: &mut StoreOpaque) -> Extern {
1366 match self {
1367 Definition::Extern(e, _) => e.clone(),
1368 // SAFETY: the contract of this function is the same as what's
1369 // required of `to_func`, that `T` of the store matches the `T` of
1370 // this original definition.
1371 Definition::HostFunc(func) => unsafe { func.to_func(store).into() },
1372 }
1373 }
1374
1375 pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
1376 match self {
1377 Definition::Extern(e, _) => e.comes_from_same_store(store),
1378 Definition::HostFunc(_func) => true,
1379 }
1380 }
1381
1382 fn update_size(&mut self, store: &StoreOpaque) {
1383 match self {
1384 Definition::Extern(Extern::Memory(m), DefinitionType::Memory(_, size)) => {
1385 *size = m.internal_size(store);
1386 }
1387 Definition::Extern(Extern::SharedMemory(m), DefinitionType::Memory(_, size)) => {
1388 *size = m.size();
1389 }
1390 Definition::Extern(Extern::Table(m), DefinitionType::Table(_, size)) => {
1391 *size = m._size(store);
1392 }
1393 _ => {}
1394 }
1395 }
1396}
1397
1398impl DefinitionType {
1399 pub(crate) fn from(store: &StoreOpaque, item: &Extern) -> DefinitionType {
1400 match item {
1401 Extern::Func(f) => DefinitionType::Func(f.type_index(store)),
1402 Extern::Table(t) => DefinitionType::Table(*t.wasmtime_ty(store), t._size(store)),
1403 Extern::Global(t) => DefinitionType::Global(*t.wasmtime_ty(store)),
1404 Extern::Memory(t) => {
1405 DefinitionType::Memory(*t.wasmtime_ty(store), t.internal_size(store))
1406 }
1407 Extern::SharedMemory(t) => DefinitionType::Memory(*t.ty().wasmtime_memory(), t.size()),
1408 Extern::Tag(t) => DefinitionType::Tag(*t.wasmtime_ty(store)),
1409 }
1410 }
1411
1412 pub(crate) fn desc(&self) -> &'static str {
1413 match self {
1414 DefinitionType::Func(_) => "function",
1415 DefinitionType::Table(..) => "table",
1416 DefinitionType::Memory(..) => "memory",
1417 DefinitionType::Global(_) => "global",
1418 DefinitionType::Tag(_) => "tag",
1419 }
1420 }
1421}
1422
1423/// Modules can be interpreted either as Commands or Reactors.
1424enum ModuleKind {
1425 /// The instance is a Command, meaning an instance is created for each
1426 /// exported function and lives for the duration of the function call.
1427 Command,
1428
1429 /// The instance is a Reactor, meaning one instance is created which
1430 /// may live across multiple calls.
1431 Reactor,
1432}
1433
1434impl ModuleKind {
1435 /// Determine whether the given module is a Command or a Reactor.
1436 fn categorize(module: &Module) -> Result<ModuleKind> {
1437 let command_start = module.get_export("_start");
1438 let reactor_start = module.get_export("_initialize");
1439 match (command_start, reactor_start) {
1440 (Some(command_start), None) => {
1441 if let Some(_) = command_start.func() {
1442 Ok(ModuleKind::Command)
1443 } else {
1444 bail!("`_start` must be a function")
1445 }
1446 }
1447 (None, Some(reactor_start)) => {
1448 if let Some(_) = reactor_start.func() {
1449 Ok(ModuleKind::Reactor)
1450 } else {
1451 bail!("`_initialize` must be a function")
1452 }
1453 }
1454 (None, None) => {
1455 // Module declares neither of the recognized functions, so treat
1456 // it as a reactor with no initialization function.
1457 Ok(ModuleKind::Reactor)
1458 }
1459 (Some(_), Some(_)) => {
1460 // Module declares itself to be both a Command and a Reactor.
1461 bail!("Program cannot be both a Command and a Reactor")
1462 }
1463 }
1464 }
1465}
1466
1467/// Error for an unresolvable import.
1468///
1469/// Returned - wrapped in an [`Error`][crate::Error] - by
1470/// [`Linker::instantiate`] and related methods for modules with unresolvable
1471/// imports.
1472#[derive(Clone, Debug)]
1473pub struct UnknownImportError {
1474 module: String,
1475 name: String,
1476 ty: ExternType,
1477}
1478
1479impl UnknownImportError {
1480 fn new(import: &ImportType) -> Self {
1481 Self {
1482 module: import.module().to_string(),
1483 name: import.name().to_string(),
1484 ty: import.ty(),
1485 }
1486 }
1487
1488 /// Returns the module name that the unknown import was expected to come from.
1489 pub fn module(&self) -> &str {
1490 &self.module
1491 }
1492
1493 /// Returns the field name of the module that the unknown import was expected to come from.
1494 pub fn name(&self) -> &str {
1495 &self.name
1496 }
1497
1498 /// Returns the type of the unknown import.
1499 pub fn ty(&self) -> ExternType {
1500 self.ty.clone()
1501 }
1502}
1503
1504impl fmt::Display for UnknownImportError {
1505 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1506 write!(
1507 f,
1508 "unknown import: `{}::{}` has not been defined",
1509 self.module, self.name,
1510 )
1511 }
1512}
1513
1514impl core::error::Error for UnknownImportError {}