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