1use crate::Abi;
2use crate::component::dfg::AbstractInstantiations;
3use crate::component::*;
4use crate::prelude::*;
5use crate::{
6 EngineOrModuleTypeIndex, EntityIndex, FuncKey, ModuleEnvironment, ModuleInternedTypeIndex,
7 ModuleTranslation, ModuleTypesBuilder, PrimaryMap, ScopeVec, TagIndex, Tunables, TypeConvert,
8 WasmHeapType, WasmResult, WasmValType,
9};
10use core::str::FromStr;
11use cranelift_entity::SecondaryMap;
12use cranelift_entity::packed_option::PackedOption;
13use indexmap::IndexMap;
14use std::collections::HashMap;
15use std::mem;
16use wasmparser::component_types::{
17 AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
18 ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
19};
20use wasmparser::types::Types;
21use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
22
23mod adapt;
24pub use self::adapt::*;
25mod inline;
26
27pub struct Translator<'a, 'data> {
29 result: Translation<'data>,
34
35 parser: Parser,
38
39 lexical_scopes: Vec<LexicalScope<'data>>,
47
48 validator: &'a mut Validator,
51
52 types: PreInliningComponentTypes<'a>,
57
58 tunables: &'a Tunables,
60
61 scope_vec: &'data ScopeVec<u8>,
63
64 static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
69
70 static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
75
76 unsafe_intrinsics_import: Option<&'a str>,
78}
79
80struct LexicalScope<'data> {
133 parser: Parser,
135 translation: Translation<'data>,
137 closure_args: ClosedOverVars,
140}
141
142#[derive(Default)]
152struct Translation<'data> {
153 initializers: Vec<LocalInitializer<'data>>,
159
160 exports: IndexMap<&'data str, ComponentItem>,
163
164 types: Option<Types>,
170}
171
172enum LocalInitializer<'data> {
178 Import(ComponentImportName<'data>, ComponentEntityType),
180
181 IntrinsicsImport,
183
184 Lower {
186 func: ComponentFuncIndex,
187 lower_ty: ComponentFuncTypeId,
188 options: LocalCanonicalOptions,
189 },
190 Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
191
192 Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
194 ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
195 ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
196 ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
197
198 BackpressureInc {
199 func: ModuleInternedTypeIndex,
200 },
201 BackpressureDec {
202 func: ModuleInternedTypeIndex,
203 },
204 TaskReturn {
205 result: Option<ComponentValType>,
206 options: LocalCanonicalOptions,
207 },
208 TaskCancel {
209 func: ModuleInternedTypeIndex,
210 },
211 WaitableSetNew {
212 func: ModuleInternedTypeIndex,
213 },
214 WaitableSetWait {
215 options: LocalCanonicalOptions,
216 },
217 WaitableSetPoll {
218 options: LocalCanonicalOptions,
219 },
220 WaitableSetDrop {
221 func: ModuleInternedTypeIndex,
222 },
223 WaitableJoin {
224 func: ModuleInternedTypeIndex,
225 },
226 ThreadYield {
227 func: ModuleInternedTypeIndex,
228 cancellable: bool,
229 },
230 SubtaskDrop {
231 func: ModuleInternedTypeIndex,
232 },
233 SubtaskCancel {
234 func: ModuleInternedTypeIndex,
235 async_: bool,
236 },
237 StreamNew {
238 ty: ComponentDefinedTypeId,
239 func: ModuleInternedTypeIndex,
240 },
241 StreamRead {
242 ty: ComponentDefinedTypeId,
243 options: LocalCanonicalOptions,
244 },
245 StreamWrite {
246 ty: ComponentDefinedTypeId,
247 options: LocalCanonicalOptions,
248 },
249 StreamCancelRead {
250 ty: ComponentDefinedTypeId,
251 func: ModuleInternedTypeIndex,
252 async_: bool,
253 },
254 StreamCancelWrite {
255 ty: ComponentDefinedTypeId,
256 func: ModuleInternedTypeIndex,
257 async_: bool,
258 },
259 StreamDropReadable {
260 ty: ComponentDefinedTypeId,
261 func: ModuleInternedTypeIndex,
262 },
263 StreamDropWritable {
264 ty: ComponentDefinedTypeId,
265 func: ModuleInternedTypeIndex,
266 },
267 FutureNew {
268 ty: ComponentDefinedTypeId,
269 func: ModuleInternedTypeIndex,
270 },
271 FutureRead {
272 ty: ComponentDefinedTypeId,
273 options: LocalCanonicalOptions,
274 },
275 FutureWrite {
276 ty: ComponentDefinedTypeId,
277 options: LocalCanonicalOptions,
278 },
279 FutureCancelRead {
280 ty: ComponentDefinedTypeId,
281 func: ModuleInternedTypeIndex,
282 async_: bool,
283 },
284 FutureCancelWrite {
285 ty: ComponentDefinedTypeId,
286 func: ModuleInternedTypeIndex,
287 async_: bool,
288 },
289 FutureDropReadable {
290 ty: ComponentDefinedTypeId,
291 func: ModuleInternedTypeIndex,
292 },
293 FutureDropWritable {
294 ty: ComponentDefinedTypeId,
295 func: ModuleInternedTypeIndex,
296 },
297 ErrorContextNew {
298 options: LocalCanonicalOptions,
299 },
300 ErrorContextDebugMessage {
301 options: LocalCanonicalOptions,
302 },
303 ErrorContextDrop {
304 func: ModuleInternedTypeIndex,
305 },
306 ContextGet {
307 func: ModuleInternedTypeIndex,
308 i: u32,
309 },
310 ContextSet {
311 func: ModuleInternedTypeIndex,
312 i: u32,
313 },
314 ThreadIndex {
315 func: ModuleInternedTypeIndex,
316 },
317 ThreadNewIndirect {
318 func: ModuleInternedTypeIndex,
319 start_func_ty: ComponentTypeIndex,
320 start_func_table_index: TableIndex,
321 },
322 ThreadSuspendToSuspended {
323 func: ModuleInternedTypeIndex,
324 cancellable: bool,
325 },
326 ThreadSuspend {
327 func: ModuleInternedTypeIndex,
328 cancellable: bool,
329 },
330 ThreadSuspendTo {
331 func: ModuleInternedTypeIndex,
332 cancellable: bool,
333 },
334 ThreadUnsuspend {
335 func: ModuleInternedTypeIndex,
336 },
337 ThreadYieldToSuspended {
338 func: ModuleInternedTypeIndex,
339 cancellable: bool,
340 },
341
342 ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
344
345 ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
347 ModuleSynthetic(HashMap<&'data str, EntityIndex>),
348
349 ComponentStatic(StaticComponentIndex, ClosedOverVars),
351
352 ComponentInstantiate(
354 ComponentIndex,
355 HashMap<&'data str, ComponentItem>,
356 ComponentInstanceTypeId,
357 ),
358 ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
359
360 AliasExportFunc(ModuleInstanceIndex, &'data str),
362 AliasExportTable(ModuleInstanceIndex, &'data str),
363 AliasExportGlobal(ModuleInstanceIndex, &'data str),
364 AliasExportMemory(ModuleInstanceIndex, &'data str),
365 AliasExportTag(ModuleInstanceIndex, &'data str),
366 AliasComponentExport(ComponentInstanceIndex, &'data str),
367 AliasModule(ClosedOverModule),
368 AliasComponent(ClosedOverComponent),
369
370 Export(ComponentItem),
372}
373
374#[derive(Default)]
378struct ClosedOverVars {
379 components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
380 modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
381}
382
383enum ClosedOverComponent {
388 Local(ComponentIndex),
391 Upvar(ComponentUpvarIndex),
396}
397
398enum ClosedOverModule {
400 Local(ModuleIndex),
401 Upvar(ModuleUpvarIndex),
402}
403
404#[derive(Debug, Clone, Hash, Eq, PartialEq)]
406pub enum LocalDataModel {
407 Gc {},
409
410 LinearMemory {
412 memory: Option<MemoryIndex>,
414 realloc: Option<FuncIndex>,
416 },
417}
418
419struct LocalCanonicalOptions {
421 string_encoding: StringEncoding,
422 post_return: Option<FuncIndex>,
423 async_: bool,
424 cancellable: bool,
425 callback: Option<FuncIndex>,
426 core_type: ModuleInternedTypeIndex,
428 data_model: LocalDataModel,
429}
430
431enum Action {
432 KeepGoing,
433 Skip(usize),
434 Done,
435}
436
437impl<'a, 'data> Translator<'a, 'data> {
438 pub fn new(
440 tunables: &'a Tunables,
441 validator: &'a mut Validator,
442 types: &'a mut ComponentTypesBuilder,
443 scope_vec: &'data ScopeVec<u8>,
444 ) -> Self {
445 let mut parser = Parser::new(0);
446 parser.set_features(*validator.features());
447 Self {
448 result: Translation::default(),
449 tunables,
450 validator,
451 types: PreInliningComponentTypes::new(types),
452 parser,
453 lexical_scopes: Vec::new(),
454 static_components: Default::default(),
455 static_modules: Default::default(),
456 scope_vec,
457 unsafe_intrinsics_import: None,
458 }
459 }
460
461 pub fn expose_unsafe_intrinsics(&mut self, name: &'a str) -> &mut Self {
464 assert!(self.unsafe_intrinsics_import.is_none());
465 self.unsafe_intrinsics_import = Some(name);
466 self
467 }
468
469 pub fn translate(
493 mut self,
494 component: &'data [u8],
495 ) -> Result<(
496 ComponentTranslation,
497 PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
498 )> {
499 let mut remaining = component;
505 loop {
506 let payload = match self.parser.parse(remaining, true)? {
507 Chunk::Parsed { payload, consumed } => {
508 remaining = &remaining[consumed..];
509 payload
510 }
511 Chunk::NeedMoreData(_) => unreachable!(),
512 };
513
514 match self.translate_payload(payload, component)? {
515 Action::KeepGoing => {}
516 Action::Skip(n) => remaining = &remaining[n..],
517 Action::Done => break,
518 }
519 }
520 assert!(remaining.is_empty());
521 assert!(self.lexical_scopes.is_empty());
522
523 let mut component = inline::run(
534 self.types.types_mut_for_inlining(),
535 &self.result,
536 &self.static_modules,
537 &self.static_components,
538 )?;
539
540 self.partition_adapter_modules(&mut component);
541
542 let translation =
543 component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
544
545 self.analyze_function_imports(&translation);
546
547 Ok((translation, self.static_modules))
548 }
549
550 fn analyze_function_imports(&mut self, translation: &ComponentTranslation) {
551 let mut instantiations = SecondaryMap::<StaticModuleIndex, AbstractInstantiations>::new();
554 let mut instance_to_module =
555 PrimaryMap::<RuntimeInstanceIndex, PackedOption<StaticModuleIndex>>::new();
556 for init in &translation.component.initializers {
557 match init {
558 GlobalInitializer::InstantiateModule(instantiation, _) => match instantiation {
559 InstantiateModule::Static(module, args) => {
560 instantiations[*module].join(AbstractInstantiations::One(&*args));
561 instance_to_module.push(Some(*module).into());
562 }
563 _ => {
564 instance_to_module.push(None.into());
565 }
566 },
567 _ => continue,
568 }
569 }
570
571 for item in translation.component.export_items.values() {
574 if let Export::ModuleStatic { index, .. } = item {
575 instantiations[*index].join(AbstractInstantiations::Many)
576 }
577 }
578
579 for (module, instantiations) in instantiations.iter() {
584 let args = match instantiations {
585 dfg::AbstractInstantiations::Many | dfg::AbstractInstantiations::None => continue,
586 dfg::AbstractInstantiations::One(args) => args,
587 };
588
589 let mut imported_func_counter = 0_u32;
590 for (i, arg) in args.iter().enumerate() {
591 let (_, _, crate::types::EntityType::Function(_)) =
593 self.static_modules[module].module.import(i).unwrap()
594 else {
595 continue;
596 };
597
598 let imported_func = FuncIndex::from_u32(imported_func_counter);
599 imported_func_counter += 1;
600 debug_assert!(
601 self.static_modules[module]
602 .module
603 .defined_func_index(imported_func)
604 .is_none()
605 );
606
607 let known_func = match arg {
608 CoreDef::InstanceFlags(_) => unreachable!("instance flags are not a function"),
609 CoreDef::TaskMayBlock => unreachable!("task_may_block is not a function"),
610
611 CoreDef::Trampoline(_) => continue,
624
625 CoreDef::UnsafeIntrinsic(i) => FuncKey::UnsafeIntrinsic(Abi::Wasm, *i),
629
630 CoreDef::Export(export) => {
634 let Some(arg_module) = &instance_to_module[export.instance].expand() else {
635 continue;
640 };
641
642 let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
643 else {
644 unreachable!("function imports must be functions")
645 };
646
647 let Some(arg_module_def_func) = self.static_modules[*arg_module]
648 .module
649 .defined_func_index(*arg_func)
650 else {
651 continue;
658 };
659
660 FuncKey::DefinedWasmFunction(*arg_module, arg_module_def_func)
661 }
662 };
663
664 assert!(
665 self.static_modules[module].known_imported_functions[imported_func].is_none()
666 );
667 self.static_modules[module].known_imported_functions[imported_func] =
668 Some(known_func);
669 }
670 }
671 }
672
673 fn translate_payload(
674 &mut self,
675 payload: Payload<'data>,
676 component: &'data [u8],
677 ) -> Result<Action> {
678 match payload {
679 Payload::Version {
680 num,
681 encoding,
682 range,
683 } => {
684 self.validator.version(num, encoding, &range)?;
685
686 match encoding {
687 Encoding::Component => {}
688 Encoding::Module => {
689 bail!("attempted to parse a wasm module with a component parser");
690 }
691 }
692 }
693
694 Payload::End(offset) => {
695 assert!(self.result.types.is_none());
696 self.result.types = Some(self.validator.end(offset)?);
697
698 let LexicalScope {
703 parser,
704 translation,
705 closure_args,
706 } = match self.lexical_scopes.pop() {
707 Some(frame) => frame,
708 None => return Ok(Action::Done),
709 };
710 self.parser = parser;
711 let component = mem::replace(&mut self.result, translation);
712 let static_idx = self.static_components.push(component);
713 self.result
714 .initializers
715 .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
716 }
717
718 Payload::ComponentTypeSection(s) => {
727 let mut component_type_index =
728 self.validator.types(0).unwrap().component_type_count();
729 self.validator.component_type_section(&s)?;
730
731 let types = self.validator.types(0).unwrap();
735 for ty in s {
736 match ty? {
737 wasmparser::ComponentType::Resource { rep, dtor } => {
738 let rep = self.types.convert_valtype(rep)?;
739 let id = types
740 .component_any_type_at(component_type_index)
741 .unwrap_resource();
742 let dtor = dtor.map(FuncIndex::from_u32);
743 self.result
744 .initializers
745 .push(LocalInitializer::Resource(id, rep, dtor));
746 }
747
748 wasmparser::ComponentType::Defined(_)
750 | wasmparser::ComponentType::Func(_)
751 | wasmparser::ComponentType::Instance(_)
752 | wasmparser::ComponentType::Component(_) => {}
753 }
754
755 component_type_index += 1;
756 }
757 }
758 Payload::CoreTypeSection(s) => {
759 self.validator.core_type_section(&s)?;
760 }
761
762 Payload::ComponentImportSection(s) => {
766 self.validator.component_import_section(&s)?;
767 for import in s {
768 let import = import?;
769 let types = self.validator.types(0).unwrap();
770 let ty = types
771 .component_entity_type_of_import(import.name.0)
772 .unwrap();
773
774 if self.is_unsafe_intrinsics_import(import.name.0) {
775 self.check_unsafe_intrinsics_import(import.name.0, ty)?;
776 self.result
777 .initializers
778 .push(LocalInitializer::IntrinsicsImport);
779 } else {
780 self.result
781 .initializers
782 .push(LocalInitializer::Import(import.name, ty));
783 }
784 }
785 }
786
787 Payload::ComponentCanonicalSection(s) => {
790 let types = self.validator.types(0).unwrap();
791 let mut core_func_index = types.function_count();
792 self.validator.component_canonical_section(&s)?;
793 for func in s {
794 let init = match func? {
795 wasmparser::CanonicalFunction::Lift {
796 type_index,
797 core_func_index,
798 options,
799 } => {
800 let ty = self
801 .validator
802 .types(0)
803 .unwrap()
804 .component_any_type_at(type_index)
805 .unwrap_func();
806
807 let func = FuncIndex::from_u32(core_func_index);
808 let options = self.canonical_options(&options, core_func_index)?;
809 LocalInitializer::Lift(ty, func, options)
810 }
811 wasmparser::CanonicalFunction::Lower {
812 func_index,
813 options,
814 } => {
815 let lower_ty = self
816 .validator
817 .types(0)
818 .unwrap()
819 .component_function_at(func_index);
820 let func = ComponentFuncIndex::from_u32(func_index);
821 let options = self.canonical_options(&options, core_func_index)?;
822 core_func_index += 1;
823 LocalInitializer::Lower {
824 func,
825 options,
826 lower_ty,
827 }
828 }
829 wasmparser::CanonicalFunction::ResourceNew { resource } => {
830 let resource = self
831 .validator
832 .types(0)
833 .unwrap()
834 .component_any_type_at(resource)
835 .unwrap_resource();
836 let ty = self.core_func_signature(core_func_index)?;
837 core_func_index += 1;
838 LocalInitializer::ResourceNew(resource, ty)
839 }
840 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
841 let resource = self
842 .validator
843 .types(0)
844 .unwrap()
845 .component_any_type_at(resource)
846 .unwrap_resource();
847 let ty = self.core_func_signature(core_func_index)?;
848 core_func_index += 1;
849 LocalInitializer::ResourceDrop(resource, ty)
850 }
851 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
852 let _ = resource;
853 bail!("support for `resource.drop async` not implemented yet")
854 }
855 wasmparser::CanonicalFunction::ResourceRep { resource } => {
856 let resource = self
857 .validator
858 .types(0)
859 .unwrap()
860 .component_any_type_at(resource)
861 .unwrap_resource();
862 let ty = self.core_func_signature(core_func_index)?;
863 core_func_index += 1;
864 LocalInitializer::ResourceRep(resource, ty)
865 }
866 wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
867 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
868 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
869 bail!("unsupported intrinsic")
870 }
871 wasmparser::CanonicalFunction::BackpressureInc => {
872 let core_type = self.core_func_signature(core_func_index)?;
873 core_func_index += 1;
874 LocalInitializer::BackpressureInc { func: core_type }
875 }
876 wasmparser::CanonicalFunction::BackpressureDec => {
877 let core_type = self.core_func_signature(core_func_index)?;
878 core_func_index += 1;
879 LocalInitializer::BackpressureDec { func: core_type }
880 }
881
882 wasmparser::CanonicalFunction::TaskReturn { result, options } => {
883 let result = result.map(|ty| match ty {
884 wasmparser::ComponentValType::Primitive(ty) => {
885 ComponentValType::Primitive(ty)
886 }
887 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
888 self.validator
889 .types(0)
890 .unwrap()
891 .component_defined_type_at(ty),
892 ),
893 });
894 let options = self.canonical_options(&options, core_func_index)?;
895 core_func_index += 1;
896 LocalInitializer::TaskReturn { result, options }
897 }
898 wasmparser::CanonicalFunction::TaskCancel => {
899 let func = self.core_func_signature(core_func_index)?;
900 core_func_index += 1;
901 LocalInitializer::TaskCancel { func }
902 }
903 wasmparser::CanonicalFunction::WaitableSetNew => {
904 let func = self.core_func_signature(core_func_index)?;
905 core_func_index += 1;
906 LocalInitializer::WaitableSetNew { func }
907 }
908 wasmparser::CanonicalFunction::WaitableSetWait {
909 cancellable,
910 memory,
911 } => {
912 let core_type = self.core_func_signature(core_func_index)?;
913 core_func_index += 1;
914 LocalInitializer::WaitableSetWait {
915 options: LocalCanonicalOptions {
916 core_type,
917 cancellable,
918 async_: false,
919 data_model: LocalDataModel::LinearMemory {
920 memory: Some(MemoryIndex::from_u32(memory)),
921 realloc: None,
922 },
923 post_return: None,
924 callback: None,
925 string_encoding: StringEncoding::Utf8,
926 },
927 }
928 }
929 wasmparser::CanonicalFunction::WaitableSetPoll {
930 cancellable,
931 memory,
932 } => {
933 let core_type = self.core_func_signature(core_func_index)?;
934 core_func_index += 1;
935 LocalInitializer::WaitableSetPoll {
936 options: LocalCanonicalOptions {
937 core_type,
938 async_: false,
939 cancellable,
940 data_model: LocalDataModel::LinearMemory {
941 memory: Some(MemoryIndex::from_u32(memory)),
942 realloc: None,
943 },
944 post_return: None,
945 callback: None,
946 string_encoding: StringEncoding::Utf8,
947 },
948 }
949 }
950 wasmparser::CanonicalFunction::WaitableSetDrop => {
951 let func = self.core_func_signature(core_func_index)?;
952 core_func_index += 1;
953 LocalInitializer::WaitableSetDrop { func }
954 }
955 wasmparser::CanonicalFunction::WaitableJoin => {
956 let func = self.core_func_signature(core_func_index)?;
957 core_func_index += 1;
958 LocalInitializer::WaitableJoin { func }
959 }
960 wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
961 let func = self.core_func_signature(core_func_index)?;
962 core_func_index += 1;
963 LocalInitializer::ThreadYield { func, cancellable }
964 }
965 wasmparser::CanonicalFunction::SubtaskDrop => {
966 let func = self.core_func_signature(core_func_index)?;
967 core_func_index += 1;
968 LocalInitializer::SubtaskDrop { func }
969 }
970 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
971 let func = self.core_func_signature(core_func_index)?;
972 core_func_index += 1;
973 LocalInitializer::SubtaskCancel { func, async_ }
974 }
975 wasmparser::CanonicalFunction::StreamNew { ty } => {
976 let ty = self
977 .validator
978 .types(0)
979 .unwrap()
980 .component_defined_type_at(ty);
981 let func = self.core_func_signature(core_func_index)?;
982 core_func_index += 1;
983 LocalInitializer::StreamNew { ty, func }
984 }
985 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
986 let ty = self
987 .validator
988 .types(0)
989 .unwrap()
990 .component_defined_type_at(ty);
991 let options = self.canonical_options(&options, core_func_index)?;
992 core_func_index += 1;
993 LocalInitializer::StreamRead { ty, options }
994 }
995 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
996 let ty = self
997 .validator
998 .types(0)
999 .unwrap()
1000 .component_defined_type_at(ty);
1001 let options = self.canonical_options(&options, core_func_index)?;
1002 core_func_index += 1;
1003 LocalInitializer::StreamWrite { ty, options }
1004 }
1005 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1006 let ty = self
1007 .validator
1008 .types(0)
1009 .unwrap()
1010 .component_defined_type_at(ty);
1011 let func = self.core_func_signature(core_func_index)?;
1012 core_func_index += 1;
1013 LocalInitializer::StreamCancelRead { ty, func, async_ }
1014 }
1015 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1016 let ty = self
1017 .validator
1018 .types(0)
1019 .unwrap()
1020 .component_defined_type_at(ty);
1021 let func = self.core_func_signature(core_func_index)?;
1022 core_func_index += 1;
1023 LocalInitializer::StreamCancelWrite { ty, func, async_ }
1024 }
1025 wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1026 let ty = self
1027 .validator
1028 .types(0)
1029 .unwrap()
1030 .component_defined_type_at(ty);
1031 let func = self.core_func_signature(core_func_index)?;
1032 core_func_index += 1;
1033 LocalInitializer::StreamDropReadable { ty, func }
1034 }
1035 wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1036 let ty = self
1037 .validator
1038 .types(0)
1039 .unwrap()
1040 .component_defined_type_at(ty);
1041 let func = self.core_func_signature(core_func_index)?;
1042 core_func_index += 1;
1043 LocalInitializer::StreamDropWritable { ty, func }
1044 }
1045 wasmparser::CanonicalFunction::FutureNew { ty } => {
1046 let ty = self
1047 .validator
1048 .types(0)
1049 .unwrap()
1050 .component_defined_type_at(ty);
1051 let func = self.core_func_signature(core_func_index)?;
1052 core_func_index += 1;
1053 LocalInitializer::FutureNew { ty, func }
1054 }
1055 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1056 let ty = self
1057 .validator
1058 .types(0)
1059 .unwrap()
1060 .component_defined_type_at(ty);
1061 let options = self.canonical_options(&options, core_func_index)?;
1062 core_func_index += 1;
1063 LocalInitializer::FutureRead { ty, options }
1064 }
1065 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1066 let ty = self
1067 .validator
1068 .types(0)
1069 .unwrap()
1070 .component_defined_type_at(ty);
1071 let options = self.canonical_options(&options, core_func_index)?;
1072 core_func_index += 1;
1073 LocalInitializer::FutureWrite { ty, options }
1074 }
1075 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1076 let ty = self
1077 .validator
1078 .types(0)
1079 .unwrap()
1080 .component_defined_type_at(ty);
1081 let func = self.core_func_signature(core_func_index)?;
1082 core_func_index += 1;
1083 LocalInitializer::FutureCancelRead { ty, func, async_ }
1084 }
1085 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1086 let ty = self
1087 .validator
1088 .types(0)
1089 .unwrap()
1090 .component_defined_type_at(ty);
1091 let func = self.core_func_signature(core_func_index)?;
1092 core_func_index += 1;
1093 LocalInitializer::FutureCancelWrite { ty, func, async_ }
1094 }
1095 wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1096 let ty = self
1097 .validator
1098 .types(0)
1099 .unwrap()
1100 .component_defined_type_at(ty);
1101 let func = self.core_func_signature(core_func_index)?;
1102 core_func_index += 1;
1103 LocalInitializer::FutureDropReadable { ty, func }
1104 }
1105 wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1106 let ty = self
1107 .validator
1108 .types(0)
1109 .unwrap()
1110 .component_defined_type_at(ty);
1111 let func = self.core_func_signature(core_func_index)?;
1112 core_func_index += 1;
1113 LocalInitializer::FutureDropWritable { ty, func }
1114 }
1115 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1116 let options = self.canonical_options(&options, core_func_index)?;
1117 core_func_index += 1;
1118 LocalInitializer::ErrorContextNew { options }
1119 }
1120 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1121 let options = self.canonical_options(&options, core_func_index)?;
1122 core_func_index += 1;
1123 LocalInitializer::ErrorContextDebugMessage { options }
1124 }
1125 wasmparser::CanonicalFunction::ErrorContextDrop => {
1126 let func = self.core_func_signature(core_func_index)?;
1127 core_func_index += 1;
1128 LocalInitializer::ErrorContextDrop { func }
1129 }
1130 wasmparser::CanonicalFunction::ContextGet { slot, ty } => {
1131 if ty != wasmparser::ValType::I32 {
1132 bail!("unsupported context.get type: {ty:?}");
1133 }
1134 let func = self.core_func_signature(core_func_index)?;
1135 core_func_index += 1;
1136 LocalInitializer::ContextGet { i: slot, func }
1137 }
1138 wasmparser::CanonicalFunction::ContextSet { slot, ty } => {
1139 if ty != wasmparser::ValType::I32 {
1140 bail!("unsupported context.set type: {ty:?}");
1141 }
1142 let func = self.core_func_signature(core_func_index)?;
1143 core_func_index += 1;
1144 LocalInitializer::ContextSet { i: slot, func }
1145 }
1146 wasmparser::CanonicalFunction::ThreadIndex => {
1147 let func = self.core_func_signature(core_func_index)?;
1148 core_func_index += 1;
1149 LocalInitializer::ThreadIndex { func }
1150 }
1151 wasmparser::CanonicalFunction::ThreadNewIndirect {
1152 func_ty_index,
1153 table_index,
1154 } => {
1155 let func = self.core_func_signature(core_func_index)?;
1156 core_func_index += 1;
1157 LocalInitializer::ThreadNewIndirect {
1158 func,
1159 start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1160 start_func_table_index: TableIndex::from_u32(table_index),
1161 }
1162 }
1163 wasmparser::CanonicalFunction::ThreadSuspendToSuspended { cancellable } => {
1164 let func = self.core_func_signature(core_func_index)?;
1165 core_func_index += 1;
1166 LocalInitializer::ThreadSuspendToSuspended { func, cancellable }
1167 }
1168 wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1169 let func = self.core_func_signature(core_func_index)?;
1170 core_func_index += 1;
1171 LocalInitializer::ThreadSuspend { func, cancellable }
1172 }
1173 wasmparser::CanonicalFunction::ThreadSuspendTo { cancellable } => {
1174 let func = self.core_func_signature(core_func_index)?;
1175 core_func_index += 1;
1176 LocalInitializer::ThreadSuspendTo { func, cancellable }
1177 }
1178 wasmparser::CanonicalFunction::ThreadUnsuspend => {
1179 let func = self.core_func_signature(core_func_index)?;
1180 core_func_index += 1;
1181 LocalInitializer::ThreadUnsuspend { func }
1182 }
1183 wasmparser::CanonicalFunction::ThreadYieldToSuspended { cancellable } => {
1184 let func = self.core_func_signature(core_func_index)?;
1185 core_func_index += 1;
1186 LocalInitializer::ThreadYieldToSuspended { func, cancellable }
1187 }
1188 };
1189 self.result.initializers.push(init);
1190 }
1191 }
1192
1193 Payload::ModuleSection {
1202 parser,
1203 unchecked_range,
1204 } => {
1205 let index = self.validator.types(0).unwrap().module_count();
1206 self.validator.module_section(&unchecked_range)?;
1207 let static_module_index = self.static_modules.next_key();
1208 let mut translation = ModuleEnvironment::new(
1209 self.tunables,
1210 self.validator,
1211 self.types.module_types_builder(),
1212 static_module_index,
1213 )
1214 .translate(
1215 parser,
1216 component
1217 .get(unchecked_range.start..unchecked_range.end)
1218 .ok_or_else(|| {
1219 format_err!(
1220 "section range {}..{} is out of bounds (bound = {})",
1221 unchecked_range.start,
1222 unchecked_range.end,
1223 component.len()
1224 )
1225 .context("wasm component contains an invalid module section")
1226 })?,
1227 )?;
1228
1229 translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap();
1230 let static_module_index2 = self.static_modules.push(translation);
1231 assert_eq!(static_module_index, static_module_index2);
1232 let types = self.validator.types(0).unwrap();
1233 let ty = types.module_at(index);
1234 self.result
1235 .initializers
1236 .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1237 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1238 }
1239
1240 Payload::ComponentSection {
1249 parser,
1250 unchecked_range,
1251 } => {
1252 self.validator.component_section(&unchecked_range)?;
1253 self.lexical_scopes.push(LexicalScope {
1254 parser: mem::replace(&mut self.parser, parser),
1255 translation: mem::take(&mut self.result),
1256 closure_args: ClosedOverVars::default(),
1257 });
1258 }
1259
1260 Payload::InstanceSection(s) => {
1265 self.validator.instance_section(&s)?;
1266 for instance in s {
1267 let init = match instance? {
1268 wasmparser::Instance::Instantiate { module_index, args } => {
1269 let index = ModuleIndex::from_u32(module_index);
1270 self.instantiate_module(index, &args)
1271 }
1272 wasmparser::Instance::FromExports(exports) => {
1273 self.instantiate_module_from_exports(&exports)
1274 }
1275 };
1276 self.result.initializers.push(init);
1277 }
1278 }
1279 Payload::ComponentInstanceSection(s) => {
1280 let mut index = self.validator.types(0).unwrap().component_instance_count();
1281 self.validator.component_instance_section(&s)?;
1282 for instance in s {
1283 let types = self.validator.types(0).unwrap();
1284 let ty = types.component_instance_at(index);
1285 let init = match instance? {
1286 wasmparser::ComponentInstance::Instantiate {
1287 component_index,
1288 args,
1289 } => {
1290 let index = ComponentIndex::from_u32(component_index);
1291 self.instantiate_component(index, &args, ty)?
1292 }
1293 wasmparser::ComponentInstance::FromExports(exports) => {
1294 self.instantiate_component_from_exports(&exports, ty)?
1295 }
1296 };
1297 self.result.initializers.push(init);
1298 index += 1;
1299 }
1300 }
1301
1302 Payload::ComponentExportSection(s) => {
1308 self.validator.component_export_section(&s)?;
1309 for export in s {
1310 let export = export?;
1311 let item = self.kind_to_item(export.kind, export.index)?;
1312 let prev = self.result.exports.insert(export.name.0, item);
1313 assert!(prev.is_none());
1314 self.result
1315 .initializers
1316 .push(LocalInitializer::Export(item));
1317 }
1318 }
1319
1320 Payload::ComponentStartSection { start, range } => {
1321 self.validator.component_start_section(&start, &range)?;
1322 unimplemented!("component start section");
1323 }
1324
1325 Payload::ComponentAliasSection(s) => {
1329 self.validator.component_alias_section(&s)?;
1330 for alias in s {
1331 let init = match alias? {
1332 wasmparser::ComponentAlias::InstanceExport {
1333 kind: _,
1334 instance_index,
1335 name,
1336 } => {
1337 let instance = ComponentInstanceIndex::from_u32(instance_index);
1338 LocalInitializer::AliasComponentExport(instance, name)
1339 }
1340 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1341 self.alias_component_outer(kind, count, index);
1342 continue;
1343 }
1344 wasmparser::ComponentAlias::CoreInstanceExport {
1345 kind,
1346 instance_index,
1347 name,
1348 } => {
1349 let instance = ModuleInstanceIndex::from_u32(instance_index);
1350 self.alias_module_instance_export(kind, instance, name)
1351 }
1352 };
1353 self.result.initializers.push(init);
1354 }
1355 }
1356
1357 Payload::CustomSection { .. } => {}
1362
1363 other => {
1369 self.validator.payload(&other)?;
1370 panic!("unimplemented section {other:?}");
1371 }
1372 }
1373
1374 Ok(Action::KeepGoing)
1375 }
1376
1377 fn instantiate_module(
1378 &mut self,
1379 module: ModuleIndex,
1380 raw_args: &[wasmparser::InstantiationArg<'data>],
1381 ) -> LocalInitializer<'data> {
1382 let mut args = HashMap::with_capacity(raw_args.len());
1383 for arg in raw_args {
1384 match arg.kind {
1385 wasmparser::InstantiationArgKind::Instance => {
1386 let idx = ModuleInstanceIndex::from_u32(arg.index);
1387 args.insert(arg.name, idx);
1388 }
1389 }
1390 }
1391 LocalInitializer::ModuleInstantiate(module, args)
1392 }
1393
1394 fn instantiate_module_from_exports(
1397 &mut self,
1398 exports: &[wasmparser::Export<'data>],
1399 ) -> LocalInitializer<'data> {
1400 let mut map = HashMap::with_capacity(exports.len());
1401 for export in exports {
1402 let idx = match export.kind {
1403 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1404 let index = FuncIndex::from_u32(export.index);
1405 EntityIndex::Function(index)
1406 }
1407 wasmparser::ExternalKind::Table => {
1408 let index = TableIndex::from_u32(export.index);
1409 EntityIndex::Table(index)
1410 }
1411 wasmparser::ExternalKind::Memory => {
1412 let index = MemoryIndex::from_u32(export.index);
1413 EntityIndex::Memory(index)
1414 }
1415 wasmparser::ExternalKind::Global => {
1416 let index = GlobalIndex::from_u32(export.index);
1417 EntityIndex::Global(index)
1418 }
1419 wasmparser::ExternalKind::Tag => {
1420 let index = TagIndex::from_u32(export.index);
1421 EntityIndex::Tag(index)
1422 }
1423 };
1424 map.insert(export.name, idx);
1425 }
1426 LocalInitializer::ModuleSynthetic(map)
1427 }
1428
1429 fn instantiate_component(
1430 &mut self,
1431 component: ComponentIndex,
1432 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1433 ty: ComponentInstanceTypeId,
1434 ) -> Result<LocalInitializer<'data>> {
1435 let mut args = HashMap::with_capacity(raw_args.len());
1436 for arg in raw_args {
1437 let idx = self.kind_to_item(arg.kind, arg.index)?;
1438 args.insert(arg.name, idx);
1439 }
1440
1441 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1442 }
1443
1444 fn instantiate_component_from_exports(
1447 &mut self,
1448 exports: &[wasmparser::ComponentExport<'data>],
1449 ty: ComponentInstanceTypeId,
1450 ) -> Result<LocalInitializer<'data>> {
1451 let mut map = HashMap::with_capacity(exports.len());
1452 for export in exports {
1453 let idx = self.kind_to_item(export.kind, export.index)?;
1454 map.insert(export.name.0, idx);
1455 }
1456
1457 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1458 }
1459
1460 fn kind_to_item(
1461 &mut self,
1462 kind: wasmparser::ComponentExternalKind,
1463 index: u32,
1464 ) -> Result<ComponentItem> {
1465 Ok(match kind {
1466 wasmparser::ComponentExternalKind::Func => {
1467 let index = ComponentFuncIndex::from_u32(index);
1468 ComponentItem::Func(index)
1469 }
1470 wasmparser::ComponentExternalKind::Module => {
1471 let index = ModuleIndex::from_u32(index);
1472 ComponentItem::Module(index)
1473 }
1474 wasmparser::ComponentExternalKind::Instance => {
1475 let index = ComponentInstanceIndex::from_u32(index);
1476 ComponentItem::ComponentInstance(index)
1477 }
1478 wasmparser::ComponentExternalKind::Component => {
1479 let index = ComponentIndex::from_u32(index);
1480 ComponentItem::Component(index)
1481 }
1482 wasmparser::ComponentExternalKind::Value => {
1483 unimplemented!("component values");
1484 }
1485 wasmparser::ComponentExternalKind::Type => {
1486 let types = self.validator.types(0).unwrap();
1487 let ty = types.component_any_type_at(index);
1488 ComponentItem::Type(ty)
1489 }
1490 })
1491 }
1492
1493 fn alias_module_instance_export(
1494 &mut self,
1495 kind: wasmparser::ExternalKind,
1496 instance: ModuleInstanceIndex,
1497 name: &'data str,
1498 ) -> LocalInitializer<'data> {
1499 match kind {
1500 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1501 LocalInitializer::AliasExportFunc(instance, name)
1502 }
1503 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1504 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1505 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1506 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1507 }
1508 }
1509
1510 fn alias_component_outer(
1511 &mut self,
1512 kind: wasmparser::ComponentOuterAliasKind,
1513 count: u32,
1514 index: u32,
1515 ) {
1516 match kind {
1517 wasmparser::ComponentOuterAliasKind::CoreType
1518 | wasmparser::ComponentOuterAliasKind::Type => {}
1519
1520 wasmparser::ComponentOuterAliasKind::CoreModule => {
1527 let index = ModuleIndex::from_u32(index);
1528 let mut module = ClosedOverModule::Local(index);
1529 let depth = self.lexical_scopes.len() - (count as usize);
1530 for frame in self.lexical_scopes[depth..].iter_mut() {
1531 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1532 }
1533
1534 self.result
1539 .initializers
1540 .push(LocalInitializer::AliasModule(module));
1541 }
1542 wasmparser::ComponentOuterAliasKind::Component => {
1543 let index = ComponentIndex::from_u32(index);
1544 let mut component = ClosedOverComponent::Local(index);
1545 let depth = self.lexical_scopes.len() - (count as usize);
1546 for frame in self.lexical_scopes[depth..].iter_mut() {
1547 component =
1548 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1549 }
1550
1551 self.result
1552 .initializers
1553 .push(LocalInitializer::AliasComponent(component));
1554 }
1555 }
1556 }
1557
1558 fn canonical_options(
1559 &mut self,
1560 opts: &[wasmparser::CanonicalOption],
1561 core_func_index: u32,
1562 ) -> WasmResult<LocalCanonicalOptions> {
1563 let core_type = self.core_func_signature(core_func_index)?;
1564
1565 let mut string_encoding = StringEncoding::Utf8;
1566 let mut post_return = None;
1567 let mut async_ = false;
1568 let mut callback = None;
1569 let mut memory = None;
1570 let mut realloc = None;
1571 let mut gc = false;
1572
1573 for opt in opts {
1574 match opt {
1575 wasmparser::CanonicalOption::UTF8 => {
1576 string_encoding = StringEncoding::Utf8;
1577 }
1578 wasmparser::CanonicalOption::UTF16 => {
1579 string_encoding = StringEncoding::Utf16;
1580 }
1581 wasmparser::CanonicalOption::CompactUTF16 => {
1582 string_encoding = StringEncoding::CompactUtf16;
1583 }
1584 wasmparser::CanonicalOption::Memory(idx) => {
1585 let idx = MemoryIndex::from_u32(*idx);
1586 memory = Some(idx);
1587 }
1588 wasmparser::CanonicalOption::Realloc(idx) => {
1589 let idx = FuncIndex::from_u32(*idx);
1590 realloc = Some(idx);
1591 }
1592 wasmparser::CanonicalOption::PostReturn(idx) => {
1593 let idx = FuncIndex::from_u32(*idx);
1594 post_return = Some(idx);
1595 }
1596 wasmparser::CanonicalOption::Async => async_ = true,
1597 wasmparser::CanonicalOption::Callback(idx) => {
1598 let idx = FuncIndex::from_u32(*idx);
1599 callback = Some(idx);
1600 }
1601 wasmparser::CanonicalOption::CoreType(idx) => {
1602 if cfg!(debug_assertions) {
1603 let types = self.validator.types(0).unwrap();
1604 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1605 let interned = self
1606 .types
1607 .module_types_builder()
1608 .intern_type(types, core_ty_id)?;
1609 debug_assert_eq!(interned, core_type);
1610 }
1611 }
1612 wasmparser::CanonicalOption::Gc => {
1613 gc = true;
1614 }
1615 }
1616 }
1617
1618 Ok(LocalCanonicalOptions {
1619 string_encoding,
1620 post_return,
1621 cancellable: false,
1622 async_,
1623 callback,
1624 core_type,
1625 data_model: if gc {
1626 LocalDataModel::Gc {}
1627 } else {
1628 LocalDataModel::LinearMemory { memory, realloc }
1629 },
1630 })
1631 }
1632
1633 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1635 let types = self.validator.types(0).unwrap();
1636 let id = types.core_function_at(index);
1637 self.types.module_types_builder().intern_type(types, id)
1638 }
1639
1640 fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1641 self.lexical_scopes.is_empty()
1642 && self
1643 .unsafe_intrinsics_import
1644 .is_some_and(|name| import == name)
1645 }
1646
1647 fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1648 let types = &self.validator.types(0).unwrap();
1649
1650 let ComponentEntityType::Instance(instance_ty) = ty else {
1651 bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1652 };
1653 let instance_ty = &types[instance_ty];
1654
1655 ensure!(
1656 instance_ty.defined_resources.is_empty(),
1657 "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1658 );
1659 ensure!(
1660 instance_ty.explicit_resources.is_empty(),
1661 "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1662 );
1663
1664 for (name, ty) in &instance_ty.exports {
1665 let ComponentEntityType::Func(func_ty) = ty else {
1666 bail!(
1667 "bad unsafe intrinsics import: imported instance `{import}` must \
1668 only export functions"
1669 )
1670 };
1671 let func_ty = &types[*func_ty];
1672
1673 fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1674 use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1675 match (a, b) {
1676 (InterfaceType::U8, C::Primitive(P::U8)) => true,
1677 (InterfaceType::U8, _) => false,
1678
1679 (InterfaceType::U16, C::Primitive(P::U16)) => true,
1680 (InterfaceType::U16, _) => false,
1681
1682 (InterfaceType::U32, C::Primitive(P::U32)) => true,
1683 (InterfaceType::U32, _) => false,
1684
1685 (InterfaceType::U64, C::Primitive(P::U64)) => true,
1686 (InterfaceType::U64, _) => false,
1687
1688 (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1689 }
1690 }
1691
1692 fn check_types<'a>(
1693 expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1694 actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1695 kind: &str,
1696 import: &str,
1697 name: &str,
1698 ) -> Result<()> {
1699 let expected_len = expected.len();
1700 let actual_len = actual.len();
1701 ensure!(
1702 expected_len == actual_len,
1703 "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1704 {expected_len} {kind}, found {actual_len}"
1705 );
1706
1707 for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1708 ensure!(
1709 ty_eq(expected_ty, actual_ty),
1710 "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1711 `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1712 );
1713 }
1714 Ok(())
1715 }
1716
1717 let intrinsic = UnsafeIntrinsic::from_str(name)
1718 .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1719
1720 check_types(
1721 intrinsic.component_params().iter(),
1722 func_ty.params.iter().map(|(_name, ty)| ty),
1723 "parameters",
1724 &import,
1725 &name,
1726 )?;
1727 check_types(
1728 intrinsic.component_results().iter(),
1729 func_ty.result.iter(),
1730 "results",
1731 &import,
1732 &name,
1733 )?;
1734 }
1735
1736 Ok(())
1737 }
1738}
1739
1740impl Translation<'_> {
1741 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1742 self.types.as_ref().unwrap().as_ref()
1743 }
1744}
1745
1746mod pre_inlining {
1758 use super::*;
1759
1760 pub struct PreInliningComponentTypes<'a> {
1761 types: &'a mut ComponentTypesBuilder,
1762 }
1763
1764 impl<'a> PreInliningComponentTypes<'a> {
1765 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1766 Self { types }
1767 }
1768
1769 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1770 self.types.module_types_builder_mut()
1771 }
1772
1773 pub fn types(&self) -> &ComponentTypesBuilder {
1774 self.types
1775 }
1776
1777 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1780 self.types
1781 }
1782 }
1783
1784 impl TypeConvert for PreInliningComponentTypes<'_> {
1785 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1786 self.types.lookup_heap_type(index)
1787 }
1788
1789 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1790 self.types.lookup_type_index(index)
1791 }
1792 }
1793}
1794use pre_inlining::PreInliningComponentTypes;