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