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 options: LocalCanonicalOptions,
181 },
182 Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
183
184 Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
186 ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
187 ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
188 ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
189
190 BackpressureSet {
191 func: ModuleInternedTypeIndex,
192 },
193 TaskReturn {
194 result: Option<ComponentValType>,
195 options: LocalCanonicalOptions,
196 },
197 TaskCancel {
198 func: ModuleInternedTypeIndex,
199 },
200 WaitableSetNew {
201 func: ModuleInternedTypeIndex,
202 },
203 WaitableSetWait {
204 func: ModuleInternedTypeIndex,
205 async_: bool,
206 memory: MemoryIndex,
207 },
208 WaitableSetPoll {
209 func: ModuleInternedTypeIndex,
210 async_: bool,
211 memory: MemoryIndex,
212 },
213 WaitableSetDrop {
214 func: ModuleInternedTypeIndex,
215 },
216 WaitableJoin {
217 func: ModuleInternedTypeIndex,
218 },
219 Yield {
220 func: ModuleInternedTypeIndex,
221 async_: bool,
222 },
223 SubtaskDrop {
224 func: ModuleInternedTypeIndex,
225 },
226 SubtaskCancel {
227 func: ModuleInternedTypeIndex,
228 async_: bool,
229 },
230 StreamNew {
231 ty: ComponentDefinedTypeId,
232 func: ModuleInternedTypeIndex,
233 },
234 StreamRead {
235 ty: ComponentDefinedTypeId,
236 options: LocalCanonicalOptions,
237 },
238 StreamWrite {
239 ty: ComponentDefinedTypeId,
240 options: LocalCanonicalOptions,
241 },
242 StreamCancelRead {
243 ty: ComponentDefinedTypeId,
244 func: ModuleInternedTypeIndex,
245 async_: bool,
246 },
247 StreamCancelWrite {
248 ty: ComponentDefinedTypeId,
249 func: ModuleInternedTypeIndex,
250 async_: bool,
251 },
252 StreamDropReadable {
253 ty: ComponentDefinedTypeId,
254 func: ModuleInternedTypeIndex,
255 },
256 StreamDropWritable {
257 ty: ComponentDefinedTypeId,
258 func: ModuleInternedTypeIndex,
259 },
260 FutureNew {
261 ty: ComponentDefinedTypeId,
262 func: ModuleInternedTypeIndex,
263 },
264 FutureRead {
265 ty: ComponentDefinedTypeId,
266 options: LocalCanonicalOptions,
267 },
268 FutureWrite {
269 ty: ComponentDefinedTypeId,
270 options: LocalCanonicalOptions,
271 },
272 FutureCancelRead {
273 ty: ComponentDefinedTypeId,
274 func: ModuleInternedTypeIndex,
275 async_: bool,
276 },
277 FutureCancelWrite {
278 ty: ComponentDefinedTypeId,
279 func: ModuleInternedTypeIndex,
280 async_: bool,
281 },
282 FutureDropReadable {
283 ty: ComponentDefinedTypeId,
284 func: ModuleInternedTypeIndex,
285 },
286 FutureDropWritable {
287 ty: ComponentDefinedTypeId,
288 func: ModuleInternedTypeIndex,
289 },
290 ErrorContextNew {
291 options: LocalCanonicalOptions,
292 },
293 ErrorContextDebugMessage {
294 options: LocalCanonicalOptions,
295 },
296 ErrorContextDrop {
297 func: ModuleInternedTypeIndex,
298 },
299 ContextGet {
300 func: ModuleInternedTypeIndex,
301 i: u32,
302 },
303 ContextSet {
304 func: ModuleInternedTypeIndex,
305 i: u32,
306 },
307
308 ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
310
311 ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
313 ModuleSynthetic(HashMap<&'data str, EntityIndex>),
314
315 ComponentStatic(StaticComponentIndex, ClosedOverVars),
317
318 ComponentInstantiate(
320 ComponentIndex,
321 HashMap<&'data str, ComponentItem>,
322 ComponentInstanceTypeId,
323 ),
324 ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
325
326 AliasExportFunc(ModuleInstanceIndex, &'data str),
328 AliasExportTable(ModuleInstanceIndex, &'data str),
329 AliasExportGlobal(ModuleInstanceIndex, &'data str),
330 AliasExportMemory(ModuleInstanceIndex, &'data str),
331 AliasExportTag(ModuleInstanceIndex, &'data str),
332 AliasComponentExport(ComponentInstanceIndex, &'data str),
333 AliasModule(ClosedOverModule),
334 AliasComponent(ClosedOverComponent),
335
336 Export(ComponentItem),
338}
339
340#[derive(Default)]
344struct ClosedOverVars {
345 components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
346 modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
347}
348
349enum ClosedOverComponent {
354 Local(ComponentIndex),
357 Upvar(ComponentUpvarIndex),
362}
363
364enum ClosedOverModule {
366 Local(ModuleIndex),
367 Upvar(ModuleUpvarIndex),
368}
369
370#[derive(Debug, Clone, Hash, Eq, PartialEq)]
372pub enum LocalDataModel {
373 Gc {},
375
376 LinearMemory {
378 memory: Option<MemoryIndex>,
380 realloc: Option<FuncIndex>,
382 },
383}
384
385struct LocalCanonicalOptions {
387 string_encoding: StringEncoding,
388 post_return: Option<FuncIndex>,
389 async_: bool,
390 callback: Option<FuncIndex>,
391 core_type: ModuleInternedTypeIndex,
393 data_model: LocalDataModel,
394}
395
396enum Action {
397 KeepGoing,
398 Skip(usize),
399 Done,
400}
401
402impl<'a, 'data> Translator<'a, 'data> {
403 pub fn new(
405 tunables: &'a Tunables,
406 validator: &'a mut Validator,
407 types: &'a mut ComponentTypesBuilder,
408 scope_vec: &'data ScopeVec<u8>,
409 ) -> Self {
410 let mut parser = Parser::new(0);
411 parser.set_features(*validator.features());
412 Self {
413 result: Translation::default(),
414 tunables,
415 validator,
416 types: PreInliningComponentTypes::new(types),
417 parser,
418 lexical_scopes: Vec::new(),
419 static_components: Default::default(),
420 static_modules: Default::default(),
421 scope_vec,
422 }
423 }
424
425 pub fn translate(
449 mut self,
450 component: &'data [u8],
451 ) -> Result<(
452 ComponentTranslation,
453 PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
454 )> {
455 let mut remaining = component;
461 loop {
462 let payload = match self.parser.parse(remaining, true)? {
463 Chunk::Parsed { payload, consumed } => {
464 remaining = &remaining[consumed..];
465 payload
466 }
467 Chunk::NeedMoreData(_) => unreachable!(),
468 };
469
470 match self.translate_payload(payload, component)? {
471 Action::KeepGoing => {}
472 Action::Skip(n) => remaining = &remaining[n..],
473 Action::Done => break,
474 }
475 }
476 assert!(remaining.is_empty());
477 assert!(self.lexical_scopes.is_empty());
478
479 let mut component = inline::run(
490 self.types.types_mut_for_inlining(),
491 &self.result,
492 &self.static_modules,
493 &self.static_components,
494 )?;
495 self.partition_adapter_modules(&mut component);
496 let translation =
497 component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
498 Ok((translation, self.static_modules))
499 }
500
501 fn translate_payload(
502 &mut self,
503 payload: Payload<'data>,
504 component: &'data [u8],
505 ) -> Result<Action> {
506 match payload {
507 Payload::Version {
508 num,
509 encoding,
510 range,
511 } => {
512 self.validator.version(num, encoding, &range)?;
513
514 match encoding {
515 Encoding::Component => {}
516 Encoding::Module => {
517 bail!("attempted to parse a wasm module with a component parser");
518 }
519 }
520 }
521
522 Payload::End(offset) => {
523 assert!(self.result.types.is_none());
524 self.result.types = Some(self.validator.end(offset)?);
525
526 let LexicalScope {
531 parser,
532 translation,
533 closure_args,
534 } = match self.lexical_scopes.pop() {
535 Some(frame) => frame,
536 None => return Ok(Action::Done),
537 };
538 self.parser = parser;
539 let component = mem::replace(&mut self.result, translation);
540 let static_idx = self.static_components.push(component);
541 self.result
542 .initializers
543 .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
544 }
545
546 Payload::ComponentTypeSection(s) => {
555 let mut component_type_index =
556 self.validator.types(0).unwrap().component_type_count();
557 self.validator.component_type_section(&s)?;
558
559 let types = self.validator.types(0).unwrap();
563 for ty in s {
564 match ty? {
565 wasmparser::ComponentType::Resource { rep, dtor } => {
566 let rep = self.types.convert_valtype(rep)?;
567 let id = types
568 .component_any_type_at(component_type_index)
569 .unwrap_resource();
570 let dtor = dtor.map(FuncIndex::from_u32);
571 self.result
572 .initializers
573 .push(LocalInitializer::Resource(id, rep, dtor));
574 }
575
576 wasmparser::ComponentType::Defined(_)
578 | wasmparser::ComponentType::Func(_)
579 | wasmparser::ComponentType::Instance(_)
580 | wasmparser::ComponentType::Component(_) => {}
581 }
582
583 component_type_index += 1;
584 }
585 }
586 Payload::CoreTypeSection(s) => {
587 self.validator.core_type_section(&s)?;
588 }
589
590 Payload::ComponentImportSection(s) => {
594 self.validator.component_import_section(&s)?;
595 for import in s {
596 let import = import?;
597 let types = self.validator.types(0).unwrap();
598 let ty = types
599 .component_entity_type_of_import(import.name.0)
600 .unwrap();
601 self.result
602 .initializers
603 .push(LocalInitializer::Import(import.name, ty));
604 }
605 }
606
607 Payload::ComponentCanonicalSection(s) => {
610 let types = self.validator.types(0).unwrap();
611 let mut core_func_index = types.function_count();
612 self.validator.component_canonical_section(&s)?;
613 for func in s {
614 let init = match func? {
615 wasmparser::CanonicalFunction::Lift {
616 type_index,
617 core_func_index,
618 options,
619 } => {
620 let ty = self
621 .validator
622 .types(0)
623 .unwrap()
624 .component_any_type_at(type_index)
625 .unwrap_func();
626
627 let func = FuncIndex::from_u32(core_func_index);
628 let options = self.canonical_options(&options, core_func_index)?;
629 LocalInitializer::Lift(ty, func, options)
630 }
631 wasmparser::CanonicalFunction::Lower {
632 func_index,
633 options,
634 } => {
635 let lower_ty = self
636 .validator
637 .types(0)
638 .unwrap()
639 .component_function_at(func_index);
640 let func = ComponentFuncIndex::from_u32(func_index);
641 let options = self.canonical_options(&options, core_func_index)?;
642 core_func_index += 1;
643 LocalInitializer::Lower {
644 func,
645 options,
646 lower_ty,
647 }
648 }
649 wasmparser::CanonicalFunction::ResourceNew { resource } => {
650 let resource = self
651 .validator
652 .types(0)
653 .unwrap()
654 .component_any_type_at(resource)
655 .unwrap_resource();
656 let ty = self.core_func_signature(core_func_index)?;
657 core_func_index += 1;
658 LocalInitializer::ResourceNew(resource, ty)
659 }
660 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
661 let resource = self
662 .validator
663 .types(0)
664 .unwrap()
665 .component_any_type_at(resource)
666 .unwrap_resource();
667 let ty = self.core_func_signature(core_func_index)?;
668 core_func_index += 1;
669 LocalInitializer::ResourceDrop(resource, ty)
670 }
671 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
672 let _ = resource;
673 bail!("support for `resource.drop async` not implemented yet")
674 }
675 wasmparser::CanonicalFunction::ResourceRep { resource } => {
676 let resource = self
677 .validator
678 .types(0)
679 .unwrap()
680 .component_any_type_at(resource)
681 .unwrap_resource();
682 let ty = self.core_func_signature(core_func_index)?;
683 core_func_index += 1;
684 LocalInitializer::ResourceRep(resource, ty)
685 }
686 wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
687 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
688 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
689 bail!("unsupported intrinsic")
690 }
691 wasmparser::CanonicalFunction::BackpressureSet => {
692 let core_type = self.core_func_signature(core_func_index)?;
693 core_func_index += 1;
694 LocalInitializer::BackpressureSet { func: core_type }
695 }
696 wasmparser::CanonicalFunction::TaskReturn { result, options } => {
697 let result = result.map(|ty| match ty {
698 wasmparser::ComponentValType::Primitive(ty) => {
699 ComponentValType::Primitive(ty)
700 }
701 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
702 self.validator
703 .types(0)
704 .unwrap()
705 .component_defined_type_at(ty),
706 ),
707 });
708 let options = self.canonical_options(&options, core_func_index)?;
709 core_func_index += 1;
710 LocalInitializer::TaskReturn { result, options }
711 }
712 wasmparser::CanonicalFunction::TaskCancel => {
713 let func = self.core_func_signature(core_func_index)?;
714 core_func_index += 1;
715 LocalInitializer::TaskCancel { func }
716 }
717 wasmparser::CanonicalFunction::WaitableSetNew => {
718 let func = self.core_func_signature(core_func_index)?;
719 core_func_index += 1;
720 LocalInitializer::WaitableSetNew { func }
721 }
722 wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
723 let func = self.core_func_signature(core_func_index)?;
724 core_func_index += 1;
725 LocalInitializer::WaitableSetWait {
726 func,
727 async_,
728 memory: MemoryIndex::from_u32(memory),
729 }
730 }
731 wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
732 let func = self.core_func_signature(core_func_index)?;
733 core_func_index += 1;
734 LocalInitializer::WaitableSetPoll {
735 func,
736 async_,
737 memory: MemoryIndex::from_u32(memory),
738 }
739 }
740 wasmparser::CanonicalFunction::WaitableSetDrop => {
741 let func = self.core_func_signature(core_func_index)?;
742 core_func_index += 1;
743 LocalInitializer::WaitableSetDrop { func }
744 }
745 wasmparser::CanonicalFunction::WaitableJoin => {
746 let func = self.core_func_signature(core_func_index)?;
747 core_func_index += 1;
748 LocalInitializer::WaitableJoin { func }
749 }
750 wasmparser::CanonicalFunction::Yield { async_ } => {
751 let func = self.core_func_signature(core_func_index)?;
752 core_func_index += 1;
753 LocalInitializer::Yield { func, async_ }
754 }
755 wasmparser::CanonicalFunction::SubtaskDrop => {
756 let func = self.core_func_signature(core_func_index)?;
757 core_func_index += 1;
758 LocalInitializer::SubtaskDrop { func }
759 }
760 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
761 let func = self.core_func_signature(core_func_index)?;
762 core_func_index += 1;
763 LocalInitializer::SubtaskCancel { func, async_ }
764 }
765 wasmparser::CanonicalFunction::StreamNew { ty } => {
766 let ty = self
767 .validator
768 .types(0)
769 .unwrap()
770 .component_defined_type_at(ty);
771 let func = self.core_func_signature(core_func_index)?;
772 core_func_index += 1;
773 LocalInitializer::StreamNew { ty, func }
774 }
775 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
776 let ty = self
777 .validator
778 .types(0)
779 .unwrap()
780 .component_defined_type_at(ty);
781 let options = self.canonical_options(&options, core_func_index)?;
782 core_func_index += 1;
783 LocalInitializer::StreamRead { ty, options }
784 }
785 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
786 let ty = self
787 .validator
788 .types(0)
789 .unwrap()
790 .component_defined_type_at(ty);
791 let options = self.canonical_options(&options, core_func_index)?;
792 core_func_index += 1;
793 LocalInitializer::StreamWrite { ty, options }
794 }
795 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
796 let ty = self
797 .validator
798 .types(0)
799 .unwrap()
800 .component_defined_type_at(ty);
801 let func = self.core_func_signature(core_func_index)?;
802 core_func_index += 1;
803 LocalInitializer::StreamCancelRead { ty, func, async_ }
804 }
805 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
806 let ty = self
807 .validator
808 .types(0)
809 .unwrap()
810 .component_defined_type_at(ty);
811 let func = self.core_func_signature(core_func_index)?;
812 core_func_index += 1;
813 LocalInitializer::StreamCancelWrite { ty, func, async_ }
814 }
815 wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
816 let ty = self
817 .validator
818 .types(0)
819 .unwrap()
820 .component_defined_type_at(ty);
821 let func = self.core_func_signature(core_func_index)?;
822 core_func_index += 1;
823 LocalInitializer::StreamDropReadable { ty, func }
824 }
825 wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
826 let ty = self
827 .validator
828 .types(0)
829 .unwrap()
830 .component_defined_type_at(ty);
831 let func = self.core_func_signature(core_func_index)?;
832 core_func_index += 1;
833 LocalInitializer::StreamDropWritable { ty, func }
834 }
835 wasmparser::CanonicalFunction::FutureNew { ty } => {
836 let ty = self
837 .validator
838 .types(0)
839 .unwrap()
840 .component_defined_type_at(ty);
841 let func = self.core_func_signature(core_func_index)?;
842 core_func_index += 1;
843 LocalInitializer::FutureNew { ty, func }
844 }
845 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
846 let ty = self
847 .validator
848 .types(0)
849 .unwrap()
850 .component_defined_type_at(ty);
851 let options = self.canonical_options(&options, core_func_index)?;
852 core_func_index += 1;
853 LocalInitializer::FutureRead { ty, options }
854 }
855 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
856 let ty = self
857 .validator
858 .types(0)
859 .unwrap()
860 .component_defined_type_at(ty);
861 let options = self.canonical_options(&options, core_func_index)?;
862 core_func_index += 1;
863 LocalInitializer::FutureWrite { ty, options }
864 }
865 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
866 let ty = self
867 .validator
868 .types(0)
869 .unwrap()
870 .component_defined_type_at(ty);
871 let func = self.core_func_signature(core_func_index)?;
872 core_func_index += 1;
873 LocalInitializer::FutureCancelRead { ty, func, async_ }
874 }
875 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
876 let ty = self
877 .validator
878 .types(0)
879 .unwrap()
880 .component_defined_type_at(ty);
881 let func = self.core_func_signature(core_func_index)?;
882 core_func_index += 1;
883 LocalInitializer::FutureCancelWrite { ty, func, async_ }
884 }
885 wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
886 let ty = self
887 .validator
888 .types(0)
889 .unwrap()
890 .component_defined_type_at(ty);
891 let func = self.core_func_signature(core_func_index)?;
892 core_func_index += 1;
893 LocalInitializer::FutureDropReadable { ty, func }
894 }
895 wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
896 let ty = self
897 .validator
898 .types(0)
899 .unwrap()
900 .component_defined_type_at(ty);
901 let func = self.core_func_signature(core_func_index)?;
902 core_func_index += 1;
903 LocalInitializer::FutureDropWritable { ty, func }
904 }
905 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
906 let options = self.canonical_options(&options, core_func_index)?;
907 core_func_index += 1;
908 LocalInitializer::ErrorContextNew { options }
909 }
910 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
911 let options = self.canonical_options(&options, core_func_index)?;
912 core_func_index += 1;
913 LocalInitializer::ErrorContextDebugMessage { options }
914 }
915 wasmparser::CanonicalFunction::ErrorContextDrop => {
916 let func = self.core_func_signature(core_func_index)?;
917 core_func_index += 1;
918 LocalInitializer::ErrorContextDrop { func }
919 }
920 wasmparser::CanonicalFunction::ContextGet(i) => {
921 let func = self.core_func_signature(core_func_index)?;
922 core_func_index += 1;
923 LocalInitializer::ContextGet { i, func }
924 }
925 wasmparser::CanonicalFunction::ContextSet(i) => {
926 let func = self.core_func_signature(core_func_index)?;
927 core_func_index += 1;
928 LocalInitializer::ContextSet { i, func }
929 }
930 };
931 self.result.initializers.push(init);
932 }
933 }
934
935 Payload::ModuleSection {
944 parser,
945 unchecked_range,
946 } => {
947 let index = self.validator.types(0).unwrap().module_count();
948 self.validator.module_section(&unchecked_range)?;
949 let translation = ModuleEnvironment::new(
950 self.tunables,
951 self.validator,
952 self.types.module_types_builder(),
953 )
954 .translate(
955 parser,
956 component
957 .get(unchecked_range.start..unchecked_range.end)
958 .ok_or_else(|| {
959 anyhow!(
960 "section range {}..{} is out of bounds (bound = {})",
961 unchecked_range.start,
962 unchecked_range.end,
963 component.len()
964 )
965 .context("wasm component contains an invalid module section")
966 })?,
967 )?;
968 let static_idx = self.static_modules.push(translation);
969 let types = self.validator.types(0).unwrap();
970 let ty = types.module_at(index);
971 self.result
972 .initializers
973 .push(LocalInitializer::ModuleStatic(static_idx, ty));
974 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
975 }
976
977 Payload::ComponentSection {
986 parser,
987 unchecked_range,
988 } => {
989 self.validator.component_section(&unchecked_range)?;
990 self.lexical_scopes.push(LexicalScope {
991 parser: mem::replace(&mut self.parser, parser),
992 translation: mem::take(&mut self.result),
993 closure_args: ClosedOverVars::default(),
994 });
995 }
996
997 Payload::InstanceSection(s) => {
1002 self.validator.instance_section(&s)?;
1003 for instance in s {
1004 let init = match instance? {
1005 wasmparser::Instance::Instantiate { module_index, args } => {
1006 let index = ModuleIndex::from_u32(module_index);
1007 self.instantiate_module(index, &args)
1008 }
1009 wasmparser::Instance::FromExports(exports) => {
1010 self.instantiate_module_from_exports(&exports)
1011 }
1012 };
1013 self.result.initializers.push(init);
1014 }
1015 }
1016 Payload::ComponentInstanceSection(s) => {
1017 let mut index = self.validator.types(0).unwrap().component_instance_count();
1018 self.validator.component_instance_section(&s)?;
1019 for instance in s {
1020 let types = self.validator.types(0).unwrap();
1021 let ty = types.component_instance_at(index);
1022 let init = match instance? {
1023 wasmparser::ComponentInstance::Instantiate {
1024 component_index,
1025 args,
1026 } => {
1027 let index = ComponentIndex::from_u32(component_index);
1028 self.instantiate_component(index, &args, ty)?
1029 }
1030 wasmparser::ComponentInstance::FromExports(exports) => {
1031 self.instantiate_component_from_exports(&exports, ty)?
1032 }
1033 };
1034 self.result.initializers.push(init);
1035 index += 1;
1036 }
1037 }
1038
1039 Payload::ComponentExportSection(s) => {
1045 self.validator.component_export_section(&s)?;
1046 for export in s {
1047 let export = export?;
1048 let item = self.kind_to_item(export.kind, export.index)?;
1049 let prev = self.result.exports.insert(export.name.0, item);
1050 assert!(prev.is_none());
1051 self.result
1052 .initializers
1053 .push(LocalInitializer::Export(item));
1054 }
1055 }
1056
1057 Payload::ComponentStartSection { start, range } => {
1058 self.validator.component_start_section(&start, &range)?;
1059 unimplemented!("component start section");
1060 }
1061
1062 Payload::ComponentAliasSection(s) => {
1066 self.validator.component_alias_section(&s)?;
1067 for alias in s {
1068 let init = match alias? {
1069 wasmparser::ComponentAlias::InstanceExport {
1070 kind: _,
1071 instance_index,
1072 name,
1073 } => {
1074 let instance = ComponentInstanceIndex::from_u32(instance_index);
1075 LocalInitializer::AliasComponentExport(instance, name)
1076 }
1077 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1078 self.alias_component_outer(kind, count, index);
1079 continue;
1080 }
1081 wasmparser::ComponentAlias::CoreInstanceExport {
1082 kind,
1083 instance_index,
1084 name,
1085 } => {
1086 let instance = ModuleInstanceIndex::from_u32(instance_index);
1087 self.alias_module_instance_export(kind, instance, name)
1088 }
1089 };
1090 self.result.initializers.push(init);
1091 }
1092 }
1093
1094 Payload::CustomSection { .. } => {}
1099
1100 other => {
1106 self.validator.payload(&other)?;
1107 panic!("unimplemented section {other:?}");
1108 }
1109 }
1110
1111 Ok(Action::KeepGoing)
1112 }
1113
1114 fn instantiate_module(
1115 &mut self,
1116 module: ModuleIndex,
1117 raw_args: &[wasmparser::InstantiationArg<'data>],
1118 ) -> LocalInitializer<'data> {
1119 let mut args = HashMap::with_capacity(raw_args.len());
1120 for arg in raw_args {
1121 match arg.kind {
1122 wasmparser::InstantiationArgKind::Instance => {
1123 let idx = ModuleInstanceIndex::from_u32(arg.index);
1124 args.insert(arg.name, idx);
1125 }
1126 }
1127 }
1128 LocalInitializer::ModuleInstantiate(module, args)
1129 }
1130
1131 fn instantiate_module_from_exports(
1134 &mut self,
1135 exports: &[wasmparser::Export<'data>],
1136 ) -> LocalInitializer<'data> {
1137 let mut map = HashMap::with_capacity(exports.len());
1138 for export in exports {
1139 let idx = match export.kind {
1140 wasmparser::ExternalKind::Func => {
1141 let index = FuncIndex::from_u32(export.index);
1142 EntityIndex::Function(index)
1143 }
1144 wasmparser::ExternalKind::Table => {
1145 let index = TableIndex::from_u32(export.index);
1146 EntityIndex::Table(index)
1147 }
1148 wasmparser::ExternalKind::Memory => {
1149 let index = MemoryIndex::from_u32(export.index);
1150 EntityIndex::Memory(index)
1151 }
1152 wasmparser::ExternalKind::Global => {
1153 let index = GlobalIndex::from_u32(export.index);
1154 EntityIndex::Global(index)
1155 }
1156 wasmparser::ExternalKind::Tag => {
1157 let index = TagIndex::from_u32(export.index);
1158 EntityIndex::Tag(index)
1159 }
1160 };
1161 map.insert(export.name, idx);
1162 }
1163 LocalInitializer::ModuleSynthetic(map)
1164 }
1165
1166 fn instantiate_component(
1167 &mut self,
1168 component: ComponentIndex,
1169 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1170 ty: ComponentInstanceTypeId,
1171 ) -> Result<LocalInitializer<'data>> {
1172 let mut args = HashMap::with_capacity(raw_args.len());
1173 for arg in raw_args {
1174 let idx = self.kind_to_item(arg.kind, arg.index)?;
1175 args.insert(arg.name, idx);
1176 }
1177
1178 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1179 }
1180
1181 fn instantiate_component_from_exports(
1184 &mut self,
1185 exports: &[wasmparser::ComponentExport<'data>],
1186 ty: ComponentInstanceTypeId,
1187 ) -> Result<LocalInitializer<'data>> {
1188 let mut map = HashMap::with_capacity(exports.len());
1189 for export in exports {
1190 let idx = self.kind_to_item(export.kind, export.index)?;
1191 map.insert(export.name.0, idx);
1192 }
1193
1194 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1195 }
1196
1197 fn kind_to_item(
1198 &mut self,
1199 kind: wasmparser::ComponentExternalKind,
1200 index: u32,
1201 ) -> Result<ComponentItem> {
1202 Ok(match kind {
1203 wasmparser::ComponentExternalKind::Func => {
1204 let index = ComponentFuncIndex::from_u32(index);
1205 ComponentItem::Func(index)
1206 }
1207 wasmparser::ComponentExternalKind::Module => {
1208 let index = ModuleIndex::from_u32(index);
1209 ComponentItem::Module(index)
1210 }
1211 wasmparser::ComponentExternalKind::Instance => {
1212 let index = ComponentInstanceIndex::from_u32(index);
1213 ComponentItem::ComponentInstance(index)
1214 }
1215 wasmparser::ComponentExternalKind::Component => {
1216 let index = ComponentIndex::from_u32(index);
1217 ComponentItem::Component(index)
1218 }
1219 wasmparser::ComponentExternalKind::Value => {
1220 unimplemented!("component values");
1221 }
1222 wasmparser::ComponentExternalKind::Type => {
1223 let types = self.validator.types(0).unwrap();
1224 let ty = types.component_any_type_at(index);
1225 ComponentItem::Type(ty)
1226 }
1227 })
1228 }
1229
1230 fn alias_module_instance_export(
1231 &mut self,
1232 kind: wasmparser::ExternalKind,
1233 instance: ModuleInstanceIndex,
1234 name: &'data str,
1235 ) -> LocalInitializer<'data> {
1236 match kind {
1237 wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1238 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1239 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1240 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1241 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1242 }
1243 }
1244
1245 fn alias_component_outer(
1246 &mut self,
1247 kind: wasmparser::ComponentOuterAliasKind,
1248 count: u32,
1249 index: u32,
1250 ) {
1251 match kind {
1252 wasmparser::ComponentOuterAliasKind::CoreType
1253 | wasmparser::ComponentOuterAliasKind::Type => {}
1254
1255 wasmparser::ComponentOuterAliasKind::CoreModule => {
1262 let index = ModuleIndex::from_u32(index);
1263 let mut module = ClosedOverModule::Local(index);
1264 let depth = self.lexical_scopes.len() - (count as usize);
1265 for frame in self.lexical_scopes[depth..].iter_mut() {
1266 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1267 }
1268
1269 self.result
1274 .initializers
1275 .push(LocalInitializer::AliasModule(module));
1276 }
1277 wasmparser::ComponentOuterAliasKind::Component => {
1278 let index = ComponentIndex::from_u32(index);
1279 let mut component = ClosedOverComponent::Local(index);
1280 let depth = self.lexical_scopes.len() - (count as usize);
1281 for frame in self.lexical_scopes[depth..].iter_mut() {
1282 component =
1283 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1284 }
1285
1286 self.result
1287 .initializers
1288 .push(LocalInitializer::AliasComponent(component));
1289 }
1290 }
1291 }
1292
1293 fn canonical_options(
1294 &mut self,
1295 opts: &[wasmparser::CanonicalOption],
1296 core_func_index: u32,
1297 ) -> WasmResult<LocalCanonicalOptions> {
1298 let core_type = self.core_func_signature(core_func_index)?;
1299
1300 let mut string_encoding = StringEncoding::Utf8;
1301 let mut post_return = None;
1302 let mut async_ = false;
1303 let mut callback = None;
1304 let mut memory = None;
1305 let mut realloc = None;
1306 let mut gc = false;
1307
1308 for opt in opts {
1309 match opt {
1310 wasmparser::CanonicalOption::UTF8 => {
1311 string_encoding = StringEncoding::Utf8;
1312 }
1313 wasmparser::CanonicalOption::UTF16 => {
1314 string_encoding = StringEncoding::Utf16;
1315 }
1316 wasmparser::CanonicalOption::CompactUTF16 => {
1317 string_encoding = StringEncoding::CompactUtf16;
1318 }
1319 wasmparser::CanonicalOption::Memory(idx) => {
1320 let idx = MemoryIndex::from_u32(*idx);
1321 memory = Some(idx);
1322 }
1323 wasmparser::CanonicalOption::Realloc(idx) => {
1324 let idx = FuncIndex::from_u32(*idx);
1325 realloc = Some(idx);
1326 }
1327 wasmparser::CanonicalOption::PostReturn(idx) => {
1328 let idx = FuncIndex::from_u32(*idx);
1329 post_return = Some(idx);
1330 }
1331 wasmparser::CanonicalOption::Async => async_ = true,
1332 wasmparser::CanonicalOption::Callback(idx) => {
1333 let idx = FuncIndex::from_u32(*idx);
1334 callback = Some(idx);
1335 }
1336 wasmparser::CanonicalOption::CoreType(idx) => {
1337 if cfg!(debug_assertions) {
1338 let types = self.validator.types(0).unwrap();
1339 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1340 let interned = self
1341 .types
1342 .module_types_builder()
1343 .intern_type(types, core_ty_id)?;
1344 debug_assert_eq!(interned, core_type);
1345 }
1346 }
1347 wasmparser::CanonicalOption::Gc => {
1348 gc = true;
1349 }
1350 }
1351 }
1352
1353 Ok(LocalCanonicalOptions {
1354 string_encoding,
1355 post_return,
1356 async_,
1357 callback,
1358 core_type,
1359 data_model: if gc {
1360 LocalDataModel::Gc {}
1361 } else {
1362 LocalDataModel::LinearMemory { memory, realloc }
1363 },
1364 })
1365 }
1366
1367 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1369 let types = self.validator.types(0).unwrap();
1370 let id = types.core_function_at(index);
1371 self.types.module_types_builder().intern_type(types, id)
1372 }
1373}
1374
1375impl Translation<'_> {
1376 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1377 self.types.as_ref().unwrap().as_ref()
1378 }
1379}
1380
1381mod pre_inlining {
1393 use super::*;
1394
1395 pub struct PreInliningComponentTypes<'a> {
1396 types: &'a mut ComponentTypesBuilder,
1397 }
1398
1399 impl<'a> PreInliningComponentTypes<'a> {
1400 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1401 Self { types }
1402 }
1403
1404 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1405 self.types.module_types_builder_mut()
1406 }
1407
1408 pub fn types(&self) -> &ComponentTypesBuilder {
1409 self.types
1410 }
1411
1412 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1415 self.types
1416 }
1417 }
1418
1419 impl TypeConvert for PreInliningComponentTypes<'_> {
1420 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1421 self.types.lookup_heap_type(index)
1422 }
1423
1424 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1425 self.types.lookup_type_index(index)
1426 }
1427 }
1428}
1429use pre_inlining::PreInliningComponentTypes;