1 use crate::Abi; 2 use crate::component::dfg::AbstractInstantiations; 3 use crate::component::*; 4 use crate::prelude::*; 5 use crate::{ 6 EngineOrModuleTypeIndex, EntityIndex, FuncKey, ModuleEnvironment, ModuleInternedTypeIndex, 7 ModuleTranslation, ModuleTypesBuilder, PrimaryMap, ScopeVec, TagIndex, Tunables, TypeConvert, 8 WasmHeapType, WasmResult, WasmValType, 9 }; 10 use core::str::FromStr; 11 use cranelift_entity::SecondaryMap; 12 use cranelift_entity::packed_option::PackedOption; 13 use indexmap::IndexMap; 14 use std::collections::HashMap; 15 use std::mem; 16 use wasmparser::component_types::{ 17 AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType, 18 ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType, 19 }; 20 use wasmparser::types::Types; 21 use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator}; 22 23 mod adapt; 24 pub use self::adapt::*; 25 mod inline; 26 27 /// Structure used to translate a component and parse it. 28 pub struct Translator<'a, 'data> { 29 /// The current component being translated. 30 /// 31 /// This will get swapped out as translation traverses the body of a 32 /// component and a sub-component is entered or left. 33 result: Translation<'data>, 34 35 /// Current state of parsing a binary component. Note that like `result` 36 /// this will change as the component is traversed. 37 parser: Parser, 38 39 /// Stack of lexical scopes that are in-progress but not finished yet. 40 /// 41 /// This is pushed to whenever a component is entered and popped from 42 /// whenever a component is left. Each lexical scope also contains 43 /// information about the variables that it is currently required to close 44 /// over which is threaded into the current in-progress translation of 45 /// the sub-component which pushed a scope here. 46 lexical_scopes: Vec<LexicalScope<'data>>, 47 48 /// The validator in use to verify that the raw input binary is a valid 49 /// component. 50 validator: &'a mut Validator, 51 52 /// Type information shared for the entire component. 53 /// 54 /// This builder is also used for all core wasm modules found to intern 55 /// signatures across all modules. 56 types: PreInliningComponentTypes<'a>, 57 58 /// The compiler configuration provided by the embedder. 59 tunables: &'a Tunables, 60 61 /// Auxiliary location to push generated adapter modules onto. 62 scope_vec: &'data ScopeVec<u8>, 63 64 /// Completely translated core wasm modules that have been found so far. 65 /// 66 /// Note that this translation only involves learning about type 67 /// information and functions are not actually compiled here. 68 static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>, 69 70 /// Completely translated components that have been found so far. 71 /// 72 /// As frames are popped from `lexical_scopes` their completed component 73 /// will be pushed onto this list. 74 static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>, 75 76 /// The top-level import name for Wasmtime's unsafe intrinsics, if any. 77 unsafe_intrinsics_import: Option<&'a str>, 78 } 79 80 /// Representation of the syntactic scope of a component meaning where it is 81 /// and what its state is at in the binary format. 82 /// 83 /// These scopes are pushed and popped when a sub-component starts being 84 /// parsed and finishes being parsed. The main purpose of this frame is to 85 /// have a `ClosedOverVars` field which encapsulates data that is inherited 86 /// from the scope specified into the component being translated just beneath 87 /// it. 88 /// 89 /// This structure exists to implement outer aliases to components and modules. 90 /// When a component or module is closed over then that means it needs to be 91 /// inherited in a sense to the component which actually had the alias. This is 92 /// achieved with a deceptively simple scheme where each parent of the 93 /// component with the alias will inherit the component from the desired 94 /// location. 95 /// 96 /// For example with a component structure that looks like: 97 /// 98 /// ```wasm 99 /// (component $A 100 /// (core module $M) 101 /// (component $B 102 /// (component $C 103 /// (alias outer $A $M (core module)) 104 /// ) 105 /// ) 106 /// ) 107 /// ``` 108 /// 109 /// here the `C` component is closing over `M` located in the root component 110 /// `A`. When `C` is being translated the `lexical_scopes` field will look like 111 /// `[A, B]`. When the alias is encountered (for module index 0) this will 112 /// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of 113 /// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then 114 /// inserted into `closure_args` in `B`'s frame. This produces yet another 115 /// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space 116 /// via `LocalInitializer::AliasModuleUpvar` with the last index. 117 /// 118 /// All of these upvar indices and such are interpreted in the "inline" phase 119 /// of compilation and not at runtime. This means that when `A` is being 120 /// instantiated one of its initializers will be 121 /// `LocalInitializer::ComponentStatic`. This starts to create `B` and the 122 /// variables captured for `B` are listed as local module 0, or `M`. This list 123 /// is then preserved in the definition of the component `B` and later reused 124 /// by `C` again to finally get access to the closed over component. 125 /// 126 /// Effectively the scopes are managed hierarchically where a reference to an 127 /// outer variable automatically injects references into all parents up to 128 /// where the reference is. This variable scopes are the processed during 129 /// inlining where a component definition is a reference to the static 130 /// component information (`Translation`) plus closed over variables 131 /// (`ComponentClosure` during inlining). 132 struct LexicalScope<'data> { 133 /// Current state of translating the `translation` below. 134 parser: Parser, 135 /// Current state of the component's translation as found so far. 136 translation: Translation<'data>, 137 /// List of captures that `translation` will need to process to create the 138 /// sub-component which is directly beneath this lexical scope. 139 closure_args: ClosedOverVars, 140 } 141 142 /// A "local" translation of a component. 143 /// 144 /// This structure is used as a sort of in-progress translation of a component. 145 /// This is not `Component` which is the final form as consumed by Wasmtime 146 /// at runtime. Instead this is a fairly simple representation of a component 147 /// where almost everything is ordered as a list of initializers. The binary 148 /// format is translated to a list of initializers here which is later processed 149 /// during "inlining" to produce a final component with the final set of 150 /// initializers. 151 #[derive(Default)] 152 struct Translation<'data> { 153 /// Instructions which form this component. 154 /// 155 /// There is one initializer for all members of each index space, and all 156 /// index spaces are incrementally built here as the initializer list is 157 /// processed. 158 initializers: Vec<LocalInitializer<'data>>, 159 160 /// The list of exports from this component, as pairs of names and an 161 /// index into an index space of what's being exported. 162 exports: IndexMap<&'data str, ComponentItem>, 163 164 /// Type information produced by `wasmparser` for this component. 165 /// 166 /// This type information is available after the translation of the entire 167 /// component has finished, e.g. for the `inline` pass, but beforehand this 168 /// is set to `None`. 169 types: Option<Types>, 170 } 171 172 // NB: the type information contained in `LocalInitializer` should always point 173 // to `wasmparser`'s type information, not Wasmtime's. Component types cannot be 174 // fully determined due to resources until instantiations are known which is 175 // tracked during the inlining phase. This means that all type information below 176 // is straight from `wasmparser`'s passes. 177 enum LocalInitializer<'data> { 178 // imports 179 Import(ComponentImportName<'data>, ComponentEntityType), 180 181 // An import of an intrinsic for compile-time builtins. 182 IntrinsicsImport, 183 184 // canonical function sections 185 Lower { 186 func: ComponentFuncIndex, 187 lower_ty: ComponentFuncTypeId, 188 options: LocalCanonicalOptions, 189 }, 190 Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions), 191 192 // resources 193 Resource(AliasableResourceId, WasmValType, Option<FuncIndex>), 194 ResourceNew(AliasableResourceId, ModuleInternedTypeIndex), 195 ResourceRep(AliasableResourceId, ModuleInternedTypeIndex), 196 ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex), 197 198 BackpressureInc { 199 func: ModuleInternedTypeIndex, 200 }, 201 BackpressureDec { 202 func: ModuleInternedTypeIndex, 203 }, 204 TaskReturn { 205 result: Option<ComponentValType>, 206 options: LocalCanonicalOptions, 207 }, 208 TaskCancel { 209 func: ModuleInternedTypeIndex, 210 }, 211 WaitableSetNew { 212 func: ModuleInternedTypeIndex, 213 }, 214 WaitableSetWait { 215 options: LocalCanonicalOptions, 216 }, 217 WaitableSetPoll { 218 options: LocalCanonicalOptions, 219 }, 220 WaitableSetDrop { 221 func: ModuleInternedTypeIndex, 222 }, 223 WaitableJoin { 224 func: ModuleInternedTypeIndex, 225 }, 226 ThreadYield { 227 func: ModuleInternedTypeIndex, 228 cancellable: bool, 229 }, 230 SubtaskDrop { 231 func: ModuleInternedTypeIndex, 232 }, 233 SubtaskCancel { 234 func: ModuleInternedTypeIndex, 235 async_: bool, 236 }, 237 StreamNew { 238 ty: ComponentDefinedTypeId, 239 func: ModuleInternedTypeIndex, 240 }, 241 StreamRead { 242 ty: ComponentDefinedTypeId, 243 options: LocalCanonicalOptions, 244 }, 245 StreamWrite { 246 ty: ComponentDefinedTypeId, 247 options: LocalCanonicalOptions, 248 }, 249 StreamCancelRead { 250 ty: ComponentDefinedTypeId, 251 func: ModuleInternedTypeIndex, 252 async_: bool, 253 }, 254 StreamCancelWrite { 255 ty: ComponentDefinedTypeId, 256 func: ModuleInternedTypeIndex, 257 async_: bool, 258 }, 259 StreamDropReadable { 260 ty: ComponentDefinedTypeId, 261 func: ModuleInternedTypeIndex, 262 }, 263 StreamDropWritable { 264 ty: ComponentDefinedTypeId, 265 func: ModuleInternedTypeIndex, 266 }, 267 FutureNew { 268 ty: ComponentDefinedTypeId, 269 func: ModuleInternedTypeIndex, 270 }, 271 FutureRead { 272 ty: ComponentDefinedTypeId, 273 options: LocalCanonicalOptions, 274 }, 275 FutureWrite { 276 ty: ComponentDefinedTypeId, 277 options: LocalCanonicalOptions, 278 }, 279 FutureCancelRead { 280 ty: ComponentDefinedTypeId, 281 func: ModuleInternedTypeIndex, 282 async_: bool, 283 }, 284 FutureCancelWrite { 285 ty: ComponentDefinedTypeId, 286 func: ModuleInternedTypeIndex, 287 async_: bool, 288 }, 289 FutureDropReadable { 290 ty: ComponentDefinedTypeId, 291 func: ModuleInternedTypeIndex, 292 }, 293 FutureDropWritable { 294 ty: ComponentDefinedTypeId, 295 func: ModuleInternedTypeIndex, 296 }, 297 ErrorContextNew { 298 options: LocalCanonicalOptions, 299 }, 300 ErrorContextDebugMessage { 301 options: LocalCanonicalOptions, 302 }, 303 ErrorContextDrop { 304 func: ModuleInternedTypeIndex, 305 }, 306 ContextGet { 307 func: ModuleInternedTypeIndex, 308 i: u32, 309 }, 310 ContextSet { 311 func: ModuleInternedTypeIndex, 312 i: u32, 313 }, 314 ThreadIndex { 315 func: ModuleInternedTypeIndex, 316 }, 317 ThreadNewIndirect { 318 func: ModuleInternedTypeIndex, 319 start_func_ty: ComponentTypeIndex, 320 start_func_table_index: TableIndex, 321 }, 322 ThreadSuspendToSuspended { 323 func: ModuleInternedTypeIndex, 324 cancellable: bool, 325 }, 326 ThreadSuspend { 327 func: ModuleInternedTypeIndex, 328 cancellable: bool, 329 }, 330 ThreadSuspendTo { 331 func: ModuleInternedTypeIndex, 332 cancellable: bool, 333 }, 334 ThreadUnsuspend { 335 func: ModuleInternedTypeIndex, 336 }, 337 ThreadYieldToSuspended { 338 func: ModuleInternedTypeIndex, 339 cancellable: bool, 340 }, 341 342 // core wasm modules 343 ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId), 344 345 // core wasm module instances 346 ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>), 347 ModuleSynthetic(HashMap<&'data str, EntityIndex>), 348 349 // components 350 ComponentStatic(StaticComponentIndex, ClosedOverVars), 351 352 // component instances 353 ComponentInstantiate( 354 ComponentIndex, 355 HashMap<&'data str, ComponentItem>, 356 ComponentInstanceTypeId, 357 ), 358 ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId), 359 360 // alias section 361 AliasExportFunc(ModuleInstanceIndex, &'data str), 362 AliasExportTable(ModuleInstanceIndex, &'data str), 363 AliasExportGlobal(ModuleInstanceIndex, &'data str), 364 AliasExportMemory(ModuleInstanceIndex, &'data str), 365 AliasExportTag(ModuleInstanceIndex, &'data str), 366 AliasComponentExport(ComponentInstanceIndex, &'data str), 367 AliasModule(ClosedOverModule), 368 AliasComponent(ClosedOverComponent), 369 370 // export section 371 Export(ComponentItem), 372 } 373 374 /// The "closure environment" of components themselves. 375 /// 376 /// For more information see `LexicalScope`. 377 #[derive(Default)] 378 struct ClosedOverVars { 379 components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>, 380 modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>, 381 } 382 383 /// Description how a component is closed over when the closure variables for 384 /// a component are being created. 385 /// 386 /// For more information see `LexicalScope`. 387 enum ClosedOverComponent { 388 /// A closed over component is coming from the local component's index 389 /// space, meaning a previously defined component is being captured. 390 Local(ComponentIndex), 391 /// A closed over component is coming from our own component's list of 392 /// upvars. This list was passed to us by our enclosing component, which 393 /// will eventually have bottomed out in closing over a `Local` component 394 /// index for some parent component. 395 Upvar(ComponentUpvarIndex), 396 } 397 398 /// Same as `ClosedOverComponent`, but for modules. 399 enum ClosedOverModule { 400 Local(ModuleIndex), 401 Upvar(ModuleUpvarIndex), 402 } 403 404 /// The data model for objects that are not unboxed in locals. 405 #[derive(Debug, Clone, Hash, Eq, PartialEq)] 406 pub enum LocalDataModel { 407 /// Data is stored in GC objects. 408 Gc {}, 409 410 /// Data is stored in a linear memory. 411 LinearMemory { 412 /// An optional memory definition supplied. 413 memory: Option<MemoryIndex>, 414 /// An optional definition of `realloc` to used. 415 realloc: Option<FuncIndex>, 416 }, 417 } 418 419 /// Representation of canonical ABI options. 420 struct LocalCanonicalOptions { 421 string_encoding: StringEncoding, 422 post_return: Option<FuncIndex>, 423 async_: bool, 424 cancellable: bool, 425 callback: Option<FuncIndex>, 426 /// The type index of the core GC types signature. 427 core_type: ModuleInternedTypeIndex, 428 data_model: LocalDataModel, 429 } 430 431 enum Action { 432 KeepGoing, 433 Skip(usize), 434 Done, 435 } 436 437 impl<'a, 'data> Translator<'a, 'data> { 438 /// Creates a new translation state ready to translate a component. new( tunables: &'a Tunables, validator: &'a mut Validator, types: &'a mut ComponentTypesBuilder, scope_vec: &'data ScopeVec<u8>, ) -> Self439 pub fn new( 440 tunables: &'a Tunables, 441 validator: &'a mut Validator, 442 types: &'a mut ComponentTypesBuilder, 443 scope_vec: &'data ScopeVec<u8>, 444 ) -> Self { 445 let mut parser = Parser::new(0); 446 parser.set_features(*validator.features()); 447 Self { 448 result: Translation::default(), 449 tunables, 450 validator, 451 types: PreInliningComponentTypes::new(types), 452 parser, 453 lexical_scopes: Vec::new(), 454 static_components: Default::default(), 455 static_modules: Default::default(), 456 scope_vec, 457 unsafe_intrinsics_import: None, 458 } 459 } 460 461 /// Expose Wasmtime's unsafe intrinsics under the given top-level import 462 /// name. expose_unsafe_intrinsics(&mut self, name: &'a str) -> &mut Self463 pub fn expose_unsafe_intrinsics(&mut self, name: &'a str) -> &mut Self { 464 assert!(self.unsafe_intrinsics_import.is_none()); 465 self.unsafe_intrinsics_import = Some(name); 466 self 467 } 468 469 /// Translates the binary `component`. 470 /// 471 /// This is the workhorse of compilation which will parse all of 472 /// `component` and create type information for Wasmtime and such. The 473 /// `component` does not have to be valid and it will be validated during 474 /// compilation. 475 /// 476 /// The result of this function is a tuple of the final component's 477 /// description plus a list of core wasm modules found within the 478 /// component. The component's description actually erases internal 479 /// components, instances, etc, as much as it can. Instead `Component` 480 /// retains a flat list of initializers (no nesting) which was created 481 /// as part of compilation from the nested structure of the original 482 /// component. 483 /// 484 /// The list of core wasm modules found is provided to allow compiling 485 /// modules externally in parallel. Additionally initializers in 486 /// `Component` may refer to the modules in the map returned by index. 487 /// 488 /// # Errors 489 /// 490 /// This function will return an error if the `component` provided is 491 /// invalid. translate( mut self, component: &'data [u8], ) -> Result<( ComponentTranslation, PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>, )>492 pub fn translate( 493 mut self, 494 component: &'data [u8], 495 ) -> Result<( 496 ComponentTranslation, 497 PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>, 498 )> { 499 // First up wasmparser is used to actually perform the translation and 500 // validation of this component. This will produce a list of core wasm 501 // modules in addition to components which are found during the 502 // translation process. When doing this only a `Translation` is created 503 // which is a simple representation of a component. 504 let mut remaining = component; 505 loop { 506 let payload = match self.parser.parse(remaining, true)? { 507 Chunk::Parsed { payload, consumed } => { 508 remaining = &remaining[consumed..]; 509 payload 510 } 511 Chunk::NeedMoreData(_) => unreachable!(), 512 }; 513 514 match self.translate_payload(payload, component)? { 515 Action::KeepGoing => {} 516 Action::Skip(n) => remaining = &remaining[n..], 517 Action::Done => break, 518 } 519 } 520 assert!(remaining.is_empty()); 521 assert!(self.lexical_scopes.is_empty()); 522 523 // ... after translation initially finishes the next pass is performed 524 // which we're calling "inlining". This will "instantiate" the root 525 // component, following nested component instantiations, creating a 526 // global list of initializers along the way. This phase uses the simple 527 // initializers in each component to track dataflow of host imports and 528 // internal references to items throughout a component at compile-time. 529 // The produce initializers in the final `Component` are intended to be 530 // much simpler than the original component and more efficient for 531 // Wasmtime to process at runtime as well (e.g. no string lookups as 532 // most everything is done through indices instead). 533 let mut component = inline::run( 534 self.types.types_mut_for_inlining(), 535 &self.result, 536 &self.static_modules, 537 &self.static_components, 538 )?; 539 540 self.partition_adapter_modules(&mut component); 541 542 let translation = 543 component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?; 544 545 self.analyze_function_imports(&translation); 546 547 Ok((translation, self.static_modules)) 548 } 549 analyze_function_imports(&mut self, translation: &ComponentTranslation)550 fn analyze_function_imports(&mut self, translation: &ComponentTranslation) { 551 // First, abstract interpret the initializers to create a map from each 552 // static module to its abstract set of instantiations. 553 let mut instantiations = SecondaryMap::<StaticModuleIndex, AbstractInstantiations>::new(); 554 let mut instance_to_module = 555 PrimaryMap::<RuntimeInstanceIndex, PackedOption<StaticModuleIndex>>::new(); 556 for init in &translation.component.initializers { 557 match init { 558 GlobalInitializer::InstantiateModule(instantiation, _) => match instantiation { 559 InstantiateModule::Static(module, args) => { 560 instantiations[*module].join(AbstractInstantiations::One(&*args)); 561 instance_to_module.push(Some(*module).into()); 562 } 563 _ => { 564 instance_to_module.push(None.into()); 565 } 566 }, 567 _ => continue, 568 } 569 } 570 571 // Second, make sure to mark exported modules as instantiated many 572 // times, since they could be linked with who-knows-what at runtime. 573 for item in translation.component.export_items.values() { 574 if let Export::ModuleStatic { index, .. } = item { 575 instantiations[*index].join(AbstractInstantiations::Many) 576 } 577 } 578 579 // Finally, iterate over our instantiations and record statically-known 580 // function imports so that they can get translated into direct calls 581 // (and eventually get inlined) rather than indirect calls through the 582 // imports table. 583 for (module, instantiations) in instantiations.iter() { 584 let args = match instantiations { 585 dfg::AbstractInstantiations::Many | dfg::AbstractInstantiations::None => continue, 586 dfg::AbstractInstantiations::One(args) => args, 587 }; 588 589 let mut imported_func_counter = 0_u32; 590 for (i, arg) in args.iter().enumerate() { 591 // Only consider function imports. 592 let (_, _, crate::types::EntityType::Function(_)) = 593 self.static_modules[module].module.import(i).unwrap() 594 else { 595 continue; 596 }; 597 598 let imported_func = FuncIndex::from_u32(imported_func_counter); 599 imported_func_counter += 1; 600 debug_assert!( 601 self.static_modules[module] 602 .module 603 .defined_func_index(imported_func) 604 .is_none() 605 ); 606 607 let known_func = match arg { 608 CoreDef::InstanceFlags(_) => unreachable!("instance flags are not a function"), 609 CoreDef::TaskMayBlock => unreachable!("task_may_block is not a function"), 610 611 // We could in theory inline these trampolines, so it could 612 // potentially make sense to record that we know this 613 // imported function is this particular trampoline. However, 614 // everything else is based around (module, 615 // defined-function) pairs and these trampolines don't fit 616 // that paradigm. Also, inlining trampolines gets really 617 // tricky when we consider the stack pointer, frame pointer, 618 // and return address note-taking that they do for the 619 // purposes of stack walking. We could, with enough effort, 620 // turn them into direct calls even though we probably 621 // wouldn't ever inline them, but it just doesn't seem worth 622 // the effort. 623 CoreDef::Trampoline(_) => continue, 624 625 // This import is a compile-time builtin intrinsic, we 626 // should inline its implementation during function 627 // translation. 628 CoreDef::UnsafeIntrinsic(i) => FuncKey::UnsafeIntrinsic(Abi::Wasm, *i), 629 630 // This imported function is an export from another 631 // instance, a perfect candidate for becoming an inlinable 632 // direct call! 633 CoreDef::Export(export) => { 634 let Some(arg_module) = &instance_to_module[export.instance].expand() else { 635 // Instance of a dynamic module that is not part of 636 // this component, not a statically-known module 637 // inside this component. We have to do an indirect 638 // call. 639 continue; 640 }; 641 642 let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item 643 else { 644 unreachable!("function imports must be functions") 645 }; 646 647 let Some(arg_module_def_func) = self.static_modules[*arg_module] 648 .module 649 .defined_func_index(*arg_func) 650 else { 651 // TODO: we should ideally follow re-export chains 652 // to bottom out the instantiation argument in 653 // either a definition or an import at the root 654 // component boundary. In practice, this pattern is 655 // rare, so following these chains is left for the 656 // Future. 657 continue; 658 }; 659 660 FuncKey::DefinedWasmFunction(*arg_module, arg_module_def_func) 661 } 662 }; 663 664 assert!( 665 self.static_modules[module].known_imported_functions[imported_func].is_none() 666 ); 667 self.static_modules[module].known_imported_functions[imported_func] = 668 Some(known_func); 669 } 670 } 671 } 672 translate_payload( &mut self, payload: Payload<'data>, component: &'data [u8], ) -> Result<Action>673 fn translate_payload( 674 &mut self, 675 payload: Payload<'data>, 676 component: &'data [u8], 677 ) -> Result<Action> { 678 match payload { 679 Payload::Version { 680 num, 681 encoding, 682 range, 683 } => { 684 self.validator.version(num, encoding, &range)?; 685 686 match encoding { 687 Encoding::Component => {} 688 Encoding::Module => { 689 bail!("attempted to parse a wasm module with a component parser"); 690 } 691 } 692 } 693 694 Payload::End(offset) => { 695 assert!(self.result.types.is_none()); 696 self.result.types = Some(self.validator.end(offset)?); 697 698 // Exit the current lexical scope. If there is no parent (no 699 // frame currently on the stack) then translation is finished. 700 // Otherwise that means that a nested component has been 701 // completed and is recorded as such. 702 let LexicalScope { 703 parser, 704 translation, 705 closure_args, 706 } = match self.lexical_scopes.pop() { 707 Some(frame) => frame, 708 None => return Ok(Action::Done), 709 }; 710 self.parser = parser; 711 let component = mem::replace(&mut self.result, translation); 712 let static_idx = self.static_components.push(component); 713 self.result 714 .initializers 715 .push(LocalInitializer::ComponentStatic(static_idx, closure_args)); 716 } 717 718 // When we see a type section the types are validated and then 719 // translated into Wasmtime's representation. Each active type 720 // definition is recorded in the `ComponentTypesBuilder` tables, or 721 // this component's active scope. 722 // 723 // Note that the push/pop of the component types scope happens above 724 // in `Version` and `End` since multiple type sections can appear 725 // within a component. 726 Payload::ComponentTypeSection(s) => { 727 let mut component_type_index = 728 self.validator.types(0).unwrap().component_type_count(); 729 self.validator.component_type_section(&s)?; 730 731 // Look for resource types and if a local resource is defined 732 // then an initializer is added to define that resource type and 733 // reference its destructor. 734 let types = self.validator.types(0).unwrap(); 735 for ty in s { 736 match ty? { 737 wasmparser::ComponentType::Resource { rep, dtor } => { 738 let rep = self.types.convert_valtype(rep)?; 739 let id = types 740 .component_any_type_at(component_type_index) 741 .unwrap_resource(); 742 let dtor = dtor.map(FuncIndex::from_u32); 743 self.result 744 .initializers 745 .push(LocalInitializer::Resource(id, rep, dtor)); 746 } 747 748 // no extra processing needed 749 wasmparser::ComponentType::Defined(_) 750 | wasmparser::ComponentType::Func(_) 751 | wasmparser::ComponentType::Instance(_) 752 | wasmparser::ComponentType::Component(_) => {} 753 } 754 755 component_type_index += 1; 756 } 757 } 758 Payload::CoreTypeSection(s) => { 759 self.validator.core_type_section(&s)?; 760 } 761 762 // Processing the import section at this point is relatively simple 763 // which is to simply record the name of the import and the type 764 // information associated with it. 765 Payload::ComponentImportSection(s) => { 766 self.validator.component_import_section(&s)?; 767 for import in s { 768 let import = import?; 769 let types = self.validator.types(0).unwrap(); 770 let ty = types 771 .component_entity_type_of_import(import.name.0) 772 .unwrap(); 773 774 if self.is_unsafe_intrinsics_import(import.name.0) { 775 self.check_unsafe_intrinsics_import(import.name.0, ty)?; 776 self.result 777 .initializers 778 .push(LocalInitializer::IntrinsicsImport); 779 } else { 780 self.result 781 .initializers 782 .push(LocalInitializer::Import(import.name, ty)); 783 } 784 } 785 } 786 787 // Entries in the canonical section will get initializers recorded 788 // with the listed options for lifting/lowering. 789 Payload::ComponentCanonicalSection(s) => { 790 let types = self.validator.types(0).unwrap(); 791 let mut core_func_index = types.function_count(); 792 self.validator.component_canonical_section(&s)?; 793 for func in s { 794 let init = match func? { 795 wasmparser::CanonicalFunction::Lift { 796 type_index, 797 core_func_index, 798 options, 799 } => { 800 let ty = self 801 .validator 802 .types(0) 803 .unwrap() 804 .component_any_type_at(type_index) 805 .unwrap_func(); 806 807 let func = FuncIndex::from_u32(core_func_index); 808 let options = self.canonical_options(&options, core_func_index)?; 809 LocalInitializer::Lift(ty, func, options) 810 } 811 wasmparser::CanonicalFunction::Lower { 812 func_index, 813 options, 814 } => { 815 let lower_ty = self 816 .validator 817 .types(0) 818 .unwrap() 819 .component_function_at(func_index); 820 let func = ComponentFuncIndex::from_u32(func_index); 821 let options = self.canonical_options(&options, core_func_index)?; 822 core_func_index += 1; 823 LocalInitializer::Lower { 824 func, 825 options, 826 lower_ty, 827 } 828 } 829 wasmparser::CanonicalFunction::ResourceNew { resource } => { 830 let resource = self 831 .validator 832 .types(0) 833 .unwrap() 834 .component_any_type_at(resource) 835 .unwrap_resource(); 836 let ty = self.core_func_signature(core_func_index)?; 837 core_func_index += 1; 838 LocalInitializer::ResourceNew(resource, ty) 839 } 840 wasmparser::CanonicalFunction::ResourceDrop { resource } => { 841 let resource = self 842 .validator 843 .types(0) 844 .unwrap() 845 .component_any_type_at(resource) 846 .unwrap_resource(); 847 let ty = self.core_func_signature(core_func_index)?; 848 core_func_index += 1; 849 LocalInitializer::ResourceDrop(resource, ty) 850 } 851 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => { 852 let _ = resource; 853 bail!("support for `resource.drop async` not implemented yet") 854 } 855 wasmparser::CanonicalFunction::ResourceRep { resource } => { 856 let resource = self 857 .validator 858 .types(0) 859 .unwrap() 860 .component_any_type_at(resource) 861 .unwrap_resource(); 862 let ty = self.core_func_signature(core_func_index)?; 863 core_func_index += 1; 864 LocalInitializer::ResourceRep(resource, ty) 865 } 866 wasmparser::CanonicalFunction::ThreadSpawnRef { .. } 867 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. } 868 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => { 869 bail!("unsupported intrinsic") 870 } 871 wasmparser::CanonicalFunction::BackpressureInc => { 872 let core_type = self.core_func_signature(core_func_index)?; 873 core_func_index += 1; 874 LocalInitializer::BackpressureInc { func: core_type } 875 } 876 wasmparser::CanonicalFunction::BackpressureDec => { 877 let core_type = self.core_func_signature(core_func_index)?; 878 core_func_index += 1; 879 LocalInitializer::BackpressureDec { func: core_type } 880 } 881 882 wasmparser::CanonicalFunction::TaskReturn { result, options } => { 883 let result = result.map(|ty| match ty { 884 wasmparser::ComponentValType::Primitive(ty) => { 885 ComponentValType::Primitive(ty) 886 } 887 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type( 888 self.validator 889 .types(0) 890 .unwrap() 891 .component_defined_type_at(ty), 892 ), 893 }); 894 let options = self.canonical_options(&options, core_func_index)?; 895 core_func_index += 1; 896 LocalInitializer::TaskReturn { result, options } 897 } 898 wasmparser::CanonicalFunction::TaskCancel => { 899 let func = self.core_func_signature(core_func_index)?; 900 core_func_index += 1; 901 LocalInitializer::TaskCancel { func } 902 } 903 wasmparser::CanonicalFunction::WaitableSetNew => { 904 let func = self.core_func_signature(core_func_index)?; 905 core_func_index += 1; 906 LocalInitializer::WaitableSetNew { func } 907 } 908 wasmparser::CanonicalFunction::WaitableSetWait { 909 cancellable, 910 memory, 911 } => { 912 let core_type = self.core_func_signature(core_func_index)?; 913 core_func_index += 1; 914 LocalInitializer::WaitableSetWait { 915 options: LocalCanonicalOptions { 916 core_type, 917 cancellable, 918 async_: false, 919 data_model: LocalDataModel::LinearMemory { 920 memory: Some(MemoryIndex::from_u32(memory)), 921 realloc: None, 922 }, 923 post_return: None, 924 callback: None, 925 string_encoding: StringEncoding::Utf8, 926 }, 927 } 928 } 929 wasmparser::CanonicalFunction::WaitableSetPoll { 930 cancellable, 931 memory, 932 } => { 933 let core_type = self.core_func_signature(core_func_index)?; 934 core_func_index += 1; 935 LocalInitializer::WaitableSetPoll { 936 options: LocalCanonicalOptions { 937 core_type, 938 async_: false, 939 cancellable, 940 data_model: LocalDataModel::LinearMemory { 941 memory: Some(MemoryIndex::from_u32(memory)), 942 realloc: None, 943 }, 944 post_return: None, 945 callback: None, 946 string_encoding: StringEncoding::Utf8, 947 }, 948 } 949 } 950 wasmparser::CanonicalFunction::WaitableSetDrop => { 951 let func = self.core_func_signature(core_func_index)?; 952 core_func_index += 1; 953 LocalInitializer::WaitableSetDrop { func } 954 } 955 wasmparser::CanonicalFunction::WaitableJoin => { 956 let func = self.core_func_signature(core_func_index)?; 957 core_func_index += 1; 958 LocalInitializer::WaitableJoin { func } 959 } 960 wasmparser::CanonicalFunction::ThreadYield { cancellable } => { 961 let func = self.core_func_signature(core_func_index)?; 962 core_func_index += 1; 963 LocalInitializer::ThreadYield { func, cancellable } 964 } 965 wasmparser::CanonicalFunction::SubtaskDrop => { 966 let func = self.core_func_signature(core_func_index)?; 967 core_func_index += 1; 968 LocalInitializer::SubtaskDrop { func } 969 } 970 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => { 971 let func = self.core_func_signature(core_func_index)?; 972 core_func_index += 1; 973 LocalInitializer::SubtaskCancel { func, async_ } 974 } 975 wasmparser::CanonicalFunction::StreamNew { ty } => { 976 let ty = self 977 .validator 978 .types(0) 979 .unwrap() 980 .component_defined_type_at(ty); 981 let func = self.core_func_signature(core_func_index)?; 982 core_func_index += 1; 983 LocalInitializer::StreamNew { ty, func } 984 } 985 wasmparser::CanonicalFunction::StreamRead { ty, options } => { 986 let ty = self 987 .validator 988 .types(0) 989 .unwrap() 990 .component_defined_type_at(ty); 991 let options = self.canonical_options(&options, core_func_index)?; 992 core_func_index += 1; 993 LocalInitializer::StreamRead { ty, options } 994 } 995 wasmparser::CanonicalFunction::StreamWrite { ty, options } => { 996 let ty = self 997 .validator 998 .types(0) 999 .unwrap() 1000 .component_defined_type_at(ty); 1001 let options = self.canonical_options(&options, core_func_index)?; 1002 core_func_index += 1; 1003 LocalInitializer::StreamWrite { ty, options } 1004 } 1005 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => { 1006 let ty = self 1007 .validator 1008 .types(0) 1009 .unwrap() 1010 .component_defined_type_at(ty); 1011 let func = self.core_func_signature(core_func_index)?; 1012 core_func_index += 1; 1013 LocalInitializer::StreamCancelRead { ty, func, async_ } 1014 } 1015 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => { 1016 let ty = self 1017 .validator 1018 .types(0) 1019 .unwrap() 1020 .component_defined_type_at(ty); 1021 let func = self.core_func_signature(core_func_index)?; 1022 core_func_index += 1; 1023 LocalInitializer::StreamCancelWrite { ty, func, async_ } 1024 } 1025 wasmparser::CanonicalFunction::StreamDropReadable { ty } => { 1026 let ty = self 1027 .validator 1028 .types(0) 1029 .unwrap() 1030 .component_defined_type_at(ty); 1031 let func = self.core_func_signature(core_func_index)?; 1032 core_func_index += 1; 1033 LocalInitializer::StreamDropReadable { ty, func } 1034 } 1035 wasmparser::CanonicalFunction::StreamDropWritable { ty } => { 1036 let ty = self 1037 .validator 1038 .types(0) 1039 .unwrap() 1040 .component_defined_type_at(ty); 1041 let func = self.core_func_signature(core_func_index)?; 1042 core_func_index += 1; 1043 LocalInitializer::StreamDropWritable { ty, func } 1044 } 1045 wasmparser::CanonicalFunction::FutureNew { ty } => { 1046 let ty = self 1047 .validator 1048 .types(0) 1049 .unwrap() 1050 .component_defined_type_at(ty); 1051 let func = self.core_func_signature(core_func_index)?; 1052 core_func_index += 1; 1053 LocalInitializer::FutureNew { ty, func } 1054 } 1055 wasmparser::CanonicalFunction::FutureRead { ty, options } => { 1056 let ty = self 1057 .validator 1058 .types(0) 1059 .unwrap() 1060 .component_defined_type_at(ty); 1061 let options = self.canonical_options(&options, core_func_index)?; 1062 core_func_index += 1; 1063 LocalInitializer::FutureRead { ty, options } 1064 } 1065 wasmparser::CanonicalFunction::FutureWrite { ty, options } => { 1066 let ty = self 1067 .validator 1068 .types(0) 1069 .unwrap() 1070 .component_defined_type_at(ty); 1071 let options = self.canonical_options(&options, core_func_index)?; 1072 core_func_index += 1; 1073 LocalInitializer::FutureWrite { ty, options } 1074 } 1075 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => { 1076 let ty = self 1077 .validator 1078 .types(0) 1079 .unwrap() 1080 .component_defined_type_at(ty); 1081 let func = self.core_func_signature(core_func_index)?; 1082 core_func_index += 1; 1083 LocalInitializer::FutureCancelRead { ty, func, async_ } 1084 } 1085 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => { 1086 let ty = self 1087 .validator 1088 .types(0) 1089 .unwrap() 1090 .component_defined_type_at(ty); 1091 let func = self.core_func_signature(core_func_index)?; 1092 core_func_index += 1; 1093 LocalInitializer::FutureCancelWrite { ty, func, async_ } 1094 } 1095 wasmparser::CanonicalFunction::FutureDropReadable { ty } => { 1096 let ty = self 1097 .validator 1098 .types(0) 1099 .unwrap() 1100 .component_defined_type_at(ty); 1101 let func = self.core_func_signature(core_func_index)?; 1102 core_func_index += 1; 1103 LocalInitializer::FutureDropReadable { ty, func } 1104 } 1105 wasmparser::CanonicalFunction::FutureDropWritable { ty } => { 1106 let ty = self 1107 .validator 1108 .types(0) 1109 .unwrap() 1110 .component_defined_type_at(ty); 1111 let func = self.core_func_signature(core_func_index)?; 1112 core_func_index += 1; 1113 LocalInitializer::FutureDropWritable { ty, func } 1114 } 1115 wasmparser::CanonicalFunction::ErrorContextNew { options } => { 1116 let options = self.canonical_options(&options, core_func_index)?; 1117 core_func_index += 1; 1118 LocalInitializer::ErrorContextNew { options } 1119 } 1120 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => { 1121 let options = self.canonical_options(&options, core_func_index)?; 1122 core_func_index += 1; 1123 LocalInitializer::ErrorContextDebugMessage { options } 1124 } 1125 wasmparser::CanonicalFunction::ErrorContextDrop => { 1126 let func = self.core_func_signature(core_func_index)?; 1127 core_func_index += 1; 1128 LocalInitializer::ErrorContextDrop { func } 1129 } 1130 wasmparser::CanonicalFunction::ContextGet(i) => { 1131 let func = self.core_func_signature(core_func_index)?; 1132 core_func_index += 1; 1133 LocalInitializer::ContextGet { i, func } 1134 } 1135 wasmparser::CanonicalFunction::ContextSet(i) => { 1136 let func = self.core_func_signature(core_func_index)?; 1137 core_func_index += 1; 1138 LocalInitializer::ContextSet { i, func } 1139 } 1140 wasmparser::CanonicalFunction::ThreadIndex => { 1141 let func = self.core_func_signature(core_func_index)?; 1142 core_func_index += 1; 1143 LocalInitializer::ThreadIndex { func } 1144 } 1145 wasmparser::CanonicalFunction::ThreadNewIndirect { 1146 func_ty_index, 1147 table_index, 1148 } => { 1149 let func = self.core_func_signature(core_func_index)?; 1150 core_func_index += 1; 1151 LocalInitializer::ThreadNewIndirect { 1152 func, 1153 start_func_ty: ComponentTypeIndex::from_u32(func_ty_index), 1154 start_func_table_index: TableIndex::from_u32(table_index), 1155 } 1156 } 1157 wasmparser::CanonicalFunction::ThreadSuspendToSuspended { cancellable } => { 1158 let func = self.core_func_signature(core_func_index)?; 1159 core_func_index += 1; 1160 LocalInitializer::ThreadSuspendToSuspended { func, cancellable } 1161 } 1162 wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => { 1163 let func = self.core_func_signature(core_func_index)?; 1164 core_func_index += 1; 1165 LocalInitializer::ThreadSuspend { func, cancellable } 1166 } 1167 wasmparser::CanonicalFunction::ThreadSuspendTo { cancellable } => { 1168 let func = self.core_func_signature(core_func_index)?; 1169 core_func_index += 1; 1170 LocalInitializer::ThreadSuspendTo { func, cancellable } 1171 } 1172 wasmparser::CanonicalFunction::ThreadUnsuspend => { 1173 let func = self.core_func_signature(core_func_index)?; 1174 core_func_index += 1; 1175 LocalInitializer::ThreadUnsuspend { func } 1176 } 1177 wasmparser::CanonicalFunction::ThreadYieldToSuspended { cancellable } => { 1178 let func = self.core_func_signature(core_func_index)?; 1179 core_func_index += 1; 1180 LocalInitializer::ThreadYieldToSuspended { func, cancellable } 1181 } 1182 }; 1183 self.result.initializers.push(init); 1184 } 1185 } 1186 1187 // Core wasm modules are translated inline directly here with the 1188 // `ModuleEnvironment` from core wasm compilation. This will return 1189 // to the caller the size of the module so it knows how many bytes 1190 // of the input are skipped. 1191 // 1192 // Note that this is just initial type translation of the core wasm 1193 // module and actual function compilation is deferred until this 1194 // entire process has completed. 1195 Payload::ModuleSection { 1196 parser, 1197 unchecked_range, 1198 } => { 1199 let index = self.validator.types(0).unwrap().module_count(); 1200 self.validator.module_section(&unchecked_range)?; 1201 let static_module_index = self.static_modules.next_key(); 1202 let mut translation = ModuleEnvironment::new( 1203 self.tunables, 1204 self.validator, 1205 self.types.module_types_builder(), 1206 static_module_index, 1207 ) 1208 .translate( 1209 parser, 1210 component 1211 .get(unchecked_range.start..unchecked_range.end) 1212 .ok_or_else(|| { 1213 format_err!( 1214 "section range {}..{} is out of bounds (bound = {})", 1215 unchecked_range.start, 1216 unchecked_range.end, 1217 component.len() 1218 ) 1219 .context("wasm component contains an invalid module section") 1220 })?, 1221 )?; 1222 1223 translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap(); 1224 let static_module_index2 = self.static_modules.push(translation); 1225 assert_eq!(static_module_index, static_module_index2); 1226 let types = self.validator.types(0).unwrap(); 1227 let ty = types.module_at(index); 1228 self.result 1229 .initializers 1230 .push(LocalInitializer::ModuleStatic(static_module_index, ty)); 1231 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start)); 1232 } 1233 1234 // When a sub-component is found then the current translation state 1235 // is pushed onto the `lexical_scopes` stack. This will subsequently 1236 // get popped as part of `Payload::End` processing above. 1237 // 1238 // Note that the set of closure args for this new lexical scope 1239 // starts empty since it will only get populated if translation of 1240 // the nested component ends up aliasing some outer module or 1241 // component. 1242 Payload::ComponentSection { 1243 parser, 1244 unchecked_range, 1245 } => { 1246 self.validator.component_section(&unchecked_range)?; 1247 self.lexical_scopes.push(LexicalScope { 1248 parser: mem::replace(&mut self.parser, parser), 1249 translation: mem::take(&mut self.result), 1250 closure_args: ClosedOverVars::default(), 1251 }); 1252 } 1253 1254 // Both core wasm instances and component instances record 1255 // initializers of what form of instantiation is performed which 1256 // largely just records the arguments given from wasmparser into a 1257 // `HashMap` for processing later during inlining. 1258 Payload::InstanceSection(s) => { 1259 self.validator.instance_section(&s)?; 1260 for instance in s { 1261 let init = match instance? { 1262 wasmparser::Instance::Instantiate { module_index, args } => { 1263 let index = ModuleIndex::from_u32(module_index); 1264 self.instantiate_module(index, &args) 1265 } 1266 wasmparser::Instance::FromExports(exports) => { 1267 self.instantiate_module_from_exports(&exports) 1268 } 1269 }; 1270 self.result.initializers.push(init); 1271 } 1272 } 1273 Payload::ComponentInstanceSection(s) => { 1274 let mut index = self.validator.types(0).unwrap().component_instance_count(); 1275 self.validator.component_instance_section(&s)?; 1276 for instance in s { 1277 let types = self.validator.types(0).unwrap(); 1278 let ty = types.component_instance_at(index); 1279 let init = match instance? { 1280 wasmparser::ComponentInstance::Instantiate { 1281 component_index, 1282 args, 1283 } => { 1284 let index = ComponentIndex::from_u32(component_index); 1285 self.instantiate_component(index, &args, ty)? 1286 } 1287 wasmparser::ComponentInstance::FromExports(exports) => { 1288 self.instantiate_component_from_exports(&exports, ty)? 1289 } 1290 }; 1291 self.result.initializers.push(init); 1292 index += 1; 1293 } 1294 } 1295 1296 // Exports don't actually fill out the `initializers` array but 1297 // instead fill out the one other field in a `Translation`, the 1298 // `exports` field (as one might imagine). This for now simply 1299 // records the index of what's exported and that's tracked further 1300 // later during inlining. 1301 Payload::ComponentExportSection(s) => { 1302 self.validator.component_export_section(&s)?; 1303 for export in s { 1304 let export = export?; 1305 let item = self.kind_to_item(export.kind, export.index)?; 1306 let prev = self.result.exports.insert(export.name.0, item); 1307 assert!(prev.is_none()); 1308 self.result 1309 .initializers 1310 .push(LocalInitializer::Export(item)); 1311 } 1312 } 1313 1314 Payload::ComponentStartSection { start, range } => { 1315 self.validator.component_start_section(&start, &range)?; 1316 unimplemented!("component start section"); 1317 } 1318 1319 // Aliases of instance exports (either core or component) will be 1320 // recorded as an initializer of the appropriate type with outer 1321 // aliases handled specially via upvars and type processing. 1322 Payload::ComponentAliasSection(s) => { 1323 self.validator.component_alias_section(&s)?; 1324 for alias in s { 1325 let init = match alias? { 1326 wasmparser::ComponentAlias::InstanceExport { 1327 kind: _, 1328 instance_index, 1329 name, 1330 } => { 1331 let instance = ComponentInstanceIndex::from_u32(instance_index); 1332 LocalInitializer::AliasComponentExport(instance, name) 1333 } 1334 wasmparser::ComponentAlias::Outer { kind, count, index } => { 1335 self.alias_component_outer(kind, count, index); 1336 continue; 1337 } 1338 wasmparser::ComponentAlias::CoreInstanceExport { 1339 kind, 1340 instance_index, 1341 name, 1342 } => { 1343 let instance = ModuleInstanceIndex::from_u32(instance_index); 1344 self.alias_module_instance_export(kind, instance, name) 1345 } 1346 }; 1347 self.result.initializers.push(init); 1348 } 1349 } 1350 1351 // All custom sections are ignored by Wasmtime at this time. 1352 // 1353 // FIXME(WebAssembly/component-model#14): probably want to specify 1354 // and parse a `name` section here. 1355 Payload::CustomSection { .. } => {} 1356 1357 // Anything else is either not reachable since we never enable the 1358 // feature in Wasmtime or we do enable it and it's a bug we don't 1359 // implement it, so let validation take care of most errors here and 1360 // if it gets past validation provide a helpful error message to 1361 // debug. 1362 other => { 1363 self.validator.payload(&other)?; 1364 panic!("unimplemented section {other:?}"); 1365 } 1366 } 1367 1368 Ok(Action::KeepGoing) 1369 } 1370 instantiate_module( &mut self, module: ModuleIndex, raw_args: &[wasmparser::InstantiationArg<'data>], ) -> LocalInitializer<'data>1371 fn instantiate_module( 1372 &mut self, 1373 module: ModuleIndex, 1374 raw_args: &[wasmparser::InstantiationArg<'data>], 1375 ) -> LocalInitializer<'data> { 1376 let mut args = HashMap::with_capacity(raw_args.len()); 1377 for arg in raw_args { 1378 match arg.kind { 1379 wasmparser::InstantiationArgKind::Instance => { 1380 let idx = ModuleInstanceIndex::from_u32(arg.index); 1381 args.insert(arg.name, idx); 1382 } 1383 } 1384 } 1385 LocalInitializer::ModuleInstantiate(module, args) 1386 } 1387 1388 /// Creates a synthetic module from the list of items currently in the 1389 /// module and their given names. instantiate_module_from_exports( &mut self, exports: &[wasmparser::Export<'data>], ) -> LocalInitializer<'data>1390 fn instantiate_module_from_exports( 1391 &mut self, 1392 exports: &[wasmparser::Export<'data>], 1393 ) -> LocalInitializer<'data> { 1394 let mut map = HashMap::with_capacity(exports.len()); 1395 for export in exports { 1396 let idx = match export.kind { 1397 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => { 1398 let index = FuncIndex::from_u32(export.index); 1399 EntityIndex::Function(index) 1400 } 1401 wasmparser::ExternalKind::Table => { 1402 let index = TableIndex::from_u32(export.index); 1403 EntityIndex::Table(index) 1404 } 1405 wasmparser::ExternalKind::Memory => { 1406 let index = MemoryIndex::from_u32(export.index); 1407 EntityIndex::Memory(index) 1408 } 1409 wasmparser::ExternalKind::Global => { 1410 let index = GlobalIndex::from_u32(export.index); 1411 EntityIndex::Global(index) 1412 } 1413 wasmparser::ExternalKind::Tag => { 1414 let index = TagIndex::from_u32(export.index); 1415 EntityIndex::Tag(index) 1416 } 1417 }; 1418 map.insert(export.name, idx); 1419 } 1420 LocalInitializer::ModuleSynthetic(map) 1421 } 1422 instantiate_component( &mut self, component: ComponentIndex, raw_args: &[wasmparser::ComponentInstantiationArg<'data>], ty: ComponentInstanceTypeId, ) -> Result<LocalInitializer<'data>>1423 fn instantiate_component( 1424 &mut self, 1425 component: ComponentIndex, 1426 raw_args: &[wasmparser::ComponentInstantiationArg<'data>], 1427 ty: ComponentInstanceTypeId, 1428 ) -> Result<LocalInitializer<'data>> { 1429 let mut args = HashMap::with_capacity(raw_args.len()); 1430 for arg in raw_args { 1431 let idx = self.kind_to_item(arg.kind, arg.index)?; 1432 args.insert(arg.name, idx); 1433 } 1434 1435 Ok(LocalInitializer::ComponentInstantiate(component, args, ty)) 1436 } 1437 1438 /// Creates a synthetic module from the list of items currently in the 1439 /// module and their given names. instantiate_component_from_exports( &mut self, exports: &[wasmparser::ComponentExport<'data>], ty: ComponentInstanceTypeId, ) -> Result<LocalInitializer<'data>>1440 fn instantiate_component_from_exports( 1441 &mut self, 1442 exports: &[wasmparser::ComponentExport<'data>], 1443 ty: ComponentInstanceTypeId, 1444 ) -> Result<LocalInitializer<'data>> { 1445 let mut map = HashMap::with_capacity(exports.len()); 1446 for export in exports { 1447 let idx = self.kind_to_item(export.kind, export.index)?; 1448 map.insert(export.name.0, idx); 1449 } 1450 1451 Ok(LocalInitializer::ComponentSynthetic(map, ty)) 1452 } 1453 kind_to_item( &mut self, kind: wasmparser::ComponentExternalKind, index: u32, ) -> Result<ComponentItem>1454 fn kind_to_item( 1455 &mut self, 1456 kind: wasmparser::ComponentExternalKind, 1457 index: u32, 1458 ) -> Result<ComponentItem> { 1459 Ok(match kind { 1460 wasmparser::ComponentExternalKind::Func => { 1461 let index = ComponentFuncIndex::from_u32(index); 1462 ComponentItem::Func(index) 1463 } 1464 wasmparser::ComponentExternalKind::Module => { 1465 let index = ModuleIndex::from_u32(index); 1466 ComponentItem::Module(index) 1467 } 1468 wasmparser::ComponentExternalKind::Instance => { 1469 let index = ComponentInstanceIndex::from_u32(index); 1470 ComponentItem::ComponentInstance(index) 1471 } 1472 wasmparser::ComponentExternalKind::Component => { 1473 let index = ComponentIndex::from_u32(index); 1474 ComponentItem::Component(index) 1475 } 1476 wasmparser::ComponentExternalKind::Value => { 1477 unimplemented!("component values"); 1478 } 1479 wasmparser::ComponentExternalKind::Type => { 1480 let types = self.validator.types(0).unwrap(); 1481 let ty = types.component_any_type_at(index); 1482 ComponentItem::Type(ty) 1483 } 1484 }) 1485 } 1486 alias_module_instance_export( &mut self, kind: wasmparser::ExternalKind, instance: ModuleInstanceIndex, name: &'data str, ) -> LocalInitializer<'data>1487 fn alias_module_instance_export( 1488 &mut self, 1489 kind: wasmparser::ExternalKind, 1490 instance: ModuleInstanceIndex, 1491 name: &'data str, 1492 ) -> LocalInitializer<'data> { 1493 match kind { 1494 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => { 1495 LocalInitializer::AliasExportFunc(instance, name) 1496 } 1497 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name), 1498 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name), 1499 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name), 1500 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name), 1501 } 1502 } 1503 alias_component_outer( &mut self, kind: wasmparser::ComponentOuterAliasKind, count: u32, index: u32, )1504 fn alias_component_outer( 1505 &mut self, 1506 kind: wasmparser::ComponentOuterAliasKind, 1507 count: u32, 1508 index: u32, 1509 ) { 1510 match kind { 1511 wasmparser::ComponentOuterAliasKind::CoreType 1512 | wasmparser::ComponentOuterAliasKind::Type => {} 1513 1514 // For more information about the implementation of outer aliases 1515 // see the documentation of `LexicalScope`. Otherwise though the 1516 // main idea here is that the data to close over starts as `Local` 1517 // and then transitions to `Upvar` as its inserted into the parents 1518 // in order from target we're aliasing back to the current 1519 // component. 1520 wasmparser::ComponentOuterAliasKind::CoreModule => { 1521 let index = ModuleIndex::from_u32(index); 1522 let mut module = ClosedOverModule::Local(index); 1523 let depth = self.lexical_scopes.len() - (count as usize); 1524 for frame in self.lexical_scopes[depth..].iter_mut() { 1525 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module)); 1526 } 1527 1528 // If the `module` is still `Local` then the `depth` was 0 and 1529 // it's an alias into our own space. Otherwise it's switched to 1530 // an upvar and will index into the upvar space. Either way 1531 // it's just plumbed directly into the initializer. 1532 self.result 1533 .initializers 1534 .push(LocalInitializer::AliasModule(module)); 1535 } 1536 wasmparser::ComponentOuterAliasKind::Component => { 1537 let index = ComponentIndex::from_u32(index); 1538 let mut component = ClosedOverComponent::Local(index); 1539 let depth = self.lexical_scopes.len() - (count as usize); 1540 for frame in self.lexical_scopes[depth..].iter_mut() { 1541 component = 1542 ClosedOverComponent::Upvar(frame.closure_args.components.push(component)); 1543 } 1544 1545 self.result 1546 .initializers 1547 .push(LocalInitializer::AliasComponent(component)); 1548 } 1549 } 1550 } 1551 canonical_options( &mut self, opts: &[wasmparser::CanonicalOption], core_func_index: u32, ) -> WasmResult<LocalCanonicalOptions>1552 fn canonical_options( 1553 &mut self, 1554 opts: &[wasmparser::CanonicalOption], 1555 core_func_index: u32, 1556 ) -> WasmResult<LocalCanonicalOptions> { 1557 let core_type = self.core_func_signature(core_func_index)?; 1558 1559 let mut string_encoding = StringEncoding::Utf8; 1560 let mut post_return = None; 1561 let mut async_ = false; 1562 let mut callback = None; 1563 let mut memory = None; 1564 let mut realloc = None; 1565 let mut gc = false; 1566 1567 for opt in opts { 1568 match opt { 1569 wasmparser::CanonicalOption::UTF8 => { 1570 string_encoding = StringEncoding::Utf8; 1571 } 1572 wasmparser::CanonicalOption::UTF16 => { 1573 string_encoding = StringEncoding::Utf16; 1574 } 1575 wasmparser::CanonicalOption::CompactUTF16 => { 1576 string_encoding = StringEncoding::CompactUtf16; 1577 } 1578 wasmparser::CanonicalOption::Memory(idx) => { 1579 let idx = MemoryIndex::from_u32(*idx); 1580 memory = Some(idx); 1581 } 1582 wasmparser::CanonicalOption::Realloc(idx) => { 1583 let idx = FuncIndex::from_u32(*idx); 1584 realloc = Some(idx); 1585 } 1586 wasmparser::CanonicalOption::PostReturn(idx) => { 1587 let idx = FuncIndex::from_u32(*idx); 1588 post_return = Some(idx); 1589 } 1590 wasmparser::CanonicalOption::Async => async_ = true, 1591 wasmparser::CanonicalOption::Callback(idx) => { 1592 let idx = FuncIndex::from_u32(*idx); 1593 callback = Some(idx); 1594 } 1595 wasmparser::CanonicalOption::CoreType(idx) => { 1596 if cfg!(debug_assertions) { 1597 let types = self.validator.types(0).unwrap(); 1598 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub(); 1599 let interned = self 1600 .types 1601 .module_types_builder() 1602 .intern_type(types, core_ty_id)?; 1603 debug_assert_eq!(interned, core_type); 1604 } 1605 } 1606 wasmparser::CanonicalOption::Gc => { 1607 gc = true; 1608 } 1609 } 1610 } 1611 1612 Ok(LocalCanonicalOptions { 1613 string_encoding, 1614 post_return, 1615 cancellable: false, 1616 async_, 1617 callback, 1618 core_type, 1619 data_model: if gc { 1620 LocalDataModel::Gc {} 1621 } else { 1622 LocalDataModel::LinearMemory { memory, realloc } 1623 }, 1624 }) 1625 } 1626 1627 /// Get the interned type index for the `index`th core function. core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex>1628 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> { 1629 let types = self.validator.types(0).unwrap(); 1630 let id = types.core_function_at(index); 1631 self.types.module_types_builder().intern_type(types, id) 1632 } 1633 is_unsafe_intrinsics_import(&self, import: &str) -> bool1634 fn is_unsafe_intrinsics_import(&self, import: &str) -> bool { 1635 self.lexical_scopes.is_empty() 1636 && self 1637 .unsafe_intrinsics_import 1638 .is_some_and(|name| import == name) 1639 } 1640 check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()>1641 fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> { 1642 let types = &self.validator.types(0).unwrap(); 1643 1644 let ComponentEntityType::Instance(instance_ty) = ty else { 1645 bail!("bad unsafe intrinsics import: import `{import}` must be an instance import") 1646 }; 1647 let instance_ty = &types[instance_ty]; 1648 1649 ensure!( 1650 instance_ty.defined_resources.is_empty(), 1651 "bad unsafe intrinsics import: import `{import}` cannot define any resources" 1652 ); 1653 ensure!( 1654 instance_ty.explicit_resources.is_empty(), 1655 "bad unsafe intrinsics import: import `{import}` cannot export any resources" 1656 ); 1657 1658 for (name, ty) in &instance_ty.exports { 1659 let ComponentEntityType::Func(func_ty) = ty else { 1660 bail!( 1661 "bad unsafe intrinsics import: imported instance `{import}` must \ 1662 only export functions" 1663 ) 1664 }; 1665 let func_ty = &types[*func_ty]; 1666 1667 fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool { 1668 use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C}; 1669 match (a, b) { 1670 (InterfaceType::U8, C::Primitive(P::U8)) => true, 1671 (InterfaceType::U8, _) => false, 1672 1673 (InterfaceType::U16, C::Primitive(P::U16)) => true, 1674 (InterfaceType::U16, _) => false, 1675 1676 (InterfaceType::U32, C::Primitive(P::U32)) => true, 1677 (InterfaceType::U32, _) => false, 1678 1679 (InterfaceType::U64, C::Primitive(P::U64)) => true, 1680 (InterfaceType::U64, _) => false, 1681 1682 (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"), 1683 } 1684 } 1685 1686 fn check_types<'a>( 1687 expected: impl ExactSizeIterator<Item = &'a InterfaceType>, 1688 actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>, 1689 kind: &str, 1690 import: &str, 1691 name: &str, 1692 ) -> Result<()> { 1693 let expected_len = expected.len(); 1694 let actual_len = actual.len(); 1695 ensure!( 1696 expected_len == actual_len, 1697 "bad unsafe intrinsics import at `{import}`: function `{name}` must have \ 1698 {expected_len} {kind}, found {actual_len}" 1699 ); 1700 1701 for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() { 1702 ensure!( 1703 ty_eq(expected_ty, actual_ty), 1704 "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \ 1705 `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`" 1706 ); 1707 } 1708 Ok(()) 1709 } 1710 1711 let intrinsic = UnsafeIntrinsic::from_str(name) 1712 .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?; 1713 1714 check_types( 1715 intrinsic.component_params().iter(), 1716 func_ty.params.iter().map(|(_name, ty)| ty), 1717 "parameters", 1718 &import, 1719 &name, 1720 )?; 1721 check_types( 1722 intrinsic.component_results().iter(), 1723 func_ty.result.iter(), 1724 "results", 1725 &import, 1726 &name, 1727 )?; 1728 } 1729 1730 Ok(()) 1731 } 1732 } 1733 1734 impl Translation<'_> { types_ref(&self) -> wasmparser::types::TypesRef<'_>1735 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> { 1736 self.types.as_ref().unwrap().as_ref() 1737 } 1738 } 1739 1740 /// A small helper module which wraps a `ComponentTypesBuilder` and attempts 1741 /// to disallow access to mutable access to the builder before the inlining 1742 /// pass. 1743 /// 1744 /// Type information in this translation pass must be preserved at the 1745 /// wasmparser layer of abstraction rather than being lowered into Wasmtime's 1746 /// own type system. Only during inlining are types fully assigned because 1747 /// that's when resource types become available as it's known which instance 1748 /// defines which resource, or more concretely the same component instantiated 1749 /// twice will produce two unique resource types unlike one as seen by 1750 /// wasmparser within the component. 1751 mod pre_inlining { 1752 use super::*; 1753 1754 pub struct PreInliningComponentTypes<'a> { 1755 types: &'a mut ComponentTypesBuilder, 1756 } 1757 1758 impl<'a> PreInliningComponentTypes<'a> { new(types: &'a mut ComponentTypesBuilder) -> Self1759 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self { 1760 Self { types } 1761 } 1762 module_types_builder(&mut self) -> &mut ModuleTypesBuilder1763 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder { 1764 self.types.module_types_builder_mut() 1765 } 1766 types(&self) -> &ComponentTypesBuilder1767 pub fn types(&self) -> &ComponentTypesBuilder { 1768 self.types 1769 } 1770 1771 // NB: this should in theory only be used for the `inline` phase of 1772 // translation. types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder1773 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder { 1774 self.types 1775 } 1776 } 1777 1778 impl TypeConvert for PreInliningComponentTypes<'_> { lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType1779 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType { 1780 self.types.lookup_heap_type(index) 1781 } 1782 lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex1783 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex { 1784 self.types.lookup_type_index(index) 1785 } 1786 } 1787 } 1788 use pre_inlining::PreInliningComponentTypes; 1789