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