1use crate::ScopeVec;
2use crate::component::dfg::AbstractInstantiations;
3use crate::component::*;
4use crate::prelude::*;
5use crate::{
6 EngineOrModuleTypeIndex, EntityIndex, ModuleEnvironment, ModuleInternedTypeIndex,
7 ModuleTranslation, ModuleTypesBuilder, PrimaryMap, TagIndex, Tunables, TypeConvert,
8 WasmHeapType, WasmResult, WasmValType,
9};
10use anyhow::anyhow;
11use anyhow::{Result, bail};
12use cranelift_entity::SecondaryMap;
13use cranelift_entity::packed_option::PackedOption;
14use indexmap::IndexMap;
15use std::collections::HashMap;
16use std::mem;
17use wasmparser::component_types::{
18 AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
19 ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
20};
21use wasmparser::types::Types;
22use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
23
24mod adapt;
25pub use self::adapt::*;
26mod inline;
27
28pub struct Translator<'a, 'data> {
30 result: Translation<'data>,
35
36 parser: Parser,
39
40 lexical_scopes: Vec<LexicalScope<'data>>,
48
49 validator: &'a mut Validator,
52
53 types: PreInliningComponentTypes<'a>,
58
59 tunables: &'a Tunables,
61
62 scope_vec: &'data ScopeVec<u8>,
64
65 static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
70
71 static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
76}
77
78struct LexicalScope<'data> {
131 parser: Parser,
133 translation: Translation<'data>,
135 closure_args: ClosedOverVars,
138}
139
140#[derive(Default)]
150struct Translation<'data> {
151 initializers: Vec<LocalInitializer<'data>>,
157
158 exports: IndexMap<&'data str, ComponentItem>,
161
162 types: Option<Types>,
168}
169
170enum LocalInitializer<'data> {
176 Import(ComponentImportName<'data>, ComponentEntityType),
178
179 Lower {
181 func: ComponentFuncIndex,
182 lower_ty: ComponentFuncTypeId,
183 options: LocalCanonicalOptions,
184 },
185 Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
186
187 Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
189 ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
190 ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
191 ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
192
193 BackpressureSet {
194 func: ModuleInternedTypeIndex,
195 },
196 TaskReturn {
197 result: Option<ComponentValType>,
198 options: LocalCanonicalOptions,
199 },
200 TaskCancel {
201 func: ModuleInternedTypeIndex,
202 },
203 WaitableSetNew {
204 func: ModuleInternedTypeIndex,
205 },
206 WaitableSetWait {
207 options: LocalCanonicalOptions,
208 },
209 WaitableSetPoll {
210 options: LocalCanonicalOptions,
211 },
212 WaitableSetDrop {
213 func: ModuleInternedTypeIndex,
214 },
215 WaitableJoin {
216 func: ModuleInternedTypeIndex,
217 },
218 Yield {
219 func: ModuleInternedTypeIndex,
220 async_: bool,
221 },
222 SubtaskDrop {
223 func: ModuleInternedTypeIndex,
224 },
225 SubtaskCancel {
226 func: ModuleInternedTypeIndex,
227 async_: bool,
228 },
229 StreamNew {
230 ty: ComponentDefinedTypeId,
231 func: ModuleInternedTypeIndex,
232 },
233 StreamRead {
234 ty: ComponentDefinedTypeId,
235 options: LocalCanonicalOptions,
236 },
237 StreamWrite {
238 ty: ComponentDefinedTypeId,
239 options: LocalCanonicalOptions,
240 },
241 StreamCancelRead {
242 ty: ComponentDefinedTypeId,
243 func: ModuleInternedTypeIndex,
244 async_: bool,
245 },
246 StreamCancelWrite {
247 ty: ComponentDefinedTypeId,
248 func: ModuleInternedTypeIndex,
249 async_: bool,
250 },
251 StreamDropReadable {
252 ty: ComponentDefinedTypeId,
253 func: ModuleInternedTypeIndex,
254 },
255 StreamDropWritable {
256 ty: ComponentDefinedTypeId,
257 func: ModuleInternedTypeIndex,
258 },
259 FutureNew {
260 ty: ComponentDefinedTypeId,
261 func: ModuleInternedTypeIndex,
262 },
263 FutureRead {
264 ty: ComponentDefinedTypeId,
265 options: LocalCanonicalOptions,
266 },
267 FutureWrite {
268 ty: ComponentDefinedTypeId,
269 options: LocalCanonicalOptions,
270 },
271 FutureCancelRead {
272 ty: ComponentDefinedTypeId,
273 func: ModuleInternedTypeIndex,
274 async_: bool,
275 },
276 FutureCancelWrite {
277 ty: ComponentDefinedTypeId,
278 func: ModuleInternedTypeIndex,
279 async_: bool,
280 },
281 FutureDropReadable {
282 ty: ComponentDefinedTypeId,
283 func: ModuleInternedTypeIndex,
284 },
285 FutureDropWritable {
286 ty: ComponentDefinedTypeId,
287 func: ModuleInternedTypeIndex,
288 },
289 ErrorContextNew {
290 options: LocalCanonicalOptions,
291 },
292 ErrorContextDebugMessage {
293 options: LocalCanonicalOptions,
294 },
295 ErrorContextDrop {
296 func: ModuleInternedTypeIndex,
297 },
298 ContextGet {
299 func: ModuleInternedTypeIndex,
300 i: u32,
301 },
302 ContextSet {
303 func: ModuleInternedTypeIndex,
304 i: u32,
305 },
306
307 ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
309
310 ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
312 ModuleSynthetic(HashMap<&'data str, EntityIndex>),
313
314 ComponentStatic(StaticComponentIndex, ClosedOverVars),
316
317 ComponentInstantiate(
319 ComponentIndex,
320 HashMap<&'data str, ComponentItem>,
321 ComponentInstanceTypeId,
322 ),
323 ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
324
325 AliasExportFunc(ModuleInstanceIndex, &'data str),
327 AliasExportTable(ModuleInstanceIndex, &'data str),
328 AliasExportGlobal(ModuleInstanceIndex, &'data str),
329 AliasExportMemory(ModuleInstanceIndex, &'data str),
330 AliasExportTag(ModuleInstanceIndex, &'data str),
331 AliasComponentExport(ComponentInstanceIndex, &'data str),
332 AliasModule(ClosedOverModule),
333 AliasComponent(ClosedOverComponent),
334
335 Export(ComponentItem),
337}
338
339#[derive(Default)]
343struct ClosedOverVars {
344 components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
345 modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
346}
347
348enum ClosedOverComponent {
353 Local(ComponentIndex),
356 Upvar(ComponentUpvarIndex),
361}
362
363enum ClosedOverModule {
365 Local(ModuleIndex),
366 Upvar(ModuleUpvarIndex),
367}
368
369#[derive(Debug, Clone, Hash, Eq, PartialEq)]
371pub enum LocalDataModel {
372 Gc {},
374
375 LinearMemory {
377 memory: Option<MemoryIndex>,
379 realloc: Option<FuncIndex>,
381 },
382}
383
384struct LocalCanonicalOptions {
386 string_encoding: StringEncoding,
387 post_return: Option<FuncIndex>,
388 async_: bool,
389 callback: Option<FuncIndex>,
390 core_type: ModuleInternedTypeIndex,
392 data_model: LocalDataModel,
393}
394
395enum Action {
396 KeepGoing,
397 Skip(usize),
398 Done,
399}
400
401impl<'a, 'data> Translator<'a, 'data> {
402 pub fn new(
404 tunables: &'a Tunables,
405 validator: &'a mut Validator,
406 types: &'a mut ComponentTypesBuilder,
407 scope_vec: &'data ScopeVec<u8>,
408 ) -> Self {
409 let mut parser = Parser::new(0);
410 parser.set_features(*validator.features());
411 Self {
412 result: Translation::default(),
413 tunables,
414 validator,
415 types: PreInliningComponentTypes::new(types),
416 parser,
417 lexical_scopes: Vec::new(),
418 static_components: Default::default(),
419 static_modules: Default::default(),
420 scope_vec,
421 }
422 }
423
424 pub fn translate(
448 mut self,
449 component: &'data [u8],
450 ) -> Result<(
451 ComponentTranslation,
452 PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
453 )> {
454 let mut remaining = component;
460 loop {
461 let payload = match self.parser.parse(remaining, true)? {
462 Chunk::Parsed { payload, consumed } => {
463 remaining = &remaining[consumed..];
464 payload
465 }
466 Chunk::NeedMoreData(_) => unreachable!(),
467 };
468
469 match self.translate_payload(payload, component)? {
470 Action::KeepGoing => {}
471 Action::Skip(n) => remaining = &remaining[n..],
472 Action::Done => break,
473 }
474 }
475 assert!(remaining.is_empty());
476 assert!(self.lexical_scopes.is_empty());
477
478 let mut component = inline::run(
489 self.types.types_mut_for_inlining(),
490 &self.result,
491 &self.static_modules,
492 &self.static_components,
493 )?;
494
495 self.partition_adapter_modules(&mut component);
496
497 let translation =
498 component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
499
500 self.analyze_function_imports(&translation);
501
502 Ok((translation, self.static_modules))
503 }
504
505 fn analyze_function_imports(&mut self, translation: &ComponentTranslation) {
506 let mut instantiations = SecondaryMap::<StaticModuleIndex, AbstractInstantiations>::new();
509 let mut instance_to_module =
510 PrimaryMap::<RuntimeInstanceIndex, PackedOption<StaticModuleIndex>>::new();
511 for init in &translation.component.initializers {
512 match init {
513 GlobalInitializer::InstantiateModule(instantiation) => match instantiation {
514 InstantiateModule::Static(module, args) => {
515 instantiations[*module].join(AbstractInstantiations::One(&*args));
516 instance_to_module.push(Some(*module).into());
517 }
518 _ => {
519 instance_to_module.push(None.into());
520 }
521 },
522 _ => continue,
523 }
524 }
525
526 for item in translation.component.export_items.values() {
529 if let Export::ModuleStatic { index, .. } = item {
530 instantiations[*index].join(AbstractInstantiations::Many)
531 }
532 }
533
534 for (module, instantiations) in instantiations.iter() {
539 let args = match instantiations {
540 dfg::AbstractInstantiations::Many | dfg::AbstractInstantiations::None => continue,
541 dfg::AbstractInstantiations::One(args) => args,
542 };
543
544 let mut imported_func_counter = 0_u32;
545 for (i, arg) in args.iter().enumerate() {
546 let (_, _, crate::types::EntityType::Function(_)) =
548 self.static_modules[module].module.import(i).unwrap()
549 else {
550 continue;
551 };
552
553 let imported_func = FuncIndex::from_u32(imported_func_counter);
554 imported_func_counter += 1;
555 debug_assert!(
556 self.static_modules[module]
557 .module
558 .defined_func_index(imported_func)
559 .is_none()
560 );
561
562 match arg {
563 CoreDef::InstanceFlags(_) => unreachable!("instance flags are not a function"),
564
565 CoreDef::Trampoline(_) => continue,
578
579 CoreDef::Export(export) => {
583 let Some(arg_module) = &instance_to_module[export.instance].expand() else {
584 continue;
589 };
590
591 let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
592 else {
593 unreachable!("function imports must be functions")
594 };
595
596 let Some(arg_module_def_func) = self.static_modules[*arg_module]
597 .module
598 .defined_func_index(*arg_func)
599 else {
600 continue;
607 };
608
609 assert!(
610 self.static_modules[module].known_imported_functions[imported_func]
611 .is_none()
612 );
613 self.static_modules[module].known_imported_functions[imported_func] =
614 Some((*arg_module, arg_module_def_func));
615 }
616 }
617 }
618 }
619 }
620
621 fn translate_payload(
622 &mut self,
623 payload: Payload<'data>,
624 component: &'data [u8],
625 ) -> Result<Action> {
626 match payload {
627 Payload::Version {
628 num,
629 encoding,
630 range,
631 } => {
632 self.validator.version(num, encoding, &range)?;
633
634 match encoding {
635 Encoding::Component => {}
636 Encoding::Module => {
637 bail!("attempted to parse a wasm module with a component parser");
638 }
639 }
640 }
641
642 Payload::End(offset) => {
643 assert!(self.result.types.is_none());
644 self.result.types = Some(self.validator.end(offset)?);
645
646 let LexicalScope {
651 parser,
652 translation,
653 closure_args,
654 } = match self.lexical_scopes.pop() {
655 Some(frame) => frame,
656 None => return Ok(Action::Done),
657 };
658 self.parser = parser;
659 let component = mem::replace(&mut self.result, translation);
660 let static_idx = self.static_components.push(component);
661 self.result
662 .initializers
663 .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
664 }
665
666 Payload::ComponentTypeSection(s) => {
675 let mut component_type_index =
676 self.validator.types(0).unwrap().component_type_count();
677 self.validator.component_type_section(&s)?;
678
679 let types = self.validator.types(0).unwrap();
683 for ty in s {
684 match ty? {
685 wasmparser::ComponentType::Resource { rep, dtor } => {
686 let rep = self.types.convert_valtype(rep)?;
687 let id = types
688 .component_any_type_at(component_type_index)
689 .unwrap_resource();
690 let dtor = dtor.map(FuncIndex::from_u32);
691 self.result
692 .initializers
693 .push(LocalInitializer::Resource(id, rep, dtor));
694 }
695
696 wasmparser::ComponentType::Defined(_)
698 | wasmparser::ComponentType::Func(_)
699 | wasmparser::ComponentType::Instance(_)
700 | wasmparser::ComponentType::Component(_) => {}
701 }
702
703 component_type_index += 1;
704 }
705 }
706 Payload::CoreTypeSection(s) => {
707 self.validator.core_type_section(&s)?;
708 }
709
710 Payload::ComponentImportSection(s) => {
714 self.validator.component_import_section(&s)?;
715 for import in s {
716 let import = import?;
717 let types = self.validator.types(0).unwrap();
718 let ty = types
719 .component_entity_type_of_import(import.name.0)
720 .unwrap();
721 self.result
722 .initializers
723 .push(LocalInitializer::Import(import.name, ty));
724 }
725 }
726
727 Payload::ComponentCanonicalSection(s) => {
730 let types = self.validator.types(0).unwrap();
731 let mut core_func_index = types.function_count();
732 self.validator.component_canonical_section(&s)?;
733 for func in s {
734 let init = match func? {
735 wasmparser::CanonicalFunction::Lift {
736 type_index,
737 core_func_index,
738 options,
739 } => {
740 let ty = self
741 .validator
742 .types(0)
743 .unwrap()
744 .component_any_type_at(type_index)
745 .unwrap_func();
746
747 let func = FuncIndex::from_u32(core_func_index);
748 let options = self.canonical_options(&options, core_func_index)?;
749 LocalInitializer::Lift(ty, func, options)
750 }
751 wasmparser::CanonicalFunction::Lower {
752 func_index,
753 options,
754 } => {
755 let lower_ty = self
756 .validator
757 .types(0)
758 .unwrap()
759 .component_function_at(func_index);
760 let func = ComponentFuncIndex::from_u32(func_index);
761 let options = self.canonical_options(&options, core_func_index)?;
762 core_func_index += 1;
763 LocalInitializer::Lower {
764 func,
765 options,
766 lower_ty,
767 }
768 }
769 wasmparser::CanonicalFunction::ResourceNew { resource } => {
770 let resource = self
771 .validator
772 .types(0)
773 .unwrap()
774 .component_any_type_at(resource)
775 .unwrap_resource();
776 let ty = self.core_func_signature(core_func_index)?;
777 core_func_index += 1;
778 LocalInitializer::ResourceNew(resource, ty)
779 }
780 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
781 let resource = self
782 .validator
783 .types(0)
784 .unwrap()
785 .component_any_type_at(resource)
786 .unwrap_resource();
787 let ty = self.core_func_signature(core_func_index)?;
788 core_func_index += 1;
789 LocalInitializer::ResourceDrop(resource, ty)
790 }
791 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
792 let _ = resource;
793 bail!("support for `resource.drop async` not implemented yet")
794 }
795 wasmparser::CanonicalFunction::ResourceRep { resource } => {
796 let resource = self
797 .validator
798 .types(0)
799 .unwrap()
800 .component_any_type_at(resource)
801 .unwrap_resource();
802 let ty = self.core_func_signature(core_func_index)?;
803 core_func_index += 1;
804 LocalInitializer::ResourceRep(resource, ty)
805 }
806 wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
807 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
808 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
809 bail!("unsupported intrinsic")
810 }
811 wasmparser::CanonicalFunction::BackpressureSet => {
812 let core_type = self.core_func_signature(core_func_index)?;
813 core_func_index += 1;
814 LocalInitializer::BackpressureSet { func: core_type }
815 }
816 wasmparser::CanonicalFunction::TaskReturn { result, options } => {
817 let result = result.map(|ty| match ty {
818 wasmparser::ComponentValType::Primitive(ty) => {
819 ComponentValType::Primitive(ty)
820 }
821 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
822 self.validator
823 .types(0)
824 .unwrap()
825 .component_defined_type_at(ty),
826 ),
827 });
828 let options = self.canonical_options(&options, core_func_index)?;
829 core_func_index += 1;
830 LocalInitializer::TaskReturn { result, options }
831 }
832 wasmparser::CanonicalFunction::TaskCancel => {
833 let func = self.core_func_signature(core_func_index)?;
834 core_func_index += 1;
835 LocalInitializer::TaskCancel { func }
836 }
837 wasmparser::CanonicalFunction::WaitableSetNew => {
838 let func = self.core_func_signature(core_func_index)?;
839 core_func_index += 1;
840 LocalInitializer::WaitableSetNew { func }
841 }
842 wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
843 let core_type = self.core_func_signature(core_func_index)?;
844 core_func_index += 1;
845 LocalInitializer::WaitableSetWait {
846 options: LocalCanonicalOptions {
847 core_type,
848 async_,
849 data_model: LocalDataModel::LinearMemory {
850 memory: Some(MemoryIndex::from_u32(memory)),
851 realloc: None,
852 },
853 post_return: None,
854 callback: None,
855 string_encoding: StringEncoding::Utf8,
856 },
857 }
858 }
859 wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
860 let core_type = self.core_func_signature(core_func_index)?;
861 core_func_index += 1;
862 LocalInitializer::WaitableSetPoll {
863 options: LocalCanonicalOptions {
864 core_type,
865 async_,
866 data_model: LocalDataModel::LinearMemory {
867 memory: Some(MemoryIndex::from_u32(memory)),
868 realloc: None,
869 },
870 post_return: None,
871 callback: None,
872 string_encoding: StringEncoding::Utf8,
873 },
874 }
875 }
876 wasmparser::CanonicalFunction::WaitableSetDrop => {
877 let func = self.core_func_signature(core_func_index)?;
878 core_func_index += 1;
879 LocalInitializer::WaitableSetDrop { func }
880 }
881 wasmparser::CanonicalFunction::WaitableJoin => {
882 let func = self.core_func_signature(core_func_index)?;
883 core_func_index += 1;
884 LocalInitializer::WaitableJoin { func }
885 }
886 wasmparser::CanonicalFunction::Yield { async_ } => {
887 let func = self.core_func_signature(core_func_index)?;
888 core_func_index += 1;
889 LocalInitializer::Yield { func, async_ }
890 }
891 wasmparser::CanonicalFunction::SubtaskDrop => {
892 let func = self.core_func_signature(core_func_index)?;
893 core_func_index += 1;
894 LocalInitializer::SubtaskDrop { func }
895 }
896 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
897 let func = self.core_func_signature(core_func_index)?;
898 core_func_index += 1;
899 LocalInitializer::SubtaskCancel { func, async_ }
900 }
901 wasmparser::CanonicalFunction::StreamNew { ty } => {
902 let ty = self
903 .validator
904 .types(0)
905 .unwrap()
906 .component_defined_type_at(ty);
907 let func = self.core_func_signature(core_func_index)?;
908 core_func_index += 1;
909 LocalInitializer::StreamNew { ty, func }
910 }
911 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
912 let ty = self
913 .validator
914 .types(0)
915 .unwrap()
916 .component_defined_type_at(ty);
917 let options = self.canonical_options(&options, core_func_index)?;
918 core_func_index += 1;
919 LocalInitializer::StreamRead { ty, options }
920 }
921 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
922 let ty = self
923 .validator
924 .types(0)
925 .unwrap()
926 .component_defined_type_at(ty);
927 let options = self.canonical_options(&options, core_func_index)?;
928 core_func_index += 1;
929 LocalInitializer::StreamWrite { ty, options }
930 }
931 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
932 let ty = self
933 .validator
934 .types(0)
935 .unwrap()
936 .component_defined_type_at(ty);
937 let func = self.core_func_signature(core_func_index)?;
938 core_func_index += 1;
939 LocalInitializer::StreamCancelRead { ty, func, async_ }
940 }
941 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
942 let ty = self
943 .validator
944 .types(0)
945 .unwrap()
946 .component_defined_type_at(ty);
947 let func = self.core_func_signature(core_func_index)?;
948 core_func_index += 1;
949 LocalInitializer::StreamCancelWrite { ty, func, async_ }
950 }
951 wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
952 let ty = self
953 .validator
954 .types(0)
955 .unwrap()
956 .component_defined_type_at(ty);
957 let func = self.core_func_signature(core_func_index)?;
958 core_func_index += 1;
959 LocalInitializer::StreamDropReadable { ty, func }
960 }
961 wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
962 let ty = self
963 .validator
964 .types(0)
965 .unwrap()
966 .component_defined_type_at(ty);
967 let func = self.core_func_signature(core_func_index)?;
968 core_func_index += 1;
969 LocalInitializer::StreamDropWritable { ty, func }
970 }
971 wasmparser::CanonicalFunction::FutureNew { ty } => {
972 let ty = self
973 .validator
974 .types(0)
975 .unwrap()
976 .component_defined_type_at(ty);
977 let func = self.core_func_signature(core_func_index)?;
978 core_func_index += 1;
979 LocalInitializer::FutureNew { ty, func }
980 }
981 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
982 let ty = self
983 .validator
984 .types(0)
985 .unwrap()
986 .component_defined_type_at(ty);
987 let options = self.canonical_options(&options, core_func_index)?;
988 core_func_index += 1;
989 LocalInitializer::FutureRead { ty, options }
990 }
991 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
992 let ty = self
993 .validator
994 .types(0)
995 .unwrap()
996 .component_defined_type_at(ty);
997 let options = self.canonical_options(&options, core_func_index)?;
998 core_func_index += 1;
999 LocalInitializer::FutureWrite { ty, options }
1000 }
1001 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1002 let ty = self
1003 .validator
1004 .types(0)
1005 .unwrap()
1006 .component_defined_type_at(ty);
1007 let func = self.core_func_signature(core_func_index)?;
1008 core_func_index += 1;
1009 LocalInitializer::FutureCancelRead { ty, func, async_ }
1010 }
1011 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1012 let ty = self
1013 .validator
1014 .types(0)
1015 .unwrap()
1016 .component_defined_type_at(ty);
1017 let func = self.core_func_signature(core_func_index)?;
1018 core_func_index += 1;
1019 LocalInitializer::FutureCancelWrite { ty, func, async_ }
1020 }
1021 wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1022 let ty = self
1023 .validator
1024 .types(0)
1025 .unwrap()
1026 .component_defined_type_at(ty);
1027 let func = self.core_func_signature(core_func_index)?;
1028 core_func_index += 1;
1029 LocalInitializer::FutureDropReadable { ty, func }
1030 }
1031 wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1032 let ty = self
1033 .validator
1034 .types(0)
1035 .unwrap()
1036 .component_defined_type_at(ty);
1037 let func = self.core_func_signature(core_func_index)?;
1038 core_func_index += 1;
1039 LocalInitializer::FutureDropWritable { ty, func }
1040 }
1041 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1042 let options = self.canonical_options(&options, core_func_index)?;
1043 core_func_index += 1;
1044 LocalInitializer::ErrorContextNew { options }
1045 }
1046 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1047 let options = self.canonical_options(&options, core_func_index)?;
1048 core_func_index += 1;
1049 LocalInitializer::ErrorContextDebugMessage { options }
1050 }
1051 wasmparser::CanonicalFunction::ErrorContextDrop => {
1052 let func = self.core_func_signature(core_func_index)?;
1053 core_func_index += 1;
1054 LocalInitializer::ErrorContextDrop { func }
1055 }
1056 wasmparser::CanonicalFunction::ContextGet(i) => {
1057 let func = self.core_func_signature(core_func_index)?;
1058 core_func_index += 1;
1059 LocalInitializer::ContextGet { i, func }
1060 }
1061 wasmparser::CanonicalFunction::ContextSet(i) => {
1062 let func = self.core_func_signature(core_func_index)?;
1063 core_func_index += 1;
1064 LocalInitializer::ContextSet { i, func }
1065 }
1066 };
1067 self.result.initializers.push(init);
1068 }
1069 }
1070
1071 Payload::ModuleSection {
1080 parser,
1081 unchecked_range,
1082 } => {
1083 let index = self.validator.types(0).unwrap().module_count();
1084 self.validator.module_section(&unchecked_range)?;
1085 let static_module_index = self.static_modules.next_key();
1086 let translation = ModuleEnvironment::new(
1087 self.tunables,
1088 self.validator,
1089 self.types.module_types_builder(),
1090 static_module_index,
1091 )
1092 .translate(
1093 parser,
1094 component
1095 .get(unchecked_range.start..unchecked_range.end)
1096 .ok_or_else(|| {
1097 anyhow!(
1098 "section range {}..{} is out of bounds (bound = {})",
1099 unchecked_range.start,
1100 unchecked_range.end,
1101 component.len()
1102 )
1103 .context("wasm component contains an invalid module section")
1104 })?,
1105 )?;
1106 let static_module_index2 = self.static_modules.push(translation);
1107 assert_eq!(static_module_index, static_module_index2);
1108 let types = self.validator.types(0).unwrap();
1109 let ty = types.module_at(index);
1110 self.result
1111 .initializers
1112 .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1113 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1114 }
1115
1116 Payload::ComponentSection {
1125 parser,
1126 unchecked_range,
1127 } => {
1128 self.validator.component_section(&unchecked_range)?;
1129 self.lexical_scopes.push(LexicalScope {
1130 parser: mem::replace(&mut self.parser, parser),
1131 translation: mem::take(&mut self.result),
1132 closure_args: ClosedOverVars::default(),
1133 });
1134 }
1135
1136 Payload::InstanceSection(s) => {
1141 self.validator.instance_section(&s)?;
1142 for instance in s {
1143 let init = match instance? {
1144 wasmparser::Instance::Instantiate { module_index, args } => {
1145 let index = ModuleIndex::from_u32(module_index);
1146 self.instantiate_module(index, &args)
1147 }
1148 wasmparser::Instance::FromExports(exports) => {
1149 self.instantiate_module_from_exports(&exports)
1150 }
1151 };
1152 self.result.initializers.push(init);
1153 }
1154 }
1155 Payload::ComponentInstanceSection(s) => {
1156 let mut index = self.validator.types(0).unwrap().component_instance_count();
1157 self.validator.component_instance_section(&s)?;
1158 for instance in s {
1159 let types = self.validator.types(0).unwrap();
1160 let ty = types.component_instance_at(index);
1161 let init = match instance? {
1162 wasmparser::ComponentInstance::Instantiate {
1163 component_index,
1164 args,
1165 } => {
1166 let index = ComponentIndex::from_u32(component_index);
1167 self.instantiate_component(index, &args, ty)?
1168 }
1169 wasmparser::ComponentInstance::FromExports(exports) => {
1170 self.instantiate_component_from_exports(&exports, ty)?
1171 }
1172 };
1173 self.result.initializers.push(init);
1174 index += 1;
1175 }
1176 }
1177
1178 Payload::ComponentExportSection(s) => {
1184 self.validator.component_export_section(&s)?;
1185 for export in s {
1186 let export = export?;
1187 let item = self.kind_to_item(export.kind, export.index)?;
1188 let prev = self.result.exports.insert(export.name.0, item);
1189 assert!(prev.is_none());
1190 self.result
1191 .initializers
1192 .push(LocalInitializer::Export(item));
1193 }
1194 }
1195
1196 Payload::ComponentStartSection { start, range } => {
1197 self.validator.component_start_section(&start, &range)?;
1198 unimplemented!("component start section");
1199 }
1200
1201 Payload::ComponentAliasSection(s) => {
1205 self.validator.component_alias_section(&s)?;
1206 for alias in s {
1207 let init = match alias? {
1208 wasmparser::ComponentAlias::InstanceExport {
1209 kind: _,
1210 instance_index,
1211 name,
1212 } => {
1213 let instance = ComponentInstanceIndex::from_u32(instance_index);
1214 LocalInitializer::AliasComponentExport(instance, name)
1215 }
1216 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1217 self.alias_component_outer(kind, count, index);
1218 continue;
1219 }
1220 wasmparser::ComponentAlias::CoreInstanceExport {
1221 kind,
1222 instance_index,
1223 name,
1224 } => {
1225 let instance = ModuleInstanceIndex::from_u32(instance_index);
1226 self.alias_module_instance_export(kind, instance, name)
1227 }
1228 };
1229 self.result.initializers.push(init);
1230 }
1231 }
1232
1233 Payload::CustomSection { .. } => {}
1238
1239 other => {
1245 self.validator.payload(&other)?;
1246 panic!("unimplemented section {other:?}");
1247 }
1248 }
1249
1250 Ok(Action::KeepGoing)
1251 }
1252
1253 fn instantiate_module(
1254 &mut self,
1255 module: ModuleIndex,
1256 raw_args: &[wasmparser::InstantiationArg<'data>],
1257 ) -> LocalInitializer<'data> {
1258 let mut args = HashMap::with_capacity(raw_args.len());
1259 for arg in raw_args {
1260 match arg.kind {
1261 wasmparser::InstantiationArgKind::Instance => {
1262 let idx = ModuleInstanceIndex::from_u32(arg.index);
1263 args.insert(arg.name, idx);
1264 }
1265 }
1266 }
1267 LocalInitializer::ModuleInstantiate(module, args)
1268 }
1269
1270 fn instantiate_module_from_exports(
1273 &mut self,
1274 exports: &[wasmparser::Export<'data>],
1275 ) -> LocalInitializer<'data> {
1276 let mut map = HashMap::with_capacity(exports.len());
1277 for export in exports {
1278 let idx = match export.kind {
1279 wasmparser::ExternalKind::Func => {
1280 let index = FuncIndex::from_u32(export.index);
1281 EntityIndex::Function(index)
1282 }
1283 wasmparser::ExternalKind::Table => {
1284 let index = TableIndex::from_u32(export.index);
1285 EntityIndex::Table(index)
1286 }
1287 wasmparser::ExternalKind::Memory => {
1288 let index = MemoryIndex::from_u32(export.index);
1289 EntityIndex::Memory(index)
1290 }
1291 wasmparser::ExternalKind::Global => {
1292 let index = GlobalIndex::from_u32(export.index);
1293 EntityIndex::Global(index)
1294 }
1295 wasmparser::ExternalKind::Tag => {
1296 let index = TagIndex::from_u32(export.index);
1297 EntityIndex::Tag(index)
1298 }
1299 };
1300 map.insert(export.name, idx);
1301 }
1302 LocalInitializer::ModuleSynthetic(map)
1303 }
1304
1305 fn instantiate_component(
1306 &mut self,
1307 component: ComponentIndex,
1308 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1309 ty: ComponentInstanceTypeId,
1310 ) -> Result<LocalInitializer<'data>> {
1311 let mut args = HashMap::with_capacity(raw_args.len());
1312 for arg in raw_args {
1313 let idx = self.kind_to_item(arg.kind, arg.index)?;
1314 args.insert(arg.name, idx);
1315 }
1316
1317 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1318 }
1319
1320 fn instantiate_component_from_exports(
1323 &mut self,
1324 exports: &[wasmparser::ComponentExport<'data>],
1325 ty: ComponentInstanceTypeId,
1326 ) -> Result<LocalInitializer<'data>> {
1327 let mut map = HashMap::with_capacity(exports.len());
1328 for export in exports {
1329 let idx = self.kind_to_item(export.kind, export.index)?;
1330 map.insert(export.name.0, idx);
1331 }
1332
1333 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1334 }
1335
1336 fn kind_to_item(
1337 &mut self,
1338 kind: wasmparser::ComponentExternalKind,
1339 index: u32,
1340 ) -> Result<ComponentItem> {
1341 Ok(match kind {
1342 wasmparser::ComponentExternalKind::Func => {
1343 let index = ComponentFuncIndex::from_u32(index);
1344 ComponentItem::Func(index)
1345 }
1346 wasmparser::ComponentExternalKind::Module => {
1347 let index = ModuleIndex::from_u32(index);
1348 ComponentItem::Module(index)
1349 }
1350 wasmparser::ComponentExternalKind::Instance => {
1351 let index = ComponentInstanceIndex::from_u32(index);
1352 ComponentItem::ComponentInstance(index)
1353 }
1354 wasmparser::ComponentExternalKind::Component => {
1355 let index = ComponentIndex::from_u32(index);
1356 ComponentItem::Component(index)
1357 }
1358 wasmparser::ComponentExternalKind::Value => {
1359 unimplemented!("component values");
1360 }
1361 wasmparser::ComponentExternalKind::Type => {
1362 let types = self.validator.types(0).unwrap();
1363 let ty = types.component_any_type_at(index);
1364 ComponentItem::Type(ty)
1365 }
1366 })
1367 }
1368
1369 fn alias_module_instance_export(
1370 &mut self,
1371 kind: wasmparser::ExternalKind,
1372 instance: ModuleInstanceIndex,
1373 name: &'data str,
1374 ) -> LocalInitializer<'data> {
1375 match kind {
1376 wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1377 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1378 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1379 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1380 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1381 }
1382 }
1383
1384 fn alias_component_outer(
1385 &mut self,
1386 kind: wasmparser::ComponentOuterAliasKind,
1387 count: u32,
1388 index: u32,
1389 ) {
1390 match kind {
1391 wasmparser::ComponentOuterAliasKind::CoreType
1392 | wasmparser::ComponentOuterAliasKind::Type => {}
1393
1394 wasmparser::ComponentOuterAliasKind::CoreModule => {
1401 let index = ModuleIndex::from_u32(index);
1402 let mut module = ClosedOverModule::Local(index);
1403 let depth = self.lexical_scopes.len() - (count as usize);
1404 for frame in self.lexical_scopes[depth..].iter_mut() {
1405 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1406 }
1407
1408 self.result
1413 .initializers
1414 .push(LocalInitializer::AliasModule(module));
1415 }
1416 wasmparser::ComponentOuterAliasKind::Component => {
1417 let index = ComponentIndex::from_u32(index);
1418 let mut component = ClosedOverComponent::Local(index);
1419 let depth = self.lexical_scopes.len() - (count as usize);
1420 for frame in self.lexical_scopes[depth..].iter_mut() {
1421 component =
1422 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1423 }
1424
1425 self.result
1426 .initializers
1427 .push(LocalInitializer::AliasComponent(component));
1428 }
1429 }
1430 }
1431
1432 fn canonical_options(
1433 &mut self,
1434 opts: &[wasmparser::CanonicalOption],
1435 core_func_index: u32,
1436 ) -> WasmResult<LocalCanonicalOptions> {
1437 let core_type = self.core_func_signature(core_func_index)?;
1438
1439 let mut string_encoding = StringEncoding::Utf8;
1440 let mut post_return = None;
1441 let mut async_ = false;
1442 let mut callback = None;
1443 let mut memory = None;
1444 let mut realloc = None;
1445 let mut gc = false;
1446
1447 for opt in opts {
1448 match opt {
1449 wasmparser::CanonicalOption::UTF8 => {
1450 string_encoding = StringEncoding::Utf8;
1451 }
1452 wasmparser::CanonicalOption::UTF16 => {
1453 string_encoding = StringEncoding::Utf16;
1454 }
1455 wasmparser::CanonicalOption::CompactUTF16 => {
1456 string_encoding = StringEncoding::CompactUtf16;
1457 }
1458 wasmparser::CanonicalOption::Memory(idx) => {
1459 let idx = MemoryIndex::from_u32(*idx);
1460 memory = Some(idx);
1461 }
1462 wasmparser::CanonicalOption::Realloc(idx) => {
1463 let idx = FuncIndex::from_u32(*idx);
1464 realloc = Some(idx);
1465 }
1466 wasmparser::CanonicalOption::PostReturn(idx) => {
1467 let idx = FuncIndex::from_u32(*idx);
1468 post_return = Some(idx);
1469 }
1470 wasmparser::CanonicalOption::Async => async_ = true,
1471 wasmparser::CanonicalOption::Callback(idx) => {
1472 let idx = FuncIndex::from_u32(*idx);
1473 callback = Some(idx);
1474 }
1475 wasmparser::CanonicalOption::CoreType(idx) => {
1476 if cfg!(debug_assertions) {
1477 let types = self.validator.types(0).unwrap();
1478 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1479 let interned = self
1480 .types
1481 .module_types_builder()
1482 .intern_type(types, core_ty_id)?;
1483 debug_assert_eq!(interned, core_type);
1484 }
1485 }
1486 wasmparser::CanonicalOption::Gc => {
1487 gc = true;
1488 }
1489 }
1490 }
1491
1492 Ok(LocalCanonicalOptions {
1493 string_encoding,
1494 post_return,
1495 async_,
1496 callback,
1497 core_type,
1498 data_model: if gc {
1499 LocalDataModel::Gc {}
1500 } else {
1501 LocalDataModel::LinearMemory { memory, realloc }
1502 },
1503 })
1504 }
1505
1506 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1508 let types = self.validator.types(0).unwrap();
1509 let id = types.core_function_at(index);
1510 self.types.module_types_builder().intern_type(types, id)
1511 }
1512}
1513
1514impl Translation<'_> {
1515 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1516 self.types.as_ref().unwrap().as_ref()
1517 }
1518}
1519
1520mod pre_inlining {
1532 use super::*;
1533
1534 pub struct PreInliningComponentTypes<'a> {
1535 types: &'a mut ComponentTypesBuilder,
1536 }
1537
1538 impl<'a> PreInliningComponentTypes<'a> {
1539 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1540 Self { types }
1541 }
1542
1543 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1544 self.types.module_types_builder_mut()
1545 }
1546
1547 pub fn types(&self) -> &ComponentTypesBuilder {
1548 self.types
1549 }
1550
1551 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1554 self.types
1555 }
1556 }
1557
1558 impl TypeConvert for PreInliningComponentTypes<'_> {
1559 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1560 self.types.lookup_heap_type(index)
1561 }
1562
1563 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1564 self.types.lookup_type_index(index)
1565 }
1566 }
1567}
1568use pre_inlining::PreInliningComponentTypes;