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