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, ComponentExternName, 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(ComponentExternName<'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_item_for_import(import.name.name)
772 .unwrap()
773 .ty;
774
775 if self.is_unsafe_intrinsics_import(import.name.name) {
776 self.check_unsafe_intrinsics_import(import.name.name, ty)?;
777 self.result
778 .initializers
779 .push(LocalInitializer::IntrinsicsImport);
780 } else {
781 self.result
782 .initializers
783 .push(LocalInitializer::Import(import.name, ty));
784 }
785 }
786 }
787
788 Payload::ComponentCanonicalSection(s) => {
791 let types = self.validator.types(0).unwrap();
792 let mut core_func_index = types.function_count();
793 self.validator.component_canonical_section(&s)?;
794 for func in s {
795 let init = match func? {
796 wasmparser::CanonicalFunction::Lift {
797 type_index,
798 core_func_index,
799 options,
800 } => {
801 let ty = self
802 .validator
803 .types(0)
804 .unwrap()
805 .component_any_type_at(type_index)
806 .unwrap_func();
807
808 let func = FuncIndex::from_u32(core_func_index);
809 let options = self.canonical_options(&options, core_func_index)?;
810 LocalInitializer::Lift(ty, func, options)
811 }
812 wasmparser::CanonicalFunction::Lower {
813 func_index,
814 options,
815 } => {
816 let lower_ty = self
817 .validator
818 .types(0)
819 .unwrap()
820 .component_function_at(func_index);
821 let func = ComponentFuncIndex::from_u32(func_index);
822 let options = self.canonical_options(&options, core_func_index)?;
823 core_func_index += 1;
824 LocalInitializer::Lower {
825 func,
826 options,
827 lower_ty,
828 }
829 }
830 wasmparser::CanonicalFunction::ResourceNew { resource } => {
831 let resource = self
832 .validator
833 .types(0)
834 .unwrap()
835 .component_any_type_at(resource)
836 .unwrap_resource();
837 let ty = self.core_func_signature(core_func_index)?;
838 core_func_index += 1;
839 LocalInitializer::ResourceNew(resource, ty)
840 }
841 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
842 let resource = self
843 .validator
844 .types(0)
845 .unwrap()
846 .component_any_type_at(resource)
847 .unwrap_resource();
848 let ty = self.core_func_signature(core_func_index)?;
849 core_func_index += 1;
850 LocalInitializer::ResourceDrop(resource, ty)
851 }
852 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
853 let _ = resource;
854 bail!("support for `resource.drop async` not implemented yet")
855 }
856 wasmparser::CanonicalFunction::ResourceRep { resource } => {
857 let resource = self
858 .validator
859 .types(0)
860 .unwrap()
861 .component_any_type_at(resource)
862 .unwrap_resource();
863 let ty = self.core_func_signature(core_func_index)?;
864 core_func_index += 1;
865 LocalInitializer::ResourceRep(resource, ty)
866 }
867 wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
868 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
869 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
870 bail!("unsupported intrinsic")
871 }
872 wasmparser::CanonicalFunction::BackpressureInc => {
873 let core_type = self.core_func_signature(core_func_index)?;
874 core_func_index += 1;
875 LocalInitializer::BackpressureInc { func: core_type }
876 }
877 wasmparser::CanonicalFunction::BackpressureDec => {
878 let core_type = self.core_func_signature(core_func_index)?;
879 core_func_index += 1;
880 LocalInitializer::BackpressureDec { func: core_type }
881 }
882
883 wasmparser::CanonicalFunction::TaskReturn { result, options } => {
884 let result = result.map(|ty| match ty {
885 wasmparser::ComponentValType::Primitive(ty) => {
886 ComponentValType::Primitive(ty)
887 }
888 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
889 self.validator
890 .types(0)
891 .unwrap()
892 .component_defined_type_at(ty),
893 ),
894 });
895 let options = self.canonical_options(&options, core_func_index)?;
896 core_func_index += 1;
897 LocalInitializer::TaskReturn { result, options }
898 }
899 wasmparser::CanonicalFunction::TaskCancel => {
900 let func = self.core_func_signature(core_func_index)?;
901 core_func_index += 1;
902 LocalInitializer::TaskCancel { func }
903 }
904 wasmparser::CanonicalFunction::WaitableSetNew => {
905 let func = self.core_func_signature(core_func_index)?;
906 core_func_index += 1;
907 LocalInitializer::WaitableSetNew { func }
908 }
909 wasmparser::CanonicalFunction::WaitableSetWait {
910 cancellable,
911 memory,
912 } => {
913 let core_type = self.core_func_signature(core_func_index)?;
914 core_func_index += 1;
915 LocalInitializer::WaitableSetWait {
916 options: LocalCanonicalOptions {
917 core_type,
918 cancellable,
919 async_: false,
920 data_model: LocalDataModel::LinearMemory {
921 memory: Some(MemoryIndex::from_u32(memory)),
922 realloc: None,
923 },
924 post_return: None,
925 callback: None,
926 string_encoding: StringEncoding::Utf8,
927 },
928 }
929 }
930 wasmparser::CanonicalFunction::WaitableSetPoll {
931 cancellable,
932 memory,
933 } => {
934 let core_type = self.core_func_signature(core_func_index)?;
935 core_func_index += 1;
936 LocalInitializer::WaitableSetPoll {
937 options: LocalCanonicalOptions {
938 core_type,
939 async_: false,
940 cancellable,
941 data_model: LocalDataModel::LinearMemory {
942 memory: Some(MemoryIndex::from_u32(memory)),
943 realloc: None,
944 },
945 post_return: None,
946 callback: None,
947 string_encoding: StringEncoding::Utf8,
948 },
949 }
950 }
951 wasmparser::CanonicalFunction::WaitableSetDrop => {
952 let func = self.core_func_signature(core_func_index)?;
953 core_func_index += 1;
954 LocalInitializer::WaitableSetDrop { func }
955 }
956 wasmparser::CanonicalFunction::WaitableJoin => {
957 let func = self.core_func_signature(core_func_index)?;
958 core_func_index += 1;
959 LocalInitializer::WaitableJoin { func }
960 }
961 wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
962 let func = self.core_func_signature(core_func_index)?;
963 core_func_index += 1;
964 LocalInitializer::ThreadYield { func, cancellable }
965 }
966 wasmparser::CanonicalFunction::SubtaskDrop => {
967 let func = self.core_func_signature(core_func_index)?;
968 core_func_index += 1;
969 LocalInitializer::SubtaskDrop { func }
970 }
971 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
972 let func = self.core_func_signature(core_func_index)?;
973 core_func_index += 1;
974 LocalInitializer::SubtaskCancel { func, async_ }
975 }
976 wasmparser::CanonicalFunction::StreamNew { ty } => {
977 let ty = self
978 .validator
979 .types(0)
980 .unwrap()
981 .component_defined_type_at(ty);
982 let func = self.core_func_signature(core_func_index)?;
983 core_func_index += 1;
984 LocalInitializer::StreamNew { ty, func }
985 }
986 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
987 let ty = self
988 .validator
989 .types(0)
990 .unwrap()
991 .component_defined_type_at(ty);
992 let options = self.canonical_options(&options, core_func_index)?;
993 core_func_index += 1;
994 LocalInitializer::StreamRead { ty, options }
995 }
996 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
997 let ty = self
998 .validator
999 .types(0)
1000 .unwrap()
1001 .component_defined_type_at(ty);
1002 let options = self.canonical_options(&options, core_func_index)?;
1003 core_func_index += 1;
1004 LocalInitializer::StreamWrite { ty, options }
1005 }
1006 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1007 let ty = self
1008 .validator
1009 .types(0)
1010 .unwrap()
1011 .component_defined_type_at(ty);
1012 let func = self.core_func_signature(core_func_index)?;
1013 core_func_index += 1;
1014 LocalInitializer::StreamCancelRead { ty, func, async_ }
1015 }
1016 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1017 let ty = self
1018 .validator
1019 .types(0)
1020 .unwrap()
1021 .component_defined_type_at(ty);
1022 let func = self.core_func_signature(core_func_index)?;
1023 core_func_index += 1;
1024 LocalInitializer::StreamCancelWrite { ty, func, async_ }
1025 }
1026 wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1027 let ty = self
1028 .validator
1029 .types(0)
1030 .unwrap()
1031 .component_defined_type_at(ty);
1032 let func = self.core_func_signature(core_func_index)?;
1033 core_func_index += 1;
1034 LocalInitializer::StreamDropReadable { ty, func }
1035 }
1036 wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1037 let ty = self
1038 .validator
1039 .types(0)
1040 .unwrap()
1041 .component_defined_type_at(ty);
1042 let func = self.core_func_signature(core_func_index)?;
1043 core_func_index += 1;
1044 LocalInitializer::StreamDropWritable { ty, func }
1045 }
1046 wasmparser::CanonicalFunction::FutureNew { ty } => {
1047 let ty = self
1048 .validator
1049 .types(0)
1050 .unwrap()
1051 .component_defined_type_at(ty);
1052 let func = self.core_func_signature(core_func_index)?;
1053 core_func_index += 1;
1054 LocalInitializer::FutureNew { ty, func }
1055 }
1056 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1057 let ty = self
1058 .validator
1059 .types(0)
1060 .unwrap()
1061 .component_defined_type_at(ty);
1062 let options = self.canonical_options(&options, core_func_index)?;
1063 core_func_index += 1;
1064 LocalInitializer::FutureRead { ty, options }
1065 }
1066 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1067 let ty = self
1068 .validator
1069 .types(0)
1070 .unwrap()
1071 .component_defined_type_at(ty);
1072 let options = self.canonical_options(&options, core_func_index)?;
1073 core_func_index += 1;
1074 LocalInitializer::FutureWrite { ty, options }
1075 }
1076 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1077 let ty = self
1078 .validator
1079 .types(0)
1080 .unwrap()
1081 .component_defined_type_at(ty);
1082 let func = self.core_func_signature(core_func_index)?;
1083 core_func_index += 1;
1084 LocalInitializer::FutureCancelRead { ty, func, async_ }
1085 }
1086 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1087 let ty = self
1088 .validator
1089 .types(0)
1090 .unwrap()
1091 .component_defined_type_at(ty);
1092 let func = self.core_func_signature(core_func_index)?;
1093 core_func_index += 1;
1094 LocalInitializer::FutureCancelWrite { ty, func, async_ }
1095 }
1096 wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1097 let ty = self
1098 .validator
1099 .types(0)
1100 .unwrap()
1101 .component_defined_type_at(ty);
1102 let func = self.core_func_signature(core_func_index)?;
1103 core_func_index += 1;
1104 LocalInitializer::FutureDropReadable { ty, func }
1105 }
1106 wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1107 let ty = self
1108 .validator
1109 .types(0)
1110 .unwrap()
1111 .component_defined_type_at(ty);
1112 let func = self.core_func_signature(core_func_index)?;
1113 core_func_index += 1;
1114 LocalInitializer::FutureDropWritable { ty, func }
1115 }
1116 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1117 let options = self.canonical_options(&options, core_func_index)?;
1118 core_func_index += 1;
1119 LocalInitializer::ErrorContextNew { options }
1120 }
1121 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1122 let options = self.canonical_options(&options, core_func_index)?;
1123 core_func_index += 1;
1124 LocalInitializer::ErrorContextDebugMessage { options }
1125 }
1126 wasmparser::CanonicalFunction::ErrorContextDrop => {
1127 let func = self.core_func_signature(core_func_index)?;
1128 core_func_index += 1;
1129 LocalInitializer::ErrorContextDrop { func }
1130 }
1131 wasmparser::CanonicalFunction::ContextGet { slot, ty } => {
1132 if ty != wasmparser::ValType::I32 {
1133 bail!("unsupported context.get type: {ty:?}");
1134 }
1135 let func = self.core_func_signature(core_func_index)?;
1136 core_func_index += 1;
1137 LocalInitializer::ContextGet { i: slot, func }
1138 }
1139 wasmparser::CanonicalFunction::ContextSet { slot, ty } => {
1140 if ty != wasmparser::ValType::I32 {
1141 bail!("unsupported context.set type: {ty:?}");
1142 }
1143 let func = self.core_func_signature(core_func_index)?;
1144 core_func_index += 1;
1145 LocalInitializer::ContextSet { i: slot, func }
1146 }
1147 wasmparser::CanonicalFunction::ThreadIndex => {
1148 let func = self.core_func_signature(core_func_index)?;
1149 core_func_index += 1;
1150 LocalInitializer::ThreadIndex { func }
1151 }
1152 wasmparser::CanonicalFunction::ThreadNewIndirect {
1153 func_ty_index,
1154 table_index,
1155 } => {
1156 let func = self.core_func_signature(core_func_index)?;
1157 core_func_index += 1;
1158 LocalInitializer::ThreadNewIndirect {
1159 func,
1160 start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1161 start_func_table_index: TableIndex::from_u32(table_index),
1162 }
1163 }
1164 wasmparser::CanonicalFunction::ThreadSuspendToSuspended { cancellable } => {
1165 let func = self.core_func_signature(core_func_index)?;
1166 core_func_index += 1;
1167 LocalInitializer::ThreadSuspendToSuspended { func, cancellable }
1168 }
1169 wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1170 let func = self.core_func_signature(core_func_index)?;
1171 core_func_index += 1;
1172 LocalInitializer::ThreadSuspend { func, cancellable }
1173 }
1174 wasmparser::CanonicalFunction::ThreadSuspendTo { cancellable } => {
1175 let func = self.core_func_signature(core_func_index)?;
1176 core_func_index += 1;
1177 LocalInitializer::ThreadSuspendTo { func, cancellable }
1178 }
1179 wasmparser::CanonicalFunction::ThreadUnsuspend => {
1180 let func = self.core_func_signature(core_func_index)?;
1181 core_func_index += 1;
1182 LocalInitializer::ThreadUnsuspend { func }
1183 }
1184 wasmparser::CanonicalFunction::ThreadYieldToSuspended { cancellable } => {
1185 let func = self.core_func_signature(core_func_index)?;
1186 core_func_index += 1;
1187 LocalInitializer::ThreadYieldToSuspended { func, cancellable }
1188 }
1189 };
1190 self.result.initializers.push(init);
1191 }
1192 }
1193
1194 Payload::ModuleSection {
1203 parser,
1204 unchecked_range,
1205 } => {
1206 let index = self.validator.types(0).unwrap().module_count();
1207 self.validator.module_section(&unchecked_range)?;
1208 let static_module_index = self.static_modules.next_key();
1209 let mut translation = ModuleEnvironment::new(
1210 self.tunables,
1211 self.validator,
1212 self.types.module_types_builder(),
1213 static_module_index,
1214 )
1215 .translate(
1216 parser,
1217 component
1218 .get(unchecked_range.start..unchecked_range.end)
1219 .ok_or_else(|| {
1220 format_err!(
1221 "section range {}..{} is out of bounds (bound = {})",
1222 unchecked_range.start,
1223 unchecked_range.end,
1224 component.len()
1225 )
1226 .context("wasm component contains an invalid module section")
1227 })?,
1228 )?;
1229
1230 translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap();
1231 let static_module_index2 = self.static_modules.push(translation);
1232 assert_eq!(static_module_index, static_module_index2);
1233 let types = self.validator.types(0).unwrap();
1234 let ty = types.module_at(index);
1235 self.result
1236 .initializers
1237 .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1238 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1239 }
1240
1241 Payload::ComponentSection {
1250 parser,
1251 unchecked_range,
1252 } => {
1253 self.validator.component_section(&unchecked_range)?;
1254 self.lexical_scopes.push(LexicalScope {
1255 parser: mem::replace(&mut self.parser, parser),
1256 translation: mem::take(&mut self.result),
1257 closure_args: ClosedOverVars::default(),
1258 });
1259 }
1260
1261 Payload::InstanceSection(s) => {
1266 self.validator.instance_section(&s)?;
1267 for instance in s {
1268 let init = match instance? {
1269 wasmparser::Instance::Instantiate { module_index, args } => {
1270 let index = ModuleIndex::from_u32(module_index);
1271 self.instantiate_module(index, &args)
1272 }
1273 wasmparser::Instance::FromExports(exports) => {
1274 self.instantiate_module_from_exports(&exports)
1275 }
1276 };
1277 self.result.initializers.push(init);
1278 }
1279 }
1280 Payload::ComponentInstanceSection(s) => {
1281 let mut index = self.validator.types(0).unwrap().component_instance_count();
1282 self.validator.component_instance_section(&s)?;
1283 for instance in s {
1284 let types = self.validator.types(0).unwrap();
1285 let ty = types.component_instance_at(index);
1286 let init = match instance? {
1287 wasmparser::ComponentInstance::Instantiate {
1288 component_index,
1289 args,
1290 } => {
1291 let index = ComponentIndex::from_u32(component_index);
1292 self.instantiate_component(index, &args, ty)?
1293 }
1294 wasmparser::ComponentInstance::FromExports(exports) => {
1295 self.instantiate_component_from_exports(&exports, ty)?
1296 }
1297 };
1298 self.result.initializers.push(init);
1299 index += 1;
1300 }
1301 }
1302
1303 Payload::ComponentExportSection(s) => {
1309 self.validator.component_export_section(&s)?;
1310 for export in s {
1311 let export = export?;
1312 let item = self.kind_to_item(export.kind, export.index)?;
1313 let prev = self.result.exports.insert(export.name.name, item);
1314 assert!(prev.is_none());
1315 self.result
1316 .initializers
1317 .push(LocalInitializer::Export(item));
1318 }
1319 }
1320
1321 Payload::ComponentStartSection { start, range } => {
1322 self.validator.component_start_section(&start, &range)?;
1323 unimplemented!("component start section");
1324 }
1325
1326 Payload::ComponentAliasSection(s) => {
1330 self.validator.component_alias_section(&s)?;
1331 for alias in s {
1332 let init = match alias? {
1333 wasmparser::ComponentAlias::InstanceExport {
1334 kind: _,
1335 instance_index,
1336 name,
1337 } => {
1338 let instance = ComponentInstanceIndex::from_u32(instance_index);
1339 LocalInitializer::AliasComponentExport(instance, name)
1340 }
1341 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1342 self.alias_component_outer(kind, count, index);
1343 continue;
1344 }
1345 wasmparser::ComponentAlias::CoreInstanceExport {
1346 kind,
1347 instance_index,
1348 name,
1349 } => {
1350 let instance = ModuleInstanceIndex::from_u32(instance_index);
1351 self.alias_module_instance_export(kind, instance, name)
1352 }
1353 };
1354 self.result.initializers.push(init);
1355 }
1356 }
1357
1358 Payload::CustomSection { .. } => {}
1363
1364 other => {
1370 self.validator.payload(&other)?;
1371 panic!("unimplemented section {other:?}");
1372 }
1373 }
1374
1375 Ok(Action::KeepGoing)
1376 }
1377
1378 fn instantiate_module(
1379 &mut self,
1380 module: ModuleIndex,
1381 raw_args: &[wasmparser::InstantiationArg<'data>],
1382 ) -> LocalInitializer<'data> {
1383 let mut args = HashMap::with_capacity(raw_args.len());
1384 for arg in raw_args {
1385 match arg.kind {
1386 wasmparser::InstantiationArgKind::Instance => {
1387 let idx = ModuleInstanceIndex::from_u32(arg.index);
1388 args.insert(arg.name, idx);
1389 }
1390 }
1391 }
1392 LocalInitializer::ModuleInstantiate(module, args)
1393 }
1394
1395 fn instantiate_module_from_exports(
1398 &mut self,
1399 exports: &[wasmparser::Export<'data>],
1400 ) -> LocalInitializer<'data> {
1401 let mut map = HashMap::with_capacity(exports.len());
1402 for export in exports {
1403 let idx = match export.kind {
1404 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1405 let index = FuncIndex::from_u32(export.index);
1406 EntityIndex::Function(index)
1407 }
1408 wasmparser::ExternalKind::Table => {
1409 let index = TableIndex::from_u32(export.index);
1410 EntityIndex::Table(index)
1411 }
1412 wasmparser::ExternalKind::Memory => {
1413 let index = MemoryIndex::from_u32(export.index);
1414 EntityIndex::Memory(index)
1415 }
1416 wasmparser::ExternalKind::Global => {
1417 let index = GlobalIndex::from_u32(export.index);
1418 EntityIndex::Global(index)
1419 }
1420 wasmparser::ExternalKind::Tag => {
1421 let index = TagIndex::from_u32(export.index);
1422 EntityIndex::Tag(index)
1423 }
1424 };
1425 map.insert(export.name, idx);
1426 }
1427 LocalInitializer::ModuleSynthetic(map)
1428 }
1429
1430 fn instantiate_component(
1431 &mut self,
1432 component: ComponentIndex,
1433 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1434 ty: ComponentInstanceTypeId,
1435 ) -> Result<LocalInitializer<'data>> {
1436 let mut args = HashMap::with_capacity(raw_args.len());
1437 for arg in raw_args {
1438 let idx = self.kind_to_item(arg.kind, arg.index)?;
1439 args.insert(arg.name, idx);
1440 }
1441
1442 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1443 }
1444
1445 fn instantiate_component_from_exports(
1448 &mut self,
1449 exports: &[wasmparser::ComponentExport<'data>],
1450 ty: ComponentInstanceTypeId,
1451 ) -> Result<LocalInitializer<'data>> {
1452 let mut map = HashMap::with_capacity(exports.len());
1453 for export in exports {
1454 let idx = self.kind_to_item(export.kind, export.index)?;
1455 map.insert(export.name.name, idx);
1456 }
1457
1458 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1459 }
1460
1461 fn kind_to_item(
1462 &mut self,
1463 kind: wasmparser::ComponentExternalKind,
1464 index: u32,
1465 ) -> Result<ComponentItem> {
1466 Ok(match kind {
1467 wasmparser::ComponentExternalKind::Func => {
1468 let index = ComponentFuncIndex::from_u32(index);
1469 ComponentItem::Func(index)
1470 }
1471 wasmparser::ComponentExternalKind::Module => {
1472 let index = ModuleIndex::from_u32(index);
1473 ComponentItem::Module(index)
1474 }
1475 wasmparser::ComponentExternalKind::Instance => {
1476 let index = ComponentInstanceIndex::from_u32(index);
1477 ComponentItem::ComponentInstance(index)
1478 }
1479 wasmparser::ComponentExternalKind::Component => {
1480 let index = ComponentIndex::from_u32(index);
1481 ComponentItem::Component(index)
1482 }
1483 wasmparser::ComponentExternalKind::Value => {
1484 unimplemented!("component values");
1485 }
1486 wasmparser::ComponentExternalKind::Type => {
1487 let types = self.validator.types(0).unwrap();
1488 let ty = types.component_any_type_at(index);
1489 ComponentItem::Type(ty)
1490 }
1491 })
1492 }
1493
1494 fn alias_module_instance_export(
1495 &mut self,
1496 kind: wasmparser::ExternalKind,
1497 instance: ModuleInstanceIndex,
1498 name: &'data str,
1499 ) -> LocalInitializer<'data> {
1500 match kind {
1501 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1502 LocalInitializer::AliasExportFunc(instance, name)
1503 }
1504 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1505 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1506 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1507 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1508 }
1509 }
1510
1511 fn alias_component_outer(
1512 &mut self,
1513 kind: wasmparser::ComponentOuterAliasKind,
1514 count: u32,
1515 index: u32,
1516 ) {
1517 match kind {
1518 wasmparser::ComponentOuterAliasKind::CoreType
1519 | wasmparser::ComponentOuterAliasKind::Type => {}
1520
1521 wasmparser::ComponentOuterAliasKind::CoreModule => {
1528 let index = ModuleIndex::from_u32(index);
1529 let mut module = ClosedOverModule::Local(index);
1530 let depth = self.lexical_scopes.len() - (count as usize);
1531 for frame in self.lexical_scopes[depth..].iter_mut() {
1532 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1533 }
1534
1535 self.result
1540 .initializers
1541 .push(LocalInitializer::AliasModule(module));
1542 }
1543 wasmparser::ComponentOuterAliasKind::Component => {
1544 let index = ComponentIndex::from_u32(index);
1545 let mut component = ClosedOverComponent::Local(index);
1546 let depth = self.lexical_scopes.len() - (count as usize);
1547 for frame in self.lexical_scopes[depth..].iter_mut() {
1548 component =
1549 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1550 }
1551
1552 self.result
1553 .initializers
1554 .push(LocalInitializer::AliasComponent(component));
1555 }
1556 }
1557 }
1558
1559 fn canonical_options(
1560 &mut self,
1561 opts: &[wasmparser::CanonicalOption],
1562 core_func_index: u32,
1563 ) -> WasmResult<LocalCanonicalOptions> {
1564 let core_type = self.core_func_signature(core_func_index)?;
1565
1566 let mut string_encoding = StringEncoding::Utf8;
1567 let mut post_return = None;
1568 let mut async_ = false;
1569 let mut callback = None;
1570 let mut memory = None;
1571 let mut realloc = None;
1572 let mut gc = false;
1573
1574 for opt in opts {
1575 match opt {
1576 wasmparser::CanonicalOption::UTF8 => {
1577 string_encoding = StringEncoding::Utf8;
1578 }
1579 wasmparser::CanonicalOption::UTF16 => {
1580 string_encoding = StringEncoding::Utf16;
1581 }
1582 wasmparser::CanonicalOption::CompactUTF16 => {
1583 string_encoding = StringEncoding::CompactUtf16;
1584 }
1585 wasmparser::CanonicalOption::Memory(idx) => {
1586 let idx = MemoryIndex::from_u32(*idx);
1587 memory = Some(idx);
1588 }
1589 wasmparser::CanonicalOption::Realloc(idx) => {
1590 let idx = FuncIndex::from_u32(*idx);
1591 realloc = Some(idx);
1592 }
1593 wasmparser::CanonicalOption::PostReturn(idx) => {
1594 let idx = FuncIndex::from_u32(*idx);
1595 post_return = Some(idx);
1596 }
1597 wasmparser::CanonicalOption::Async => async_ = true,
1598 wasmparser::CanonicalOption::Callback(idx) => {
1599 let idx = FuncIndex::from_u32(*idx);
1600 callback = Some(idx);
1601 }
1602 wasmparser::CanonicalOption::CoreType(idx) => {
1603 if cfg!(debug_assertions) {
1604 let types = self.validator.types(0).unwrap();
1605 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1606 let interned = self
1607 .types
1608 .module_types_builder()
1609 .intern_type(types, core_ty_id)?;
1610 debug_assert_eq!(interned, core_type);
1611 }
1612 }
1613 wasmparser::CanonicalOption::Gc => {
1614 gc = true;
1615 }
1616 }
1617 }
1618
1619 Ok(LocalCanonicalOptions {
1620 string_encoding,
1621 post_return,
1622 cancellable: false,
1623 async_,
1624 callback,
1625 core_type,
1626 data_model: if gc {
1627 LocalDataModel::Gc {}
1628 } else {
1629 LocalDataModel::LinearMemory { memory, realloc }
1630 },
1631 })
1632 }
1633
1634 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1636 let types = self.validator.types(0).unwrap();
1637 let id = types.core_function_at(index);
1638 self.types.module_types_builder().intern_type(types, id)
1639 }
1640
1641 fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1642 self.lexical_scopes.is_empty()
1643 && self
1644 .unsafe_intrinsics_import
1645 .is_some_and(|name| import == name)
1646 }
1647
1648 fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1649 let types = &self.validator.types(0).unwrap();
1650
1651 let ComponentEntityType::Instance(instance_ty) = ty else {
1652 bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1653 };
1654 let instance_ty = &types[instance_ty];
1655
1656 ensure!(
1657 instance_ty.defined_resources.is_empty(),
1658 "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1659 );
1660 ensure!(
1661 instance_ty.explicit_resources.is_empty(),
1662 "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1663 );
1664
1665 for (name, ty) in &instance_ty.exports {
1666 let ComponentEntityType::Func(func_ty) = ty.ty else {
1667 bail!(
1668 "bad unsafe intrinsics import: imported instance `{import}` must \
1669 only export functions"
1670 )
1671 };
1672 let func_ty = &types[func_ty];
1673
1674 fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1675 use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1676 match (a, b) {
1677 (InterfaceType::U8, C::Primitive(P::U8)) => true,
1678 (InterfaceType::U8, _) => false,
1679
1680 (InterfaceType::U16, C::Primitive(P::U16)) => true,
1681 (InterfaceType::U16, _) => false,
1682
1683 (InterfaceType::U32, C::Primitive(P::U32)) => true,
1684 (InterfaceType::U32, _) => false,
1685
1686 (InterfaceType::U64, C::Primitive(P::U64)) => true,
1687 (InterfaceType::U64, _) => false,
1688
1689 (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1690 }
1691 }
1692
1693 fn check_types<'a>(
1694 expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1695 actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1696 kind: &str,
1697 import: &str,
1698 name: &str,
1699 ) -> Result<()> {
1700 let expected_len = expected.len();
1701 let actual_len = actual.len();
1702 ensure!(
1703 expected_len == actual_len,
1704 "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1705 {expected_len} {kind}, found {actual_len}"
1706 );
1707
1708 for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1709 ensure!(
1710 ty_eq(expected_ty, actual_ty),
1711 "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1712 `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1713 );
1714 }
1715 Ok(())
1716 }
1717
1718 let intrinsic = UnsafeIntrinsic::from_str(name)
1719 .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1720
1721 check_types(
1722 intrinsic.component_params().iter(),
1723 func_ty.params.iter().map(|(_name, ty)| ty),
1724 "parameters",
1725 &import,
1726 &name,
1727 )?;
1728 check_types(
1729 intrinsic.component_results().iter(),
1730 func_ty.result.iter(),
1731 "results",
1732 &import,
1733 &name,
1734 )?;
1735 }
1736
1737 Ok(())
1738 }
1739}
1740
1741impl Translation<'_> {
1742 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1743 self.types.as_ref().unwrap().as_ref()
1744 }
1745}
1746
1747mod pre_inlining {
1759 use super::*;
1760
1761 pub struct PreInliningComponentTypes<'a> {
1762 types: &'a mut ComponentTypesBuilder,
1763 }
1764
1765 impl<'a> PreInliningComponentTypes<'a> {
1766 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1767 Self { types }
1768 }
1769
1770 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1771 self.types.module_types_builder_mut()
1772 }
1773
1774 pub fn types(&self) -> &ComponentTypesBuilder {
1775 self.types
1776 }
1777
1778 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1781 self.types
1782 }
1783 }
1784
1785 impl TypeConvert for PreInliningComponentTypes<'_> {
1786 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1787 self.types.lookup_heap_type(index)
1788 }
1789
1790 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1791 self.types.lookup_type_index(index)
1792 }
1793 }
1794}
1795use pre_inlining::PreInliningComponentTypes;