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