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