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