1use crate::ScopeVec;
2use crate::component::*;
3use crate::prelude::*;
4use crate::{
5 EngineOrModuleTypeIndex, EntityIndex, ModuleEnvironment, ModuleInternedTypeIndex,
6 ModuleTranslation, ModuleTypesBuilder, PrimaryMap, TagIndex, Tunables, TypeConvert,
7 WasmHeapType, WasmResult, WasmValType,
8};
9use anyhow::anyhow;
10use anyhow::{Result, bail};
11use indexmap::IndexMap;
12use std::collections::HashMap;
13use std::mem;
14use wasmparser::component_types::{
15 AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
16 ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
17};
18use wasmparser::types::Types;
19use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
20
21mod adapt;
22pub use self::adapt::*;
23mod inline;
24
25pub struct Translator<'a, 'data> {
27 result: Translation<'data>,
32
33 parser: Parser,
36
37 lexical_scopes: Vec<LexicalScope<'data>>,
45
46 validator: &'a mut Validator,
49
50 types: PreInliningComponentTypes<'a>,
55
56 tunables: &'a Tunables,
58
59 scope_vec: &'data ScopeVec<u8>,
61
62 static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
67
68 static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
73}
74
75struct LexicalScope<'data> {
128 parser: Parser,
130 translation: Translation<'data>,
132 closure_args: ClosedOverVars,
135}
136
137#[derive(Default)]
147struct Translation<'data> {
148 initializers: Vec<LocalInitializer<'data>>,
154
155 exports: IndexMap<&'data str, ComponentItem>,
158
159 types: Option<Types>,
165}
166
167enum LocalInitializer<'data> {
173 Import(ComponentImportName<'data>, ComponentEntityType),
175
176 Lower {
178 func: ComponentFuncIndex,
179 lower_ty: ComponentFuncTypeId,
180 canonical_abi: ModuleInternedTypeIndex,
181 options: LocalCanonicalOptions,
182 },
183 Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
184
185 Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
187 ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
188 ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
189 ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
190
191 BackpressureSet {
192 func: ModuleInternedTypeIndex,
193 },
194 TaskReturn {
195 func: ModuleInternedTypeIndex,
196 result: Option<ComponentValType>,
197 options: LocalCanonicalOptions,
198 },
199 TaskCancel {
200 func: ModuleInternedTypeIndex,
201 },
202 WaitableSetNew {
203 func: ModuleInternedTypeIndex,
204 },
205 WaitableSetWait {
206 func: ModuleInternedTypeIndex,
207 async_: bool,
208 memory: MemoryIndex,
209 },
210 WaitableSetPoll {
211 func: ModuleInternedTypeIndex,
212 async_: bool,
213 memory: MemoryIndex,
214 },
215 WaitableSetDrop {
216 func: ModuleInternedTypeIndex,
217 },
218 WaitableJoin {
219 func: ModuleInternedTypeIndex,
220 },
221 Yield {
222 func: ModuleInternedTypeIndex,
223 async_: bool,
224 },
225 SubtaskDrop {
226 func: ModuleInternedTypeIndex,
227 },
228 SubtaskCancel {
229 func: ModuleInternedTypeIndex,
230 async_: bool,
231 },
232 StreamNew {
233 ty: ComponentDefinedTypeId,
234 func: ModuleInternedTypeIndex,
235 },
236 StreamRead {
237 ty: ComponentDefinedTypeId,
238 func: ModuleInternedTypeIndex,
239 options: LocalCanonicalOptions,
240 },
241 StreamWrite {
242 ty: ComponentDefinedTypeId,
243 func: ModuleInternedTypeIndex,
244 options: LocalCanonicalOptions,
245 },
246 StreamCancelRead {
247 ty: ComponentDefinedTypeId,
248 func: ModuleInternedTypeIndex,
249 async_: bool,
250 },
251 StreamCancelWrite {
252 ty: ComponentDefinedTypeId,
253 func: ModuleInternedTypeIndex,
254 async_: bool,
255 },
256 StreamCloseReadable {
257 ty: ComponentDefinedTypeId,
258 func: ModuleInternedTypeIndex,
259 },
260 StreamCloseWritable {
261 ty: ComponentDefinedTypeId,
262 func: ModuleInternedTypeIndex,
263 },
264 FutureNew {
265 ty: ComponentDefinedTypeId,
266 func: ModuleInternedTypeIndex,
267 },
268 FutureRead {
269 ty: ComponentDefinedTypeId,
270 func: ModuleInternedTypeIndex,
271 options: LocalCanonicalOptions,
272 },
273 FutureWrite {
274 ty: ComponentDefinedTypeId,
275 func: ModuleInternedTypeIndex,
276 options: LocalCanonicalOptions,
277 },
278 FutureCancelRead {
279 ty: ComponentDefinedTypeId,
280 func: ModuleInternedTypeIndex,
281 async_: bool,
282 },
283 FutureCancelWrite {
284 ty: ComponentDefinedTypeId,
285 func: ModuleInternedTypeIndex,
286 async_: bool,
287 },
288 FutureCloseReadable {
289 ty: ComponentDefinedTypeId,
290 func: ModuleInternedTypeIndex,
291 },
292 FutureCloseWritable {
293 ty: ComponentDefinedTypeId,
294 func: ModuleInternedTypeIndex,
295 },
296 ErrorContextNew {
297 func: ModuleInternedTypeIndex,
298 options: LocalCanonicalOptions,
299 },
300 ErrorContextDebugMessage {
301 func: ModuleInternedTypeIndex,
302 options: LocalCanonicalOptions,
303 },
304 ErrorContextDrop {
305 func: ModuleInternedTypeIndex,
306 },
307 ContextGet {
308 func: ModuleInternedTypeIndex,
309 i: u32,
310 },
311 ContextSet {
312 func: ModuleInternedTypeIndex,
313 i: u32,
314 },
315
316 ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
318
319 ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
321 ModuleSynthetic(HashMap<&'data str, EntityIndex>),
322
323 ComponentStatic(StaticComponentIndex, ClosedOverVars),
325
326 ComponentInstantiate(
328 ComponentIndex,
329 HashMap<&'data str, ComponentItem>,
330 ComponentInstanceTypeId,
331 ),
332 ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
333
334 AliasExportFunc(ModuleInstanceIndex, &'data str),
336 AliasExportTable(ModuleInstanceIndex, &'data str),
337 AliasExportGlobal(ModuleInstanceIndex, &'data str),
338 AliasExportMemory(ModuleInstanceIndex, &'data str),
339 AliasExportTag(ModuleInstanceIndex, &'data str),
340 AliasComponentExport(ComponentInstanceIndex, &'data str),
341 AliasModule(ClosedOverModule),
342 AliasComponent(ClosedOverComponent),
343
344 Export(ComponentItem),
346}
347
348#[derive(Default)]
352struct ClosedOverVars {
353 components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
354 modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
355}
356
357enum ClosedOverComponent {
362 Local(ComponentIndex),
365 Upvar(ComponentUpvarIndex),
370}
371
372enum ClosedOverModule {
374 Local(ModuleIndex),
375 Upvar(ModuleUpvarIndex),
376}
377
378struct LocalCanonicalOptions {
380 string_encoding: StringEncoding,
381 memory: Option<MemoryIndex>,
382 realloc: Option<FuncIndex>,
383 post_return: Option<FuncIndex>,
384 async_: bool,
385 callback: Option<FuncIndex>,
386}
387
388enum Action {
389 KeepGoing,
390 Skip(usize),
391 Done,
392}
393
394impl<'a, 'data> Translator<'a, 'data> {
395 pub fn new(
397 tunables: &'a Tunables,
398 validator: &'a mut Validator,
399 types: &'a mut ComponentTypesBuilder,
400 scope_vec: &'data ScopeVec<u8>,
401 ) -> Self {
402 let mut parser = Parser::new(0);
403 parser.set_features(*validator.features());
404 Self {
405 result: Translation::default(),
406 tunables,
407 validator,
408 types: PreInliningComponentTypes::new(types),
409 parser,
410 lexical_scopes: Vec::new(),
411 static_components: Default::default(),
412 static_modules: Default::default(),
413 scope_vec,
414 }
415 }
416
417 pub fn translate(
441 mut self,
442 component: &'data [u8],
443 ) -> Result<(
444 ComponentTranslation,
445 PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
446 )> {
447 let mut remaining = component;
453 loop {
454 let payload = match self.parser.parse(remaining, true)? {
455 Chunk::Parsed { payload, consumed } => {
456 remaining = &remaining[consumed..];
457 payload
458 }
459 Chunk::NeedMoreData(_) => unreachable!(),
460 };
461
462 match self.translate_payload(payload, component)? {
463 Action::KeepGoing => {}
464 Action::Skip(n) => remaining = &remaining[n..],
465 Action::Done => break,
466 }
467 }
468 assert!(remaining.is_empty());
469 assert!(self.lexical_scopes.is_empty());
470
471 let mut component = inline::run(
482 self.types.types_mut_for_inlining(),
483 &self.result,
484 &self.static_modules,
485 &self.static_components,
486 )?;
487 self.partition_adapter_modules(&mut component);
488 let translation =
489 component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
490 Ok((translation, self.static_modules))
491 }
492
493 fn translate_payload(
494 &mut self,
495 payload: Payload<'data>,
496 component: &'data [u8],
497 ) -> Result<Action> {
498 match payload {
499 Payload::Version {
500 num,
501 encoding,
502 range,
503 } => {
504 self.validator.version(num, encoding, &range)?;
505
506 match encoding {
507 Encoding::Component => {}
508 Encoding::Module => {
509 bail!("attempted to parse a wasm module with a component parser");
510 }
511 }
512 }
513
514 Payload::End(offset) => {
515 assert!(self.result.types.is_none());
516 self.result.types = Some(self.validator.end(offset)?);
517
518 let LexicalScope {
523 parser,
524 translation,
525 closure_args,
526 } = match self.lexical_scopes.pop() {
527 Some(frame) => frame,
528 None => return Ok(Action::Done),
529 };
530 self.parser = parser;
531 let component = mem::replace(&mut self.result, translation);
532 let static_idx = self.static_components.push(component);
533 self.result
534 .initializers
535 .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
536 }
537
538 Payload::ComponentTypeSection(s) => {
547 let mut component_type_index =
548 self.validator.types(0).unwrap().component_type_count();
549 self.validator.component_type_section(&s)?;
550
551 let types = self.validator.types(0).unwrap();
555 for ty in s {
556 match ty? {
557 wasmparser::ComponentType::Resource { rep, dtor } => {
558 let rep = self.types.convert_valtype(rep)?;
559 let id = types
560 .component_any_type_at(component_type_index)
561 .unwrap_resource();
562 let dtor = dtor.map(FuncIndex::from_u32);
563 self.result
564 .initializers
565 .push(LocalInitializer::Resource(id, rep, dtor));
566 }
567
568 wasmparser::ComponentType::Defined(_)
570 | wasmparser::ComponentType::Func(_)
571 | wasmparser::ComponentType::Instance(_)
572 | wasmparser::ComponentType::Component(_) => {}
573 }
574
575 component_type_index += 1;
576 }
577 }
578 Payload::CoreTypeSection(s) => {
579 self.validator.core_type_section(&s)?;
580 }
581
582 Payload::ComponentImportSection(s) => {
586 self.validator.component_import_section(&s)?;
587 for import in s {
588 let import = import?;
589 let types = self.validator.types(0).unwrap();
590 let ty = types
591 .component_entity_type_of_import(import.name.0)
592 .unwrap();
593 self.result
594 .initializers
595 .push(LocalInitializer::Import(import.name, ty));
596 }
597 }
598
599 Payload::ComponentCanonicalSection(s) => {
602 let types = self.validator.types(0).unwrap();
603 let mut core_func_index = types.function_count();
604 self.validator.component_canonical_section(&s)?;
605 for func in s {
606 let types = self.validator.types(0).unwrap();
607 let init = match func? {
608 wasmparser::CanonicalFunction::Lift {
609 type_index,
610 core_func_index,
611 options,
612 } => {
613 let ty = types.component_any_type_at(type_index).unwrap_func();
614 let func = FuncIndex::from_u32(core_func_index);
615 let options = self.canonical_options(&options);
616 LocalInitializer::Lift(ty, func, options)
617 }
618 wasmparser::CanonicalFunction::Lower {
619 func_index,
620 options,
621 } => {
622 let lower_ty = types.component_function_at(func_index);
623 let func = ComponentFuncIndex::from_u32(func_index);
624 let options = self.canonical_options(&options);
625 let canonical_abi = self.core_func_signature(core_func_index)?;
626
627 core_func_index += 1;
628 LocalInitializer::Lower {
629 func,
630 options,
631 canonical_abi,
632 lower_ty,
633 }
634 }
635 wasmparser::CanonicalFunction::ResourceNew { resource } => {
636 let resource = types.component_any_type_at(resource).unwrap_resource();
637 let ty = self.core_func_signature(core_func_index)?;
638 core_func_index += 1;
639 LocalInitializer::ResourceNew(resource, ty)
640 }
641 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
642 let resource = types.component_any_type_at(resource).unwrap_resource();
643 let ty = self.core_func_signature(core_func_index)?;
644 core_func_index += 1;
645 LocalInitializer::ResourceDrop(resource, ty)
646 }
647 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
648 let _ = resource;
649 bail!("support for `resource.drop async` not implemented yet")
650 }
651 wasmparser::CanonicalFunction::ResourceRep { resource } => {
652 let resource = types.component_any_type_at(resource).unwrap_resource();
653 let ty = self.core_func_signature(core_func_index)?;
654 core_func_index += 1;
655 LocalInitializer::ResourceRep(resource, ty)
656 }
657 wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
658 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
659 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
660 bail!("unsupported intrinsic")
661 }
662 wasmparser::CanonicalFunction::BackpressureSet => {
663 let core_type = self.core_func_signature(core_func_index)?;
664 core_func_index += 1;
665 LocalInitializer::BackpressureSet { func: core_type }
666 }
667 wasmparser::CanonicalFunction::TaskReturn { result, options } => {
668 let result = result.map(|ty| match ty {
669 wasmparser::ComponentValType::Primitive(ty) => {
670 ComponentValType::Primitive(ty)
671 }
672 wasmparser::ComponentValType::Type(ty) => {
673 ComponentValType::Type(types.component_defined_type_at(ty))
674 }
675 });
676 let options = self.canonical_options(&options);
677 let func = self.core_func_signature(core_func_index)?;
678 core_func_index += 1;
679 LocalInitializer::TaskReturn {
680 func,
681 result,
682 options,
683 }
684 }
685 wasmparser::CanonicalFunction::TaskCancel => {
686 let func = self.core_func_signature(core_func_index)?;
687 core_func_index += 1;
688 LocalInitializer::TaskCancel { func }
689 }
690 wasmparser::CanonicalFunction::WaitableSetNew => {
691 let func = self.core_func_signature(core_func_index)?;
692 core_func_index += 1;
693 LocalInitializer::WaitableSetNew { func }
694 }
695 wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
696 let func = self.core_func_signature(core_func_index)?;
697 core_func_index += 1;
698 LocalInitializer::WaitableSetWait {
699 func,
700 async_,
701 memory: MemoryIndex::from_u32(memory),
702 }
703 }
704 wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
705 let func = self.core_func_signature(core_func_index)?;
706 core_func_index += 1;
707 LocalInitializer::WaitableSetPoll {
708 func,
709 async_,
710 memory: MemoryIndex::from_u32(memory),
711 }
712 }
713 wasmparser::CanonicalFunction::WaitableSetDrop => {
714 let func = self.core_func_signature(core_func_index)?;
715 core_func_index += 1;
716 LocalInitializer::WaitableSetDrop { func }
717 }
718 wasmparser::CanonicalFunction::WaitableJoin => {
719 let func = self.core_func_signature(core_func_index)?;
720 core_func_index += 1;
721 LocalInitializer::WaitableJoin { func }
722 }
723 wasmparser::CanonicalFunction::Yield { async_ } => {
724 let func = self.core_func_signature(core_func_index)?;
725 core_func_index += 1;
726 LocalInitializer::Yield { func, async_ }
727 }
728 wasmparser::CanonicalFunction::SubtaskDrop => {
729 let func = self.core_func_signature(core_func_index)?;
730 core_func_index += 1;
731 LocalInitializer::SubtaskDrop { func }
732 }
733 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
734 let func = self.core_func_signature(core_func_index)?;
735 core_func_index += 1;
736 LocalInitializer::SubtaskCancel { func, async_ }
737 }
738 wasmparser::CanonicalFunction::StreamNew { ty } => {
739 let ty = types.component_defined_type_at(ty);
740 let func = self.core_func_signature(core_func_index)?;
741 core_func_index += 1;
742 LocalInitializer::StreamNew { ty, func }
743 }
744 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
745 let ty = types.component_defined_type_at(ty);
746 let options = self.canonical_options(&options);
747 let func = self.core_func_signature(core_func_index)?;
748 core_func_index += 1;
749 LocalInitializer::StreamRead { ty, func, options }
750 }
751 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
752 let ty = types.component_defined_type_at(ty);
753 let options = self.canonical_options(&options);
754 let func = self.core_func_signature(core_func_index)?;
755 core_func_index += 1;
756 LocalInitializer::StreamWrite { ty, func, options }
757 }
758 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
759 let ty = types.component_defined_type_at(ty);
760 let func = self.core_func_signature(core_func_index)?;
761 core_func_index += 1;
762 LocalInitializer::StreamCancelRead { ty, func, async_ }
763 }
764 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
765 let ty = types.component_defined_type_at(ty);
766 let func = self.core_func_signature(core_func_index)?;
767 core_func_index += 1;
768 LocalInitializer::StreamCancelWrite { ty, func, async_ }
769 }
770 wasmparser::CanonicalFunction::StreamCloseReadable { ty } => {
771 let ty = types.component_defined_type_at(ty);
772 let func = self.core_func_signature(core_func_index)?;
773 core_func_index += 1;
774 LocalInitializer::StreamCloseReadable { ty, func }
775 }
776 wasmparser::CanonicalFunction::StreamCloseWritable { ty } => {
777 let ty = types.component_defined_type_at(ty);
778 let func = self.core_func_signature(core_func_index)?;
779 core_func_index += 1;
780 LocalInitializer::StreamCloseWritable { ty, func }
781 }
782 wasmparser::CanonicalFunction::FutureNew { ty } => {
783 let ty = types.component_defined_type_at(ty);
784 let func = self.core_func_signature(core_func_index)?;
785 core_func_index += 1;
786 LocalInitializer::FutureNew { ty, func }
787 }
788 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
789 let ty = types.component_defined_type_at(ty);
790 let options = self.canonical_options(&options);
791 let func = self.core_func_signature(core_func_index)?;
792 core_func_index += 1;
793 LocalInitializer::FutureRead { ty, func, options }
794 }
795 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
796 let ty = types.component_defined_type_at(ty);
797 let options = self.canonical_options(&options);
798 let func = self.core_func_signature(core_func_index)?;
799 core_func_index += 1;
800 LocalInitializer::FutureWrite { ty, func, options }
801 }
802 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
803 let ty = types.component_defined_type_at(ty);
804 let func = self.core_func_signature(core_func_index)?;
805 core_func_index += 1;
806 LocalInitializer::FutureCancelRead { ty, func, async_ }
807 }
808 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
809 let ty = types.component_defined_type_at(ty);
810 let func = self.core_func_signature(core_func_index)?;
811 core_func_index += 1;
812 LocalInitializer::FutureCancelWrite { ty, func, async_ }
813 }
814 wasmparser::CanonicalFunction::FutureCloseReadable { ty } => {
815 let ty = types.component_defined_type_at(ty);
816 let func = self.core_func_signature(core_func_index)?;
817 core_func_index += 1;
818 LocalInitializer::FutureCloseReadable { ty, func }
819 }
820 wasmparser::CanonicalFunction::FutureCloseWritable { ty } => {
821 let ty = types.component_defined_type_at(ty);
822 let func = self.core_func_signature(core_func_index)?;
823 core_func_index += 1;
824 LocalInitializer::FutureCloseWritable { ty, func }
825 }
826 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
827 let options = self.canonical_options(&options);
828 let func = self.core_func_signature(core_func_index)?;
829 core_func_index += 1;
830 LocalInitializer::ErrorContextNew { func, options }
831 }
832 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
833 let options = self.canonical_options(&options);
834 let func = self.core_func_signature(core_func_index)?;
835 core_func_index += 1;
836 LocalInitializer::ErrorContextDebugMessage { func, options }
837 }
838 wasmparser::CanonicalFunction::ErrorContextDrop => {
839 let func = self.core_func_signature(core_func_index)?;
840 core_func_index += 1;
841 LocalInitializer::ErrorContextDrop { func }
842 }
843 wasmparser::CanonicalFunction::ContextGet(i) => {
844 let func = self.core_func_signature(core_func_index)?;
845 core_func_index += 1;
846 LocalInitializer::ContextGet { i, func }
847 }
848 wasmparser::CanonicalFunction::ContextSet(i) => {
849 let func = self.core_func_signature(core_func_index)?;
850 core_func_index += 1;
851 LocalInitializer::ContextSet { i, func }
852 }
853 };
854 self.result.initializers.push(init);
855 }
856 }
857
858 Payload::ModuleSection {
867 parser,
868 unchecked_range,
869 } => {
870 let index = self.validator.types(0).unwrap().module_count();
871 self.validator.module_section(&unchecked_range)?;
872 let translation = ModuleEnvironment::new(
873 self.tunables,
874 self.validator,
875 self.types.module_types_builder(),
876 )
877 .translate(
878 parser,
879 component
880 .get(unchecked_range.start..unchecked_range.end)
881 .ok_or_else(|| {
882 anyhow!(
883 "section range {}..{} is out of bounds (bound = {})",
884 unchecked_range.start,
885 unchecked_range.end,
886 component.len()
887 )
888 .context("wasm component contains an invalid module section")
889 })?,
890 )?;
891 let static_idx = self.static_modules.push(translation);
892 let types = self.validator.types(0).unwrap();
893 let ty = types.module_at(index);
894 self.result
895 .initializers
896 .push(LocalInitializer::ModuleStatic(static_idx, ty));
897 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
898 }
899
900 Payload::ComponentSection {
909 parser,
910 unchecked_range,
911 } => {
912 self.validator.component_section(&unchecked_range)?;
913 self.lexical_scopes.push(LexicalScope {
914 parser: mem::replace(&mut self.parser, parser),
915 translation: mem::take(&mut self.result),
916 closure_args: ClosedOverVars::default(),
917 });
918 }
919
920 Payload::InstanceSection(s) => {
925 self.validator.instance_section(&s)?;
926 for instance in s {
927 let init = match instance? {
928 wasmparser::Instance::Instantiate { module_index, args } => {
929 let index = ModuleIndex::from_u32(module_index);
930 self.instantiate_module(index, &args)
931 }
932 wasmparser::Instance::FromExports(exports) => {
933 self.instantiate_module_from_exports(&exports)
934 }
935 };
936 self.result.initializers.push(init);
937 }
938 }
939 Payload::ComponentInstanceSection(s) => {
940 let mut index = self.validator.types(0).unwrap().component_instance_count();
941 self.validator.component_instance_section(&s)?;
942 for instance in s {
943 let types = self.validator.types(0).unwrap();
944 let ty = types.component_instance_at(index);
945 let init = match instance? {
946 wasmparser::ComponentInstance::Instantiate {
947 component_index,
948 args,
949 } => {
950 let index = ComponentIndex::from_u32(component_index);
951 self.instantiate_component(index, &args, ty)?
952 }
953 wasmparser::ComponentInstance::FromExports(exports) => {
954 self.instantiate_component_from_exports(&exports, ty)?
955 }
956 };
957 self.result.initializers.push(init);
958 index += 1;
959 }
960 }
961
962 Payload::ComponentExportSection(s) => {
968 self.validator.component_export_section(&s)?;
969 for export in s {
970 let export = export?;
971 let item = self.kind_to_item(export.kind, export.index)?;
972 let prev = self.result.exports.insert(export.name.0, item);
973 assert!(prev.is_none());
974 self.result
975 .initializers
976 .push(LocalInitializer::Export(item));
977 }
978 }
979
980 Payload::ComponentStartSection { start, range } => {
981 self.validator.component_start_section(&start, &range)?;
982 unimplemented!("component start section");
983 }
984
985 Payload::ComponentAliasSection(s) => {
989 self.validator.component_alias_section(&s)?;
990 for alias in s {
991 let init = match alias? {
992 wasmparser::ComponentAlias::InstanceExport {
993 kind: _,
994 instance_index,
995 name,
996 } => {
997 let instance = ComponentInstanceIndex::from_u32(instance_index);
998 LocalInitializer::AliasComponentExport(instance, name)
999 }
1000 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1001 self.alias_component_outer(kind, count, index);
1002 continue;
1003 }
1004 wasmparser::ComponentAlias::CoreInstanceExport {
1005 kind,
1006 instance_index,
1007 name,
1008 } => {
1009 let instance = ModuleInstanceIndex::from_u32(instance_index);
1010 self.alias_module_instance_export(kind, instance, name)
1011 }
1012 };
1013 self.result.initializers.push(init);
1014 }
1015 }
1016
1017 Payload::CustomSection { .. } => {}
1022
1023 other => {
1029 self.validator.payload(&other)?;
1030 panic!("unimplemented section {other:?}");
1031 }
1032 }
1033
1034 Ok(Action::KeepGoing)
1035 }
1036
1037 fn instantiate_module(
1038 &mut self,
1039 module: ModuleIndex,
1040 raw_args: &[wasmparser::InstantiationArg<'data>],
1041 ) -> LocalInitializer<'data> {
1042 let mut args = HashMap::with_capacity(raw_args.len());
1043 for arg in raw_args {
1044 match arg.kind {
1045 wasmparser::InstantiationArgKind::Instance => {
1046 let idx = ModuleInstanceIndex::from_u32(arg.index);
1047 args.insert(arg.name, idx);
1048 }
1049 }
1050 }
1051 LocalInitializer::ModuleInstantiate(module, args)
1052 }
1053
1054 fn instantiate_module_from_exports(
1057 &mut self,
1058 exports: &[wasmparser::Export<'data>],
1059 ) -> LocalInitializer<'data> {
1060 let mut map = HashMap::with_capacity(exports.len());
1061 for export in exports {
1062 let idx = match export.kind {
1063 wasmparser::ExternalKind::Func => {
1064 let index = FuncIndex::from_u32(export.index);
1065 EntityIndex::Function(index)
1066 }
1067 wasmparser::ExternalKind::Table => {
1068 let index = TableIndex::from_u32(export.index);
1069 EntityIndex::Table(index)
1070 }
1071 wasmparser::ExternalKind::Memory => {
1072 let index = MemoryIndex::from_u32(export.index);
1073 EntityIndex::Memory(index)
1074 }
1075 wasmparser::ExternalKind::Global => {
1076 let index = GlobalIndex::from_u32(export.index);
1077 EntityIndex::Global(index)
1078 }
1079 wasmparser::ExternalKind::Tag => {
1080 let index = TagIndex::from_u32(export.index);
1081 EntityIndex::Tag(index)
1082 }
1083 };
1084 map.insert(export.name, idx);
1085 }
1086 LocalInitializer::ModuleSynthetic(map)
1087 }
1088
1089 fn instantiate_component(
1090 &mut self,
1091 component: ComponentIndex,
1092 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1093 ty: ComponentInstanceTypeId,
1094 ) -> Result<LocalInitializer<'data>> {
1095 let mut args = HashMap::with_capacity(raw_args.len());
1096 for arg in raw_args {
1097 let idx = self.kind_to_item(arg.kind, arg.index)?;
1098 args.insert(arg.name, idx);
1099 }
1100
1101 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1102 }
1103
1104 fn instantiate_component_from_exports(
1107 &mut self,
1108 exports: &[wasmparser::ComponentExport<'data>],
1109 ty: ComponentInstanceTypeId,
1110 ) -> Result<LocalInitializer<'data>> {
1111 let mut map = HashMap::with_capacity(exports.len());
1112 for export in exports {
1113 let idx = self.kind_to_item(export.kind, export.index)?;
1114 map.insert(export.name.0, idx);
1115 }
1116
1117 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1118 }
1119
1120 fn kind_to_item(
1121 &mut self,
1122 kind: wasmparser::ComponentExternalKind,
1123 index: u32,
1124 ) -> Result<ComponentItem> {
1125 Ok(match kind {
1126 wasmparser::ComponentExternalKind::Func => {
1127 let index = ComponentFuncIndex::from_u32(index);
1128 ComponentItem::Func(index)
1129 }
1130 wasmparser::ComponentExternalKind::Module => {
1131 let index = ModuleIndex::from_u32(index);
1132 ComponentItem::Module(index)
1133 }
1134 wasmparser::ComponentExternalKind::Instance => {
1135 let index = ComponentInstanceIndex::from_u32(index);
1136 ComponentItem::ComponentInstance(index)
1137 }
1138 wasmparser::ComponentExternalKind::Component => {
1139 let index = ComponentIndex::from_u32(index);
1140 ComponentItem::Component(index)
1141 }
1142 wasmparser::ComponentExternalKind::Value => {
1143 unimplemented!("component values");
1144 }
1145 wasmparser::ComponentExternalKind::Type => {
1146 let types = self.validator.types(0).unwrap();
1147 let ty = types.component_any_type_at(index);
1148 ComponentItem::Type(ty)
1149 }
1150 })
1151 }
1152
1153 fn alias_module_instance_export(
1154 &mut self,
1155 kind: wasmparser::ExternalKind,
1156 instance: ModuleInstanceIndex,
1157 name: &'data str,
1158 ) -> LocalInitializer<'data> {
1159 match kind {
1160 wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1161 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1162 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1163 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1164 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1165 }
1166 }
1167
1168 fn alias_component_outer(
1169 &mut self,
1170 kind: wasmparser::ComponentOuterAliasKind,
1171 count: u32,
1172 index: u32,
1173 ) {
1174 match kind {
1175 wasmparser::ComponentOuterAliasKind::CoreType
1176 | wasmparser::ComponentOuterAliasKind::Type => {}
1177
1178 wasmparser::ComponentOuterAliasKind::CoreModule => {
1185 let index = ModuleIndex::from_u32(index);
1186 let mut module = ClosedOverModule::Local(index);
1187 let depth = self.lexical_scopes.len() - (count as usize);
1188 for frame in self.lexical_scopes[depth..].iter_mut() {
1189 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1190 }
1191
1192 self.result
1197 .initializers
1198 .push(LocalInitializer::AliasModule(module));
1199 }
1200 wasmparser::ComponentOuterAliasKind::Component => {
1201 let index = ComponentIndex::from_u32(index);
1202 let mut component = ClosedOverComponent::Local(index);
1203 let depth = self.lexical_scopes.len() - (count as usize);
1204 for frame in self.lexical_scopes[depth..].iter_mut() {
1205 component =
1206 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1207 }
1208
1209 self.result
1210 .initializers
1211 .push(LocalInitializer::AliasComponent(component));
1212 }
1213 }
1214 }
1215
1216 fn canonical_options(&self, opts: &[wasmparser::CanonicalOption]) -> LocalCanonicalOptions {
1217 let mut ret = LocalCanonicalOptions {
1218 string_encoding: StringEncoding::Utf8,
1219 memory: None,
1220 realloc: None,
1221 post_return: None,
1222 async_: false,
1223 callback: None,
1224 };
1225 for opt in opts {
1226 match opt {
1227 wasmparser::CanonicalOption::UTF8 => {
1228 ret.string_encoding = StringEncoding::Utf8;
1229 }
1230 wasmparser::CanonicalOption::UTF16 => {
1231 ret.string_encoding = StringEncoding::Utf16;
1232 }
1233 wasmparser::CanonicalOption::CompactUTF16 => {
1234 ret.string_encoding = StringEncoding::CompactUtf16;
1235 }
1236 wasmparser::CanonicalOption::Memory(idx) => {
1237 let idx = MemoryIndex::from_u32(*idx);
1238 ret.memory = Some(idx);
1239 }
1240 wasmparser::CanonicalOption::Realloc(idx) => {
1241 let idx = FuncIndex::from_u32(*idx);
1242 ret.realloc = Some(idx);
1243 }
1244 wasmparser::CanonicalOption::PostReturn(idx) => {
1245 let idx = FuncIndex::from_u32(*idx);
1246 ret.post_return = Some(idx);
1247 }
1248 wasmparser::CanonicalOption::Async => ret.async_ = true,
1249 wasmparser::CanonicalOption::Callback(idx) => {
1250 let idx = FuncIndex::from_u32(*idx);
1251 ret.callback = Some(idx);
1252 }
1253 wasmparser::CanonicalOption::CoreType(_) | wasmparser::CanonicalOption::Gc => {
1254 todo!("component model and GC support")
1255 }
1256 }
1257 }
1258 return ret;
1259 }
1260
1261 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1263 let types = self.validator.types(0).unwrap();
1264 let id = types.core_function_at(index);
1265 self.types.module_types_builder().intern_type(types, id)
1266 }
1267}
1268
1269impl Translation<'_> {
1270 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1271 self.types.as_ref().unwrap().as_ref()
1272 }
1273}
1274
1275mod pre_inlining {
1287 use super::*;
1288
1289 pub struct PreInliningComponentTypes<'a> {
1290 types: &'a mut ComponentTypesBuilder,
1291 }
1292
1293 impl<'a> PreInliningComponentTypes<'a> {
1294 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1295 Self { types }
1296 }
1297
1298 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1299 self.types.module_types_builder_mut()
1300 }
1301
1302 pub fn types(&self) -> &ComponentTypesBuilder {
1303 self.types
1304 }
1305
1306 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1309 self.types
1310 }
1311 }
1312
1313 impl TypeConvert for PreInliningComponentTypes<'_> {
1314 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1315 self.types.lookup_heap_type(index)
1316 }
1317
1318 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1319 self.types.lookup_type_index(index)
1320 }
1321 }
1322}
1323use pre_inlining::PreInliningComponentTypes;