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