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