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