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