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