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 translation = ModuleEnvironment::new(
1086 self.tunables,
1087 self.validator,
1088 self.types.module_types_builder(),
1089 )
1090 .translate(
1091 parser,
1092 component
1093 .get(unchecked_range.start..unchecked_range.end)
1094 .ok_or_else(|| {
1095 anyhow!(
1096 "section range {}..{} is out of bounds (bound = {})",
1097 unchecked_range.start,
1098 unchecked_range.end,
1099 component.len()
1100 )
1101 .context("wasm component contains an invalid module section")
1102 })?,
1103 )?;
1104 let static_idx = self.static_modules.push(translation);
1105 let types = self.validator.types(0).unwrap();
1106 let ty = types.module_at(index);
1107 self.result
1108 .initializers
1109 .push(LocalInitializer::ModuleStatic(static_idx, ty));
1110 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1111 }
1112
1113 Payload::ComponentSection {
1122 parser,
1123 unchecked_range,
1124 } => {
1125 self.validator.component_section(&unchecked_range)?;
1126 self.lexical_scopes.push(LexicalScope {
1127 parser: mem::replace(&mut self.parser, parser),
1128 translation: mem::take(&mut self.result),
1129 closure_args: ClosedOverVars::default(),
1130 });
1131 }
1132
1133 Payload::InstanceSection(s) => {
1138 self.validator.instance_section(&s)?;
1139 for instance in s {
1140 let init = match instance? {
1141 wasmparser::Instance::Instantiate { module_index, args } => {
1142 let index = ModuleIndex::from_u32(module_index);
1143 self.instantiate_module(index, &args)
1144 }
1145 wasmparser::Instance::FromExports(exports) => {
1146 self.instantiate_module_from_exports(&exports)
1147 }
1148 };
1149 self.result.initializers.push(init);
1150 }
1151 }
1152 Payload::ComponentInstanceSection(s) => {
1153 let mut index = self.validator.types(0).unwrap().component_instance_count();
1154 self.validator.component_instance_section(&s)?;
1155 for instance in s {
1156 let types = self.validator.types(0).unwrap();
1157 let ty = types.component_instance_at(index);
1158 let init = match instance? {
1159 wasmparser::ComponentInstance::Instantiate {
1160 component_index,
1161 args,
1162 } => {
1163 let index = ComponentIndex::from_u32(component_index);
1164 self.instantiate_component(index, &args, ty)?
1165 }
1166 wasmparser::ComponentInstance::FromExports(exports) => {
1167 self.instantiate_component_from_exports(&exports, ty)?
1168 }
1169 };
1170 self.result.initializers.push(init);
1171 index += 1;
1172 }
1173 }
1174
1175 Payload::ComponentExportSection(s) => {
1181 self.validator.component_export_section(&s)?;
1182 for export in s {
1183 let export = export?;
1184 let item = self.kind_to_item(export.kind, export.index)?;
1185 let prev = self.result.exports.insert(export.name.0, item);
1186 assert!(prev.is_none());
1187 self.result
1188 .initializers
1189 .push(LocalInitializer::Export(item));
1190 }
1191 }
1192
1193 Payload::ComponentStartSection { start, range } => {
1194 self.validator.component_start_section(&start, &range)?;
1195 unimplemented!("component start section");
1196 }
1197
1198 Payload::ComponentAliasSection(s) => {
1202 self.validator.component_alias_section(&s)?;
1203 for alias in s {
1204 let init = match alias? {
1205 wasmparser::ComponentAlias::InstanceExport {
1206 kind: _,
1207 instance_index,
1208 name,
1209 } => {
1210 let instance = ComponentInstanceIndex::from_u32(instance_index);
1211 LocalInitializer::AliasComponentExport(instance, name)
1212 }
1213 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1214 self.alias_component_outer(kind, count, index);
1215 continue;
1216 }
1217 wasmparser::ComponentAlias::CoreInstanceExport {
1218 kind,
1219 instance_index,
1220 name,
1221 } => {
1222 let instance = ModuleInstanceIndex::from_u32(instance_index);
1223 self.alias_module_instance_export(kind, instance, name)
1224 }
1225 };
1226 self.result.initializers.push(init);
1227 }
1228 }
1229
1230 Payload::CustomSection { .. } => {}
1235
1236 other => {
1242 self.validator.payload(&other)?;
1243 panic!("unimplemented section {other:?}");
1244 }
1245 }
1246
1247 Ok(Action::KeepGoing)
1248 }
1249
1250 fn instantiate_module(
1251 &mut self,
1252 module: ModuleIndex,
1253 raw_args: &[wasmparser::InstantiationArg<'data>],
1254 ) -> LocalInitializer<'data> {
1255 let mut args = HashMap::with_capacity(raw_args.len());
1256 for arg in raw_args {
1257 match arg.kind {
1258 wasmparser::InstantiationArgKind::Instance => {
1259 let idx = ModuleInstanceIndex::from_u32(arg.index);
1260 args.insert(arg.name, idx);
1261 }
1262 }
1263 }
1264 LocalInitializer::ModuleInstantiate(module, args)
1265 }
1266
1267 fn instantiate_module_from_exports(
1270 &mut self,
1271 exports: &[wasmparser::Export<'data>],
1272 ) -> LocalInitializer<'data> {
1273 let mut map = HashMap::with_capacity(exports.len());
1274 for export in exports {
1275 let idx = match export.kind {
1276 wasmparser::ExternalKind::Func => {
1277 let index = FuncIndex::from_u32(export.index);
1278 EntityIndex::Function(index)
1279 }
1280 wasmparser::ExternalKind::Table => {
1281 let index = TableIndex::from_u32(export.index);
1282 EntityIndex::Table(index)
1283 }
1284 wasmparser::ExternalKind::Memory => {
1285 let index = MemoryIndex::from_u32(export.index);
1286 EntityIndex::Memory(index)
1287 }
1288 wasmparser::ExternalKind::Global => {
1289 let index = GlobalIndex::from_u32(export.index);
1290 EntityIndex::Global(index)
1291 }
1292 wasmparser::ExternalKind::Tag => {
1293 let index = TagIndex::from_u32(export.index);
1294 EntityIndex::Tag(index)
1295 }
1296 };
1297 map.insert(export.name, idx);
1298 }
1299 LocalInitializer::ModuleSynthetic(map)
1300 }
1301
1302 fn instantiate_component(
1303 &mut self,
1304 component: ComponentIndex,
1305 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1306 ty: ComponentInstanceTypeId,
1307 ) -> Result<LocalInitializer<'data>> {
1308 let mut args = HashMap::with_capacity(raw_args.len());
1309 for arg in raw_args {
1310 let idx = self.kind_to_item(arg.kind, arg.index)?;
1311 args.insert(arg.name, idx);
1312 }
1313
1314 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1315 }
1316
1317 fn instantiate_component_from_exports(
1320 &mut self,
1321 exports: &[wasmparser::ComponentExport<'data>],
1322 ty: ComponentInstanceTypeId,
1323 ) -> Result<LocalInitializer<'data>> {
1324 let mut map = HashMap::with_capacity(exports.len());
1325 for export in exports {
1326 let idx = self.kind_to_item(export.kind, export.index)?;
1327 map.insert(export.name.0, idx);
1328 }
1329
1330 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1331 }
1332
1333 fn kind_to_item(
1334 &mut self,
1335 kind: wasmparser::ComponentExternalKind,
1336 index: u32,
1337 ) -> Result<ComponentItem> {
1338 Ok(match kind {
1339 wasmparser::ComponentExternalKind::Func => {
1340 let index = ComponentFuncIndex::from_u32(index);
1341 ComponentItem::Func(index)
1342 }
1343 wasmparser::ComponentExternalKind::Module => {
1344 let index = ModuleIndex::from_u32(index);
1345 ComponentItem::Module(index)
1346 }
1347 wasmparser::ComponentExternalKind::Instance => {
1348 let index = ComponentInstanceIndex::from_u32(index);
1349 ComponentItem::ComponentInstance(index)
1350 }
1351 wasmparser::ComponentExternalKind::Component => {
1352 let index = ComponentIndex::from_u32(index);
1353 ComponentItem::Component(index)
1354 }
1355 wasmparser::ComponentExternalKind::Value => {
1356 unimplemented!("component values");
1357 }
1358 wasmparser::ComponentExternalKind::Type => {
1359 let types = self.validator.types(0).unwrap();
1360 let ty = types.component_any_type_at(index);
1361 ComponentItem::Type(ty)
1362 }
1363 })
1364 }
1365
1366 fn alias_module_instance_export(
1367 &mut self,
1368 kind: wasmparser::ExternalKind,
1369 instance: ModuleInstanceIndex,
1370 name: &'data str,
1371 ) -> LocalInitializer<'data> {
1372 match kind {
1373 wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1374 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1375 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1376 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1377 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1378 }
1379 }
1380
1381 fn alias_component_outer(
1382 &mut self,
1383 kind: wasmparser::ComponentOuterAliasKind,
1384 count: u32,
1385 index: u32,
1386 ) {
1387 match kind {
1388 wasmparser::ComponentOuterAliasKind::CoreType
1389 | wasmparser::ComponentOuterAliasKind::Type => {}
1390
1391 wasmparser::ComponentOuterAliasKind::CoreModule => {
1398 let index = ModuleIndex::from_u32(index);
1399 let mut module = ClosedOverModule::Local(index);
1400 let depth = self.lexical_scopes.len() - (count as usize);
1401 for frame in self.lexical_scopes[depth..].iter_mut() {
1402 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1403 }
1404
1405 self.result
1410 .initializers
1411 .push(LocalInitializer::AliasModule(module));
1412 }
1413 wasmparser::ComponentOuterAliasKind::Component => {
1414 let index = ComponentIndex::from_u32(index);
1415 let mut component = ClosedOverComponent::Local(index);
1416 let depth = self.lexical_scopes.len() - (count as usize);
1417 for frame in self.lexical_scopes[depth..].iter_mut() {
1418 component =
1419 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1420 }
1421
1422 self.result
1423 .initializers
1424 .push(LocalInitializer::AliasComponent(component));
1425 }
1426 }
1427 }
1428
1429 fn canonical_options(
1430 &mut self,
1431 opts: &[wasmparser::CanonicalOption],
1432 core_func_index: u32,
1433 ) -> WasmResult<LocalCanonicalOptions> {
1434 let core_type = self.core_func_signature(core_func_index)?;
1435
1436 let mut string_encoding = StringEncoding::Utf8;
1437 let mut post_return = None;
1438 let mut async_ = false;
1439 let mut callback = None;
1440 let mut memory = None;
1441 let mut realloc = None;
1442 let mut gc = false;
1443
1444 for opt in opts {
1445 match opt {
1446 wasmparser::CanonicalOption::UTF8 => {
1447 string_encoding = StringEncoding::Utf8;
1448 }
1449 wasmparser::CanonicalOption::UTF16 => {
1450 string_encoding = StringEncoding::Utf16;
1451 }
1452 wasmparser::CanonicalOption::CompactUTF16 => {
1453 string_encoding = StringEncoding::CompactUtf16;
1454 }
1455 wasmparser::CanonicalOption::Memory(idx) => {
1456 let idx = MemoryIndex::from_u32(*idx);
1457 memory = Some(idx);
1458 }
1459 wasmparser::CanonicalOption::Realloc(idx) => {
1460 let idx = FuncIndex::from_u32(*idx);
1461 realloc = Some(idx);
1462 }
1463 wasmparser::CanonicalOption::PostReturn(idx) => {
1464 let idx = FuncIndex::from_u32(*idx);
1465 post_return = Some(idx);
1466 }
1467 wasmparser::CanonicalOption::Async => async_ = true,
1468 wasmparser::CanonicalOption::Callback(idx) => {
1469 let idx = FuncIndex::from_u32(*idx);
1470 callback = Some(idx);
1471 }
1472 wasmparser::CanonicalOption::CoreType(idx) => {
1473 if cfg!(debug_assertions) {
1474 let types = self.validator.types(0).unwrap();
1475 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1476 let interned = self
1477 .types
1478 .module_types_builder()
1479 .intern_type(types, core_ty_id)?;
1480 debug_assert_eq!(interned, core_type);
1481 }
1482 }
1483 wasmparser::CanonicalOption::Gc => {
1484 gc = true;
1485 }
1486 }
1487 }
1488
1489 Ok(LocalCanonicalOptions {
1490 string_encoding,
1491 post_return,
1492 async_,
1493 callback,
1494 core_type,
1495 data_model: if gc {
1496 LocalDataModel::Gc {}
1497 } else {
1498 LocalDataModel::LinearMemory { memory, realloc }
1499 },
1500 })
1501 }
1502
1503 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1505 let types = self.validator.types(0).unwrap();
1506 let id = types.core_function_at(index);
1507 self.types.module_types_builder().intern_type(types, id)
1508 }
1509}
1510
1511impl Translation<'_> {
1512 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1513 self.types.as_ref().unwrap().as_ref()
1514 }
1515}
1516
1517mod pre_inlining {
1529 use super::*;
1530
1531 pub struct PreInliningComponentTypes<'a> {
1532 types: &'a mut ComponentTypesBuilder,
1533 }
1534
1535 impl<'a> PreInliningComponentTypes<'a> {
1536 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1537 Self { types }
1538 }
1539
1540 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1541 self.types.module_types_builder_mut()
1542 }
1543
1544 pub fn types(&self) -> &ComponentTypesBuilder {
1545 self.types
1546 }
1547
1548 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1551 self.types
1552 }
1553 }
1554
1555 impl TypeConvert for PreInliningComponentTypes<'_> {
1556 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1557 self.types.lookup_heap_type(index)
1558 }
1559
1560 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1561 self.types.lookup_type_index(index)
1562 }
1563 }
1564}
1565use pre_inlining::PreInliningComponentTypes;