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