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