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 func: ModuleInternedTypeIndex,
208 async_: bool,
209 memory: MemoryIndex,
210 },
211 WaitableSetPoll {
212 func: ModuleInternedTypeIndex,
213 async_: bool,
214 memory: MemoryIndex,
215 },
216 WaitableSetDrop {
217 func: ModuleInternedTypeIndex,
218 },
219 WaitableJoin {
220 func: ModuleInternedTypeIndex,
221 },
222 Yield {
223 func: ModuleInternedTypeIndex,
224 async_: bool,
225 },
226 SubtaskDrop {
227 func: ModuleInternedTypeIndex,
228 },
229 SubtaskCancel {
230 func: ModuleInternedTypeIndex,
231 async_: bool,
232 },
233 StreamNew {
234 ty: ComponentDefinedTypeId,
235 func: ModuleInternedTypeIndex,
236 },
237 StreamRead {
238 ty: ComponentDefinedTypeId,
239 options: LocalCanonicalOptions,
240 },
241 StreamWrite {
242 ty: ComponentDefinedTypeId,
243 options: LocalCanonicalOptions,
244 },
245 StreamCancelRead {
246 ty: ComponentDefinedTypeId,
247 func: ModuleInternedTypeIndex,
248 async_: bool,
249 },
250 StreamCancelWrite {
251 ty: ComponentDefinedTypeId,
252 func: ModuleInternedTypeIndex,
253 async_: bool,
254 },
255 StreamDropReadable {
256 ty: ComponentDefinedTypeId,
257 func: ModuleInternedTypeIndex,
258 },
259 StreamDropWritable {
260 ty: ComponentDefinedTypeId,
261 func: ModuleInternedTypeIndex,
262 },
263 FutureNew {
264 ty: ComponentDefinedTypeId,
265 func: ModuleInternedTypeIndex,
266 },
267 FutureRead {
268 ty: ComponentDefinedTypeId,
269 options: LocalCanonicalOptions,
270 },
271 FutureWrite {
272 ty: ComponentDefinedTypeId,
273 options: LocalCanonicalOptions,
274 },
275 FutureCancelRead {
276 ty: ComponentDefinedTypeId,
277 func: ModuleInternedTypeIndex,
278 async_: bool,
279 },
280 FutureCancelWrite {
281 ty: ComponentDefinedTypeId,
282 func: ModuleInternedTypeIndex,
283 async_: bool,
284 },
285 FutureDropReadable {
286 ty: ComponentDefinedTypeId,
287 func: ModuleInternedTypeIndex,
288 },
289 FutureDropWritable {
290 ty: ComponentDefinedTypeId,
291 func: ModuleInternedTypeIndex,
292 },
293 ErrorContextNew {
294 options: LocalCanonicalOptions,
295 },
296 ErrorContextDebugMessage {
297 options: LocalCanonicalOptions,
298 },
299 ErrorContextDrop {
300 func: ModuleInternedTypeIndex,
301 },
302 ContextGet {
303 func: ModuleInternedTypeIndex,
304 i: u32,
305 },
306 ContextSet {
307 func: ModuleInternedTypeIndex,
308 i: u32,
309 },
310
311 ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
313
314 ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
316 ModuleSynthetic(HashMap<&'data str, EntityIndex>),
317
318 ComponentStatic(StaticComponentIndex, ClosedOverVars),
320
321 ComponentInstantiate(
323 ComponentIndex,
324 HashMap<&'data str, ComponentItem>,
325 ComponentInstanceTypeId,
326 ),
327 ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
328
329 AliasExportFunc(ModuleInstanceIndex, &'data str),
331 AliasExportTable(ModuleInstanceIndex, &'data str),
332 AliasExportGlobal(ModuleInstanceIndex, &'data str),
333 AliasExportMemory(ModuleInstanceIndex, &'data str),
334 AliasExportTag(ModuleInstanceIndex, &'data str),
335 AliasComponentExport(ComponentInstanceIndex, &'data str),
336 AliasModule(ClosedOverModule),
337 AliasComponent(ClosedOverComponent),
338
339 Export(ComponentItem),
341}
342
343#[derive(Default)]
347struct ClosedOverVars {
348 components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
349 modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
350}
351
352enum ClosedOverComponent {
357 Local(ComponentIndex),
360 Upvar(ComponentUpvarIndex),
365}
366
367enum ClosedOverModule {
369 Local(ModuleIndex),
370 Upvar(ModuleUpvarIndex),
371}
372
373#[derive(Debug, Clone, Hash, Eq, PartialEq)]
375pub enum LocalDataModel {
376 Gc {},
378
379 LinearMemory {
381 memory: Option<MemoryIndex>,
383 realloc: Option<FuncIndex>,
385 },
386}
387
388struct LocalCanonicalOptions {
390 string_encoding: StringEncoding,
391 post_return: Option<FuncIndex>,
392 async_: bool,
393 callback: Option<FuncIndex>,
394 core_type: ModuleInternedTypeIndex,
396 data_model: LocalDataModel,
397}
398
399enum Action {
400 KeepGoing,
401 Skip(usize),
402 Done,
403}
404
405impl<'a, 'data> Translator<'a, 'data> {
406 pub fn new(
408 tunables: &'a Tunables,
409 validator: &'a mut Validator,
410 types: &'a mut ComponentTypesBuilder,
411 scope_vec: &'data ScopeVec<u8>,
412 ) -> Self {
413 let mut parser = Parser::new(0);
414 parser.set_features(*validator.features());
415 Self {
416 result: Translation::default(),
417 tunables,
418 validator,
419 types: PreInliningComponentTypes::new(types),
420 parser,
421 lexical_scopes: Vec::new(),
422 static_components: Default::default(),
423 static_modules: Default::default(),
424 scope_vec,
425 }
426 }
427
428 pub fn translate(
452 mut self,
453 component: &'data [u8],
454 ) -> Result<(
455 ComponentTranslation,
456 PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
457 )> {
458 let mut remaining = component;
464 loop {
465 let payload = match self.parser.parse(remaining, true)? {
466 Chunk::Parsed { payload, consumed } => {
467 remaining = &remaining[consumed..];
468 payload
469 }
470 Chunk::NeedMoreData(_) => unreachable!(),
471 };
472
473 match self.translate_payload(payload, component)? {
474 Action::KeepGoing => {}
475 Action::Skip(n) => remaining = &remaining[n..],
476 Action::Done => break,
477 }
478 }
479 assert!(remaining.is_empty());
480 assert!(self.lexical_scopes.is_empty());
481
482 let mut component = inline::run(
493 self.types.types_mut_for_inlining(),
494 &self.result,
495 &self.static_modules,
496 &self.static_components,
497 )?;
498
499 self.partition_adapter_modules(&mut component);
500
501 let translation =
502 component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
503
504 self.analyze_function_imports(&translation);
505
506 Ok((translation, self.static_modules))
507 }
508
509 fn analyze_function_imports(&mut self, translation: &ComponentTranslation) {
510 let mut instantiations = SecondaryMap::<StaticModuleIndex, AbstractInstantiations>::new();
513 let mut instance_to_module =
514 PrimaryMap::<RuntimeInstanceIndex, PackedOption<StaticModuleIndex>>::new();
515 for init in &translation.component.initializers {
516 match init {
517 GlobalInitializer::InstantiateModule(instantiation) => match instantiation {
518 InstantiateModule::Static(module, args) => {
519 instantiations[*module].join(AbstractInstantiations::One(&*args));
520 instance_to_module.push(Some(*module).into());
521 }
522 _ => {
523 instance_to_module.push(None.into());
524 }
525 },
526 _ => continue,
527 }
528 }
529
530 for item in translation.component.export_items.values() {
533 if let Export::ModuleStatic { index, .. } = item {
534 instantiations[*index].join(AbstractInstantiations::Many)
535 }
536 }
537
538 for (module, instantiations) in instantiations.iter() {
543 let args = match instantiations {
544 dfg::AbstractInstantiations::Many | dfg::AbstractInstantiations::None => continue,
545 dfg::AbstractInstantiations::One(args) => args,
546 };
547
548 let mut imported_func_counter = 0_u32;
549 for (i, arg) in args.iter().enumerate() {
550 let (_, _, crate::types::EntityType::Function(_)) =
552 self.static_modules[module].module.import(i).unwrap()
553 else {
554 continue;
555 };
556
557 let imported_func = FuncIndex::from_u32(imported_func_counter);
558 imported_func_counter += 1;
559 debug_assert!(
560 self.static_modules[module]
561 .module
562 .defined_func_index(imported_func)
563 .is_none()
564 );
565
566 match arg {
567 CoreDef::InstanceFlags(_) => unreachable!("instance flags are not a function"),
568
569 CoreDef::Trampoline(_) => continue,
582
583 CoreDef::Export(export) => {
587 let Some(arg_module) = &instance_to_module[export.instance].expand() else {
588 continue;
593 };
594
595 let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
596 else {
597 unreachable!("function imports must be functions")
598 };
599
600 let Some(arg_module_def_func) = self.static_modules[*arg_module]
601 .module
602 .defined_func_index(*arg_func)
603 else {
604 continue;
611 };
612
613 assert!(
614 self.static_modules[module].known_imported_functions[imported_func]
615 .is_none()
616 );
617 self.static_modules[module].known_imported_functions[imported_func] =
618 Some((*arg_module, arg_module_def_func));
619 }
620 }
621 }
622 }
623 }
624
625 fn translate_payload(
626 &mut self,
627 payload: Payload<'data>,
628 component: &'data [u8],
629 ) -> Result<Action> {
630 match payload {
631 Payload::Version {
632 num,
633 encoding,
634 range,
635 } => {
636 self.validator.version(num, encoding, &range)?;
637
638 match encoding {
639 Encoding::Component => {}
640 Encoding::Module => {
641 bail!("attempted to parse a wasm module with a component parser");
642 }
643 }
644 }
645
646 Payload::End(offset) => {
647 assert!(self.result.types.is_none());
648 self.result.types = Some(self.validator.end(offset)?);
649
650 let LexicalScope {
655 parser,
656 translation,
657 closure_args,
658 } = match self.lexical_scopes.pop() {
659 Some(frame) => frame,
660 None => return Ok(Action::Done),
661 };
662 self.parser = parser;
663 let component = mem::replace(&mut self.result, translation);
664 let static_idx = self.static_components.push(component);
665 self.result
666 .initializers
667 .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
668 }
669
670 Payload::ComponentTypeSection(s) => {
679 let mut component_type_index =
680 self.validator.types(0).unwrap().component_type_count();
681 self.validator.component_type_section(&s)?;
682
683 let types = self.validator.types(0).unwrap();
687 for ty in s {
688 match ty? {
689 wasmparser::ComponentType::Resource { rep, dtor } => {
690 let rep = self.types.convert_valtype(rep)?;
691 let id = types
692 .component_any_type_at(component_type_index)
693 .unwrap_resource();
694 let dtor = dtor.map(FuncIndex::from_u32);
695 self.result
696 .initializers
697 .push(LocalInitializer::Resource(id, rep, dtor));
698 }
699
700 wasmparser::ComponentType::Defined(_)
702 | wasmparser::ComponentType::Func(_)
703 | wasmparser::ComponentType::Instance(_)
704 | wasmparser::ComponentType::Component(_) => {}
705 }
706
707 component_type_index += 1;
708 }
709 }
710 Payload::CoreTypeSection(s) => {
711 self.validator.core_type_section(&s)?;
712 }
713
714 Payload::ComponentImportSection(s) => {
718 self.validator.component_import_section(&s)?;
719 for import in s {
720 let import = import?;
721 let types = self.validator.types(0).unwrap();
722 let ty = types
723 .component_entity_type_of_import(import.name.0)
724 .unwrap();
725 self.result
726 .initializers
727 .push(LocalInitializer::Import(import.name, ty));
728 }
729 }
730
731 Payload::ComponentCanonicalSection(s) => {
734 let types = self.validator.types(0).unwrap();
735 let mut core_func_index = types.function_count();
736 self.validator.component_canonical_section(&s)?;
737 for func in s {
738 let init = match func? {
739 wasmparser::CanonicalFunction::Lift {
740 type_index,
741 core_func_index,
742 options,
743 } => {
744 let ty = self
745 .validator
746 .types(0)
747 .unwrap()
748 .component_any_type_at(type_index)
749 .unwrap_func();
750
751 let func = FuncIndex::from_u32(core_func_index);
752 let options = self.canonical_options(&options, core_func_index)?;
753 LocalInitializer::Lift(ty, func, options)
754 }
755 wasmparser::CanonicalFunction::Lower {
756 func_index,
757 options,
758 } => {
759 let lower_ty = self
760 .validator
761 .types(0)
762 .unwrap()
763 .component_function_at(func_index);
764 let func = ComponentFuncIndex::from_u32(func_index);
765 let options = self.canonical_options(&options, core_func_index)?;
766 core_func_index += 1;
767 LocalInitializer::Lower {
768 func,
769 options,
770 lower_ty,
771 }
772 }
773 wasmparser::CanonicalFunction::ResourceNew { resource } => {
774 let resource = self
775 .validator
776 .types(0)
777 .unwrap()
778 .component_any_type_at(resource)
779 .unwrap_resource();
780 let ty = self.core_func_signature(core_func_index)?;
781 core_func_index += 1;
782 LocalInitializer::ResourceNew(resource, ty)
783 }
784 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
785 let resource = self
786 .validator
787 .types(0)
788 .unwrap()
789 .component_any_type_at(resource)
790 .unwrap_resource();
791 let ty = self.core_func_signature(core_func_index)?;
792 core_func_index += 1;
793 LocalInitializer::ResourceDrop(resource, ty)
794 }
795 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
796 let _ = resource;
797 bail!("support for `resource.drop async` not implemented yet")
798 }
799 wasmparser::CanonicalFunction::ResourceRep { resource } => {
800 let resource = self
801 .validator
802 .types(0)
803 .unwrap()
804 .component_any_type_at(resource)
805 .unwrap_resource();
806 let ty = self.core_func_signature(core_func_index)?;
807 core_func_index += 1;
808 LocalInitializer::ResourceRep(resource, ty)
809 }
810 wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
811 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
812 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
813 bail!("unsupported intrinsic")
814 }
815 wasmparser::CanonicalFunction::BackpressureSet => {
816 let core_type = self.core_func_signature(core_func_index)?;
817 core_func_index += 1;
818 LocalInitializer::BackpressureSet { func: core_type }
819 }
820 wasmparser::CanonicalFunction::TaskReturn { result, options } => {
821 let result = result.map(|ty| match ty {
822 wasmparser::ComponentValType::Primitive(ty) => {
823 ComponentValType::Primitive(ty)
824 }
825 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
826 self.validator
827 .types(0)
828 .unwrap()
829 .component_defined_type_at(ty),
830 ),
831 });
832 let options = self.canonical_options(&options, core_func_index)?;
833 core_func_index += 1;
834 LocalInitializer::TaskReturn { result, options }
835 }
836 wasmparser::CanonicalFunction::TaskCancel => {
837 let func = self.core_func_signature(core_func_index)?;
838 core_func_index += 1;
839 LocalInitializer::TaskCancel { func }
840 }
841 wasmparser::CanonicalFunction::WaitableSetNew => {
842 let func = self.core_func_signature(core_func_index)?;
843 core_func_index += 1;
844 LocalInitializer::WaitableSetNew { func }
845 }
846 wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
847 let func = self.core_func_signature(core_func_index)?;
848 core_func_index += 1;
849 LocalInitializer::WaitableSetWait {
850 func,
851 async_,
852 memory: MemoryIndex::from_u32(memory),
853 }
854 }
855 wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
856 let func = self.core_func_signature(core_func_index)?;
857 core_func_index += 1;
858 LocalInitializer::WaitableSetPoll {
859 func,
860 async_,
861 memory: MemoryIndex::from_u32(memory),
862 }
863 }
864 wasmparser::CanonicalFunction::WaitableSetDrop => {
865 let func = self.core_func_signature(core_func_index)?;
866 core_func_index += 1;
867 LocalInitializer::WaitableSetDrop { func }
868 }
869 wasmparser::CanonicalFunction::WaitableJoin => {
870 let func = self.core_func_signature(core_func_index)?;
871 core_func_index += 1;
872 LocalInitializer::WaitableJoin { func }
873 }
874 wasmparser::CanonicalFunction::Yield { async_ } => {
875 let func = self.core_func_signature(core_func_index)?;
876 core_func_index += 1;
877 LocalInitializer::Yield { func, async_ }
878 }
879 wasmparser::CanonicalFunction::SubtaskDrop => {
880 let func = self.core_func_signature(core_func_index)?;
881 core_func_index += 1;
882 LocalInitializer::SubtaskDrop { func }
883 }
884 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
885 let func = self.core_func_signature(core_func_index)?;
886 core_func_index += 1;
887 LocalInitializer::SubtaskCancel { func, async_ }
888 }
889 wasmparser::CanonicalFunction::StreamNew { ty } => {
890 let ty = self
891 .validator
892 .types(0)
893 .unwrap()
894 .component_defined_type_at(ty);
895 let func = self.core_func_signature(core_func_index)?;
896 core_func_index += 1;
897 LocalInitializer::StreamNew { ty, func }
898 }
899 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
900 let ty = self
901 .validator
902 .types(0)
903 .unwrap()
904 .component_defined_type_at(ty);
905 let options = self.canonical_options(&options, core_func_index)?;
906 core_func_index += 1;
907 LocalInitializer::StreamRead { ty, options }
908 }
909 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
910 let ty = self
911 .validator
912 .types(0)
913 .unwrap()
914 .component_defined_type_at(ty);
915 let options = self.canonical_options(&options, core_func_index)?;
916 core_func_index += 1;
917 LocalInitializer::StreamWrite { ty, options }
918 }
919 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
920 let ty = self
921 .validator
922 .types(0)
923 .unwrap()
924 .component_defined_type_at(ty);
925 let func = self.core_func_signature(core_func_index)?;
926 core_func_index += 1;
927 LocalInitializer::StreamCancelRead { ty, func, async_ }
928 }
929 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
930 let ty = self
931 .validator
932 .types(0)
933 .unwrap()
934 .component_defined_type_at(ty);
935 let func = self.core_func_signature(core_func_index)?;
936 core_func_index += 1;
937 LocalInitializer::StreamCancelWrite { ty, func, async_ }
938 }
939 wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
940 let ty = self
941 .validator
942 .types(0)
943 .unwrap()
944 .component_defined_type_at(ty);
945 let func = self.core_func_signature(core_func_index)?;
946 core_func_index += 1;
947 LocalInitializer::StreamDropReadable { ty, func }
948 }
949 wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
950 let ty = self
951 .validator
952 .types(0)
953 .unwrap()
954 .component_defined_type_at(ty);
955 let func = self.core_func_signature(core_func_index)?;
956 core_func_index += 1;
957 LocalInitializer::StreamDropWritable { ty, func }
958 }
959 wasmparser::CanonicalFunction::FutureNew { ty } => {
960 let ty = self
961 .validator
962 .types(0)
963 .unwrap()
964 .component_defined_type_at(ty);
965 let func = self.core_func_signature(core_func_index)?;
966 core_func_index += 1;
967 LocalInitializer::FutureNew { ty, func }
968 }
969 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
970 let ty = self
971 .validator
972 .types(0)
973 .unwrap()
974 .component_defined_type_at(ty);
975 let options = self.canonical_options(&options, core_func_index)?;
976 core_func_index += 1;
977 LocalInitializer::FutureRead { ty, options }
978 }
979 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
980 let ty = self
981 .validator
982 .types(0)
983 .unwrap()
984 .component_defined_type_at(ty);
985 let options = self.canonical_options(&options, core_func_index)?;
986 core_func_index += 1;
987 LocalInitializer::FutureWrite { ty, options }
988 }
989 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
990 let ty = self
991 .validator
992 .types(0)
993 .unwrap()
994 .component_defined_type_at(ty);
995 let func = self.core_func_signature(core_func_index)?;
996 core_func_index += 1;
997 LocalInitializer::FutureCancelRead { ty, func, async_ }
998 }
999 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1000 let ty = self
1001 .validator
1002 .types(0)
1003 .unwrap()
1004 .component_defined_type_at(ty);
1005 let func = self.core_func_signature(core_func_index)?;
1006 core_func_index += 1;
1007 LocalInitializer::FutureCancelWrite { ty, func, async_ }
1008 }
1009 wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1010 let ty = self
1011 .validator
1012 .types(0)
1013 .unwrap()
1014 .component_defined_type_at(ty);
1015 let func = self.core_func_signature(core_func_index)?;
1016 core_func_index += 1;
1017 LocalInitializer::FutureDropReadable { ty, func }
1018 }
1019 wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1020 let ty = self
1021 .validator
1022 .types(0)
1023 .unwrap()
1024 .component_defined_type_at(ty);
1025 let func = self.core_func_signature(core_func_index)?;
1026 core_func_index += 1;
1027 LocalInitializer::FutureDropWritable { ty, func }
1028 }
1029 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1030 let options = self.canonical_options(&options, core_func_index)?;
1031 core_func_index += 1;
1032 LocalInitializer::ErrorContextNew { options }
1033 }
1034 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1035 let options = self.canonical_options(&options, core_func_index)?;
1036 core_func_index += 1;
1037 LocalInitializer::ErrorContextDebugMessage { options }
1038 }
1039 wasmparser::CanonicalFunction::ErrorContextDrop => {
1040 let func = self.core_func_signature(core_func_index)?;
1041 core_func_index += 1;
1042 LocalInitializer::ErrorContextDrop { func }
1043 }
1044 wasmparser::CanonicalFunction::ContextGet(i) => {
1045 let func = self.core_func_signature(core_func_index)?;
1046 core_func_index += 1;
1047 LocalInitializer::ContextGet { i, func }
1048 }
1049 wasmparser::CanonicalFunction::ContextSet(i) => {
1050 let func = self.core_func_signature(core_func_index)?;
1051 core_func_index += 1;
1052 LocalInitializer::ContextSet { i, func }
1053 }
1054 };
1055 self.result.initializers.push(init);
1056 }
1057 }
1058
1059 Payload::ModuleSection {
1068 parser,
1069 unchecked_range,
1070 } => {
1071 let index = self.validator.types(0).unwrap().module_count();
1072 self.validator.module_section(&unchecked_range)?;
1073 let translation = ModuleEnvironment::new(
1074 self.tunables,
1075 self.validator,
1076 self.types.module_types_builder(),
1077 )
1078 .translate(
1079 parser,
1080 component
1081 .get(unchecked_range.start..unchecked_range.end)
1082 .ok_or_else(|| {
1083 anyhow!(
1084 "section range {}..{} is out of bounds (bound = {})",
1085 unchecked_range.start,
1086 unchecked_range.end,
1087 component.len()
1088 )
1089 .context("wasm component contains an invalid module section")
1090 })?,
1091 )?;
1092 let static_idx = self.static_modules.push(translation);
1093 let types = self.validator.types(0).unwrap();
1094 let ty = types.module_at(index);
1095 self.result
1096 .initializers
1097 .push(LocalInitializer::ModuleStatic(static_idx, ty));
1098 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1099 }
1100
1101 Payload::ComponentSection {
1110 parser,
1111 unchecked_range,
1112 } => {
1113 self.validator.component_section(&unchecked_range)?;
1114 self.lexical_scopes.push(LexicalScope {
1115 parser: mem::replace(&mut self.parser, parser),
1116 translation: mem::take(&mut self.result),
1117 closure_args: ClosedOverVars::default(),
1118 });
1119 }
1120
1121 Payload::InstanceSection(s) => {
1126 self.validator.instance_section(&s)?;
1127 for instance in s {
1128 let init = match instance? {
1129 wasmparser::Instance::Instantiate { module_index, args } => {
1130 let index = ModuleIndex::from_u32(module_index);
1131 self.instantiate_module(index, &args)
1132 }
1133 wasmparser::Instance::FromExports(exports) => {
1134 self.instantiate_module_from_exports(&exports)
1135 }
1136 };
1137 self.result.initializers.push(init);
1138 }
1139 }
1140 Payload::ComponentInstanceSection(s) => {
1141 let mut index = self.validator.types(0).unwrap().component_instance_count();
1142 self.validator.component_instance_section(&s)?;
1143 for instance in s {
1144 let types = self.validator.types(0).unwrap();
1145 let ty = types.component_instance_at(index);
1146 let init = match instance? {
1147 wasmparser::ComponentInstance::Instantiate {
1148 component_index,
1149 args,
1150 } => {
1151 let index = ComponentIndex::from_u32(component_index);
1152 self.instantiate_component(index, &args, ty)?
1153 }
1154 wasmparser::ComponentInstance::FromExports(exports) => {
1155 self.instantiate_component_from_exports(&exports, ty)?
1156 }
1157 };
1158 self.result.initializers.push(init);
1159 index += 1;
1160 }
1161 }
1162
1163 Payload::ComponentExportSection(s) => {
1169 self.validator.component_export_section(&s)?;
1170 for export in s {
1171 let export = export?;
1172 let item = self.kind_to_item(export.kind, export.index)?;
1173 let prev = self.result.exports.insert(export.name.0, item);
1174 assert!(prev.is_none());
1175 self.result
1176 .initializers
1177 .push(LocalInitializer::Export(item));
1178 }
1179 }
1180
1181 Payload::ComponentStartSection { start, range } => {
1182 self.validator.component_start_section(&start, &range)?;
1183 unimplemented!("component start section");
1184 }
1185
1186 Payload::ComponentAliasSection(s) => {
1190 self.validator.component_alias_section(&s)?;
1191 for alias in s {
1192 let init = match alias? {
1193 wasmparser::ComponentAlias::InstanceExport {
1194 kind: _,
1195 instance_index,
1196 name,
1197 } => {
1198 let instance = ComponentInstanceIndex::from_u32(instance_index);
1199 LocalInitializer::AliasComponentExport(instance, name)
1200 }
1201 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1202 self.alias_component_outer(kind, count, index);
1203 continue;
1204 }
1205 wasmparser::ComponentAlias::CoreInstanceExport {
1206 kind,
1207 instance_index,
1208 name,
1209 } => {
1210 let instance = ModuleInstanceIndex::from_u32(instance_index);
1211 self.alias_module_instance_export(kind, instance, name)
1212 }
1213 };
1214 self.result.initializers.push(init);
1215 }
1216 }
1217
1218 Payload::CustomSection { .. } => {}
1223
1224 other => {
1230 self.validator.payload(&other)?;
1231 panic!("unimplemented section {other:?}");
1232 }
1233 }
1234
1235 Ok(Action::KeepGoing)
1236 }
1237
1238 fn instantiate_module(
1239 &mut self,
1240 module: ModuleIndex,
1241 raw_args: &[wasmparser::InstantiationArg<'data>],
1242 ) -> LocalInitializer<'data> {
1243 let mut args = HashMap::with_capacity(raw_args.len());
1244 for arg in raw_args {
1245 match arg.kind {
1246 wasmparser::InstantiationArgKind::Instance => {
1247 let idx = ModuleInstanceIndex::from_u32(arg.index);
1248 args.insert(arg.name, idx);
1249 }
1250 }
1251 }
1252 LocalInitializer::ModuleInstantiate(module, args)
1253 }
1254
1255 fn instantiate_module_from_exports(
1258 &mut self,
1259 exports: &[wasmparser::Export<'data>],
1260 ) -> LocalInitializer<'data> {
1261 let mut map = HashMap::with_capacity(exports.len());
1262 for export in exports {
1263 let idx = match export.kind {
1264 wasmparser::ExternalKind::Func => {
1265 let index = FuncIndex::from_u32(export.index);
1266 EntityIndex::Function(index)
1267 }
1268 wasmparser::ExternalKind::Table => {
1269 let index = TableIndex::from_u32(export.index);
1270 EntityIndex::Table(index)
1271 }
1272 wasmparser::ExternalKind::Memory => {
1273 let index = MemoryIndex::from_u32(export.index);
1274 EntityIndex::Memory(index)
1275 }
1276 wasmparser::ExternalKind::Global => {
1277 let index = GlobalIndex::from_u32(export.index);
1278 EntityIndex::Global(index)
1279 }
1280 wasmparser::ExternalKind::Tag => {
1281 let index = TagIndex::from_u32(export.index);
1282 EntityIndex::Tag(index)
1283 }
1284 };
1285 map.insert(export.name, idx);
1286 }
1287 LocalInitializer::ModuleSynthetic(map)
1288 }
1289
1290 fn instantiate_component(
1291 &mut self,
1292 component: ComponentIndex,
1293 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1294 ty: ComponentInstanceTypeId,
1295 ) -> Result<LocalInitializer<'data>> {
1296 let mut args = HashMap::with_capacity(raw_args.len());
1297 for arg in raw_args {
1298 let idx = self.kind_to_item(arg.kind, arg.index)?;
1299 args.insert(arg.name, idx);
1300 }
1301
1302 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1303 }
1304
1305 fn instantiate_component_from_exports(
1308 &mut self,
1309 exports: &[wasmparser::ComponentExport<'data>],
1310 ty: ComponentInstanceTypeId,
1311 ) -> Result<LocalInitializer<'data>> {
1312 let mut map = HashMap::with_capacity(exports.len());
1313 for export in exports {
1314 let idx = self.kind_to_item(export.kind, export.index)?;
1315 map.insert(export.name.0, idx);
1316 }
1317
1318 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1319 }
1320
1321 fn kind_to_item(
1322 &mut self,
1323 kind: wasmparser::ComponentExternalKind,
1324 index: u32,
1325 ) -> Result<ComponentItem> {
1326 Ok(match kind {
1327 wasmparser::ComponentExternalKind::Func => {
1328 let index = ComponentFuncIndex::from_u32(index);
1329 ComponentItem::Func(index)
1330 }
1331 wasmparser::ComponentExternalKind::Module => {
1332 let index = ModuleIndex::from_u32(index);
1333 ComponentItem::Module(index)
1334 }
1335 wasmparser::ComponentExternalKind::Instance => {
1336 let index = ComponentInstanceIndex::from_u32(index);
1337 ComponentItem::ComponentInstance(index)
1338 }
1339 wasmparser::ComponentExternalKind::Component => {
1340 let index = ComponentIndex::from_u32(index);
1341 ComponentItem::Component(index)
1342 }
1343 wasmparser::ComponentExternalKind::Value => {
1344 unimplemented!("component values");
1345 }
1346 wasmparser::ComponentExternalKind::Type => {
1347 let types = self.validator.types(0).unwrap();
1348 let ty = types.component_any_type_at(index);
1349 ComponentItem::Type(ty)
1350 }
1351 })
1352 }
1353
1354 fn alias_module_instance_export(
1355 &mut self,
1356 kind: wasmparser::ExternalKind,
1357 instance: ModuleInstanceIndex,
1358 name: &'data str,
1359 ) -> LocalInitializer<'data> {
1360 match kind {
1361 wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1362 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1363 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1364 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1365 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1366 }
1367 }
1368
1369 fn alias_component_outer(
1370 &mut self,
1371 kind: wasmparser::ComponentOuterAliasKind,
1372 count: u32,
1373 index: u32,
1374 ) {
1375 match kind {
1376 wasmparser::ComponentOuterAliasKind::CoreType
1377 | wasmparser::ComponentOuterAliasKind::Type => {}
1378
1379 wasmparser::ComponentOuterAliasKind::CoreModule => {
1386 let index = ModuleIndex::from_u32(index);
1387 let mut module = ClosedOverModule::Local(index);
1388 let depth = self.lexical_scopes.len() - (count as usize);
1389 for frame in self.lexical_scopes[depth..].iter_mut() {
1390 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1391 }
1392
1393 self.result
1398 .initializers
1399 .push(LocalInitializer::AliasModule(module));
1400 }
1401 wasmparser::ComponentOuterAliasKind::Component => {
1402 let index = ComponentIndex::from_u32(index);
1403 let mut component = ClosedOverComponent::Local(index);
1404 let depth = self.lexical_scopes.len() - (count as usize);
1405 for frame in self.lexical_scopes[depth..].iter_mut() {
1406 component =
1407 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1408 }
1409
1410 self.result
1411 .initializers
1412 .push(LocalInitializer::AliasComponent(component));
1413 }
1414 }
1415 }
1416
1417 fn canonical_options(
1418 &mut self,
1419 opts: &[wasmparser::CanonicalOption],
1420 core_func_index: u32,
1421 ) -> WasmResult<LocalCanonicalOptions> {
1422 let core_type = self.core_func_signature(core_func_index)?;
1423
1424 let mut string_encoding = StringEncoding::Utf8;
1425 let mut post_return = None;
1426 let mut async_ = false;
1427 let mut callback = None;
1428 let mut memory = None;
1429 let mut realloc = None;
1430 let mut gc = false;
1431
1432 for opt in opts {
1433 match opt {
1434 wasmparser::CanonicalOption::UTF8 => {
1435 string_encoding = StringEncoding::Utf8;
1436 }
1437 wasmparser::CanonicalOption::UTF16 => {
1438 string_encoding = StringEncoding::Utf16;
1439 }
1440 wasmparser::CanonicalOption::CompactUTF16 => {
1441 string_encoding = StringEncoding::CompactUtf16;
1442 }
1443 wasmparser::CanonicalOption::Memory(idx) => {
1444 let idx = MemoryIndex::from_u32(*idx);
1445 memory = Some(idx);
1446 }
1447 wasmparser::CanonicalOption::Realloc(idx) => {
1448 let idx = FuncIndex::from_u32(*idx);
1449 realloc = Some(idx);
1450 }
1451 wasmparser::CanonicalOption::PostReturn(idx) => {
1452 let idx = FuncIndex::from_u32(*idx);
1453 post_return = Some(idx);
1454 }
1455 wasmparser::CanonicalOption::Async => async_ = true,
1456 wasmparser::CanonicalOption::Callback(idx) => {
1457 let idx = FuncIndex::from_u32(*idx);
1458 callback = Some(idx);
1459 }
1460 wasmparser::CanonicalOption::CoreType(idx) => {
1461 if cfg!(debug_assertions) {
1462 let types = self.validator.types(0).unwrap();
1463 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1464 let interned = self
1465 .types
1466 .module_types_builder()
1467 .intern_type(types, core_ty_id)?;
1468 debug_assert_eq!(interned, core_type);
1469 }
1470 }
1471 wasmparser::CanonicalOption::Gc => {
1472 gc = true;
1473 }
1474 }
1475 }
1476
1477 Ok(LocalCanonicalOptions {
1478 string_encoding,
1479 post_return,
1480 async_,
1481 callback,
1482 core_type,
1483 data_model: if gc {
1484 LocalDataModel::Gc {}
1485 } else {
1486 LocalDataModel::LinearMemory { memory, realloc }
1487 },
1488 })
1489 }
1490
1491 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1493 let types = self.validator.types(0).unwrap();
1494 let id = types.core_function_at(index);
1495 self.types.module_types_builder().intern_type(types, id)
1496 }
1497}
1498
1499impl Translation<'_> {
1500 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1501 self.types.as_ref().unwrap().as_ref()
1502 }
1503}
1504
1505mod pre_inlining {
1517 use super::*;
1518
1519 pub struct PreInliningComponentTypes<'a> {
1520 types: &'a mut ComponentTypesBuilder,
1521 }
1522
1523 impl<'a> PreInliningComponentTypes<'a> {
1524 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1525 Self { types }
1526 }
1527
1528 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1529 self.types.module_types_builder_mut()
1530 }
1531
1532 pub fn types(&self) -> &ComponentTypesBuilder {
1533 self.types
1534 }
1535
1536 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1539 self.types
1540 }
1541 }
1542
1543 impl TypeConvert for PreInliningComponentTypes<'_> {
1544 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1545 self.types.lookup_heap_type(index)
1546 }
1547
1548 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1549 self.types.lookup_type_index(index)
1550 }
1551 }
1552}
1553use pre_inlining::PreInliningComponentTypes;