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 _ => continue,
639 },
640
641 CoreDef::UnsafeIntrinsic(i) => FuncKey::UnsafeIntrinsic(Abi::Wasm, *i).into(),
645
646 CoreDef::Export(export) => {
650 let Some(arg_module) = &instance_to_module[export.instance].expand() else {
651 continue;
656 };
657
658 let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
659 else {
660 unreachable!("function imports must be functions")
661 };
662
663 let Some(arg_module_def_func) = self.static_modules[*arg_module]
664 .module
665 .defined_func_index(*arg_func)
666 else {
667 continue;
674 };
675
676 FuncKey::DefinedWasmFunction(*arg_module, arg_module_def_func).into()
677 }
678 };
679
680 assert!(
681 self.static_modules[module].known_imported_functions[imported_func].is_none()
682 );
683 self.static_modules[module].known_imported_functions[imported_func] =
684 Some(known_func);
685 }
686 }
687 }
688
689 fn translate_payload(
690 &mut self,
691 payload: Payload<'data>,
692 component: &'data [u8],
693 ) -> Result<Action> {
694 match payload {
695 Payload::Version {
696 num,
697 encoding,
698 range,
699 } => {
700 self.validator.version(num, encoding, &range)?;
701
702 match encoding {
703 Encoding::Component => {}
704 Encoding::Module => {
705 bail!("attempted to parse a wasm module with a component parser");
706 }
707 }
708 }
709
710 Payload::End(offset) => {
711 assert!(self.result.types.is_none());
712 self.result.types = Some(self.validator.end(offset)?);
713
714 let LexicalScope {
719 parser,
720 translation,
721 closure_args,
722 } = match self.lexical_scopes.pop() {
723 Some(frame) => frame,
724 None => return Ok(Action::Done),
725 };
726 self.parser = parser;
727 let component = mem::replace(&mut self.result, translation);
728 let static_idx = self.static_components.push(component);
729 self.result
730 .initializers
731 .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
732 }
733
734 Payload::ComponentTypeSection(s) => {
743 let mut component_type_index =
744 self.validator.types(0).unwrap().component_type_count();
745 self.validator.component_type_section(&s)?;
746
747 let types = self.validator.types(0).unwrap();
751 for ty in s {
752 match ty? {
753 wasmparser::ComponentType::Resource { rep, dtor } => {
754 let rep = self.types.convert_valtype(rep)?;
755 let id = types
756 .component_any_type_at(component_type_index)
757 .unwrap_resource();
758 let dtor = dtor.map(FuncIndex::from_u32);
759 self.result
760 .initializers
761 .push(LocalInitializer::Resource(id, rep, dtor));
762 }
763
764 wasmparser::ComponentType::Defined(_)
766 | wasmparser::ComponentType::Func(_)
767 | wasmparser::ComponentType::Instance(_)
768 | wasmparser::ComponentType::Component(_) => {}
769 }
770
771 component_type_index += 1;
772 }
773 }
774 Payload::CoreTypeSection(s) => {
775 self.validator.core_type_section(&s)?;
776 }
777
778 Payload::ComponentImportSection(s) => {
782 self.validator.component_import_section(&s)?;
783 for import in s {
784 let import = import?;
785 let types = self.validator.types(0).unwrap();
786 let ty = types
787 .component_item_for_import(import.name.name)
788 .unwrap()
789 .ty;
790
791 if self.is_unsafe_intrinsics_import(import.name.name) {
792 self.check_unsafe_intrinsics_import(import.name.name, ty)?;
793 self.result
794 .initializers
795 .push(LocalInitializer::IntrinsicsImport);
796 } else {
797 self.result
798 .initializers
799 .push(LocalInitializer::Import(import.name, ty));
800 }
801 }
802 }
803
804 Payload::ComponentCanonicalSection(s) => {
807 let types = self.validator.types(0).unwrap();
808 let mut core_func_index = types.function_count();
809 self.validator.component_canonical_section(&s)?;
810 for func in s {
811 let init = match func? {
812 wasmparser::CanonicalFunction::Lift {
813 type_index,
814 core_func_index,
815 options,
816 } => {
817 let ty = self
818 .validator
819 .types(0)
820 .unwrap()
821 .component_any_type_at(type_index)
822 .unwrap_func();
823
824 let func = FuncIndex::from_u32(core_func_index);
825 let options = self.canonical_options(&options, core_func_index)?;
826 LocalInitializer::Lift(ty, func, options)
827 }
828 wasmparser::CanonicalFunction::Lower {
829 func_index,
830 options,
831 } => {
832 let lower_ty = self
833 .validator
834 .types(0)
835 .unwrap()
836 .component_function_at(func_index);
837 let func = ComponentFuncIndex::from_u32(func_index);
838 let options = self.canonical_options(&options, core_func_index)?;
839 core_func_index += 1;
840 LocalInitializer::Lower {
841 func,
842 options,
843 lower_ty,
844 }
845 }
846 wasmparser::CanonicalFunction::ResourceNew { resource } => {
847 let resource = self
848 .validator
849 .types(0)
850 .unwrap()
851 .component_any_type_at(resource)
852 .unwrap_resource();
853 let ty = self.core_func_signature(core_func_index)?;
854 core_func_index += 1;
855 LocalInitializer::ResourceNew(resource, ty)
856 }
857 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
858 let resource = self
859 .validator
860 .types(0)
861 .unwrap()
862 .component_any_type_at(resource)
863 .unwrap_resource();
864 let ty = self.core_func_signature(core_func_index)?;
865 core_func_index += 1;
866 LocalInitializer::ResourceDrop(resource, ty)
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::SubtaskDrop => {
974 let func = self.core_func_signature(core_func_index)?;
975 core_func_index += 1;
976 LocalInitializer::SubtaskDrop { func }
977 }
978 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
979 let func = self.core_func_signature(core_func_index)?;
980 core_func_index += 1;
981 LocalInitializer::SubtaskCancel { func, async_ }
982 }
983 wasmparser::CanonicalFunction::StreamNew { ty } => {
984 let ty = self
985 .validator
986 .types(0)
987 .unwrap()
988 .component_defined_type_at(ty);
989 let func = self.core_func_signature(core_func_index)?;
990 core_func_index += 1;
991 LocalInitializer::StreamNew { ty, func }
992 }
993 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
994 let ty = self
995 .validator
996 .types(0)
997 .unwrap()
998 .component_defined_type_at(ty);
999 let options = self.canonical_options(&options, core_func_index)?;
1000 core_func_index += 1;
1001 LocalInitializer::StreamRead { ty, options }
1002 }
1003 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
1004 let ty = self
1005 .validator
1006 .types(0)
1007 .unwrap()
1008 .component_defined_type_at(ty);
1009 let options = self.canonical_options(&options, core_func_index)?;
1010 core_func_index += 1;
1011 LocalInitializer::StreamWrite { ty, options }
1012 }
1013 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1014 let ty = self
1015 .validator
1016 .types(0)
1017 .unwrap()
1018 .component_defined_type_at(ty);
1019 let func = self.core_func_signature(core_func_index)?;
1020 core_func_index += 1;
1021 LocalInitializer::StreamCancelRead { ty, func, async_ }
1022 }
1023 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1024 let ty = self
1025 .validator
1026 .types(0)
1027 .unwrap()
1028 .component_defined_type_at(ty);
1029 let func = self.core_func_signature(core_func_index)?;
1030 core_func_index += 1;
1031 LocalInitializer::StreamCancelWrite { ty, func, async_ }
1032 }
1033 wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1034 let ty = self
1035 .validator
1036 .types(0)
1037 .unwrap()
1038 .component_defined_type_at(ty);
1039 let func = self.core_func_signature(core_func_index)?;
1040 core_func_index += 1;
1041 LocalInitializer::StreamDropReadable { ty, func }
1042 }
1043 wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1044 let ty = self
1045 .validator
1046 .types(0)
1047 .unwrap()
1048 .component_defined_type_at(ty);
1049 let func = self.core_func_signature(core_func_index)?;
1050 core_func_index += 1;
1051 LocalInitializer::StreamDropWritable { ty, func }
1052 }
1053 wasmparser::CanonicalFunction::FutureNew { ty } => {
1054 let ty = self
1055 .validator
1056 .types(0)
1057 .unwrap()
1058 .component_defined_type_at(ty);
1059 let func = self.core_func_signature(core_func_index)?;
1060 core_func_index += 1;
1061 LocalInitializer::FutureNew { ty, func }
1062 }
1063 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1064 let ty = self
1065 .validator
1066 .types(0)
1067 .unwrap()
1068 .component_defined_type_at(ty);
1069 let options = self.canonical_options(&options, core_func_index)?;
1070 core_func_index += 1;
1071 LocalInitializer::FutureRead { ty, options }
1072 }
1073 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1074 let ty = self
1075 .validator
1076 .types(0)
1077 .unwrap()
1078 .component_defined_type_at(ty);
1079 let options = self.canonical_options(&options, core_func_index)?;
1080 core_func_index += 1;
1081 LocalInitializer::FutureWrite { ty, options }
1082 }
1083 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1084 let ty = self
1085 .validator
1086 .types(0)
1087 .unwrap()
1088 .component_defined_type_at(ty);
1089 let func = self.core_func_signature(core_func_index)?;
1090 core_func_index += 1;
1091 LocalInitializer::FutureCancelRead { ty, func, async_ }
1092 }
1093 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1094 let ty = self
1095 .validator
1096 .types(0)
1097 .unwrap()
1098 .component_defined_type_at(ty);
1099 let func = self.core_func_signature(core_func_index)?;
1100 core_func_index += 1;
1101 LocalInitializer::FutureCancelWrite { ty, func, async_ }
1102 }
1103 wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1104 let ty = self
1105 .validator
1106 .types(0)
1107 .unwrap()
1108 .component_defined_type_at(ty);
1109 let func = self.core_func_signature(core_func_index)?;
1110 core_func_index += 1;
1111 LocalInitializer::FutureDropReadable { ty, func }
1112 }
1113 wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1114 let ty = self
1115 .validator
1116 .types(0)
1117 .unwrap()
1118 .component_defined_type_at(ty);
1119 let func = self.core_func_signature(core_func_index)?;
1120 core_func_index += 1;
1121 LocalInitializer::FutureDropWritable { ty, func }
1122 }
1123 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1124 let options = self.canonical_options(&options, core_func_index)?;
1125 core_func_index += 1;
1126 LocalInitializer::ErrorContextNew { options }
1127 }
1128 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1129 let options = self.canonical_options(&options, core_func_index)?;
1130 core_func_index += 1;
1131 LocalInitializer::ErrorContextDebugMessage { options }
1132 }
1133 wasmparser::CanonicalFunction::ErrorContextDrop => {
1134 let func = self.core_func_signature(core_func_index)?;
1135 core_func_index += 1;
1136 LocalInitializer::ErrorContextDrop { func }
1137 }
1138 wasmparser::CanonicalFunction::ContextGet { slot, ty } => {
1139 if ty != wasmparser::ValType::I32 {
1140 bail!("unsupported context.get type: {ty:?}");
1141 }
1142 let func = self.core_func_signature(core_func_index)?;
1143 core_func_index += 1;
1144 LocalInitializer::ContextGet { i: slot, func }
1145 }
1146 wasmparser::CanonicalFunction::ContextSet { slot, ty } => {
1147 if ty != wasmparser::ValType::I32 {
1148 bail!("unsupported context.set type: {ty:?}");
1149 }
1150 let func = self.core_func_signature(core_func_index)?;
1151 core_func_index += 1;
1152 LocalInitializer::ContextSet { i: slot, func }
1153 }
1154 wasmparser::CanonicalFunction::ThreadIndex => {
1155 let func = self.core_func_signature(core_func_index)?;
1156 core_func_index += 1;
1157 LocalInitializer::ThreadIndex { func }
1158 }
1159 wasmparser::CanonicalFunction::ThreadNewIndirect {
1160 func_ty_index,
1161 table_index,
1162 } => {
1163 let func = self.core_func_signature(core_func_index)?;
1164 core_func_index += 1;
1165 LocalInitializer::ThreadNewIndirect {
1166 func,
1167 start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1168 start_func_table_index: TableIndex::from_u32(table_index),
1169 }
1170 }
1171 wasmparser::CanonicalFunction::ThreadResumeLater => {
1172 let func = self.core_func_signature(core_func_index)?;
1173 core_func_index += 1;
1174 LocalInitializer::ThreadResumeLater { func }
1175 }
1176 wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1177 let func = self.core_func_signature(core_func_index)?;
1178 core_func_index += 1;
1179 LocalInitializer::ThreadSuspend { func, cancellable }
1180 }
1181 wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
1182 let func = self.core_func_signature(core_func_index)?;
1183 core_func_index += 1;
1184 LocalInitializer::ThreadYield { func, cancellable }
1185 }
1186 wasmparser::CanonicalFunction::ThreadSuspendThenResume { cancellable } => {
1187 let func = self.core_func_signature(core_func_index)?;
1188 core_func_index += 1;
1189 LocalInitializer::ThreadSuspendThenResume { func, cancellable }
1190 }
1191 wasmparser::CanonicalFunction::ThreadYieldThenResume { cancellable } => {
1192 let func = self.core_func_signature(core_func_index)?;
1193 core_func_index += 1;
1194 LocalInitializer::ThreadYieldThenResume { func, cancellable }
1195 }
1196 wasmparser::CanonicalFunction::ThreadSuspendThenPromote { cancellable } => {
1197 let func = self.core_func_signature(core_func_index)?;
1198 core_func_index += 1;
1199 LocalInitializer::ThreadSuspendThenPromote { func, cancellable }
1200 }
1201 wasmparser::CanonicalFunction::ThreadYieldThenPromote { cancellable } => {
1202 let func = self.core_func_signature(core_func_index)?;
1203 core_func_index += 1;
1204 LocalInitializer::ThreadYieldThenPromote { func, cancellable }
1205 }
1206 };
1207 self.result.initializers.push(init);
1208 }
1209 }
1210
1211 Payload::ModuleSection {
1220 parser,
1221 unchecked_range,
1222 } => {
1223 let index = self.validator.types(0).unwrap().module_count();
1224 self.validator.module_section(&unchecked_range)?;
1225 let static_module_index = self.static_modules.next_key();
1226 let mut translation = ModuleEnvironment::new(
1227 self.tunables,
1228 self.validator,
1229 self.types.module_types_builder(),
1230 static_module_index,
1231 )
1232 .translate(
1233 parser,
1234 component
1235 .get(unchecked_range.start..unchecked_range.end)
1236 .ok_or_else(|| {
1237 format_err!(
1238 "section range {}..{} is out of bounds (bound = {})",
1239 unchecked_range.start,
1240 unchecked_range.end,
1241 component.len()
1242 )
1243 .context("wasm component contains an invalid module section")
1244 })?,
1245 )?;
1246
1247 translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap();
1248 let static_module_index2 = self.static_modules.push(translation);
1249 assert_eq!(static_module_index, static_module_index2);
1250 let types = self.validator.types(0).unwrap();
1251 let ty = types.module_at(index);
1252 self.result
1253 .initializers
1254 .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1255 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1256 }
1257
1258 Payload::ComponentSection {
1267 parser,
1268 unchecked_range,
1269 } => {
1270 self.validator.component_section(&unchecked_range)?;
1271 self.lexical_scopes.push(LexicalScope {
1272 parser: mem::replace(&mut self.parser, parser),
1273 translation: mem::take(&mut self.result),
1274 closure_args: ClosedOverVars::default(),
1275 });
1276 }
1277
1278 Payload::InstanceSection(s) => {
1283 self.validator.instance_section(&s)?;
1284 for instance in s {
1285 let init = match instance? {
1286 wasmparser::Instance::Instantiate { module_index, args } => {
1287 let index = ModuleIndex::from_u32(module_index);
1288 self.instantiate_module(index, &args)
1289 }
1290 wasmparser::Instance::FromExports(exports) => {
1291 self.instantiate_module_from_exports(&exports)
1292 }
1293 };
1294 self.result.initializers.push(init);
1295 }
1296 }
1297 Payload::ComponentInstanceSection(s) => {
1298 let mut index = self.validator.types(0).unwrap().component_instance_count();
1299 self.validator.component_instance_section(&s)?;
1300 for instance in s {
1301 let types = self.validator.types(0).unwrap();
1302 let ty = types.component_instance_at(index);
1303 let init = match instance? {
1304 wasmparser::ComponentInstance::Instantiate {
1305 component_index,
1306 args,
1307 } => {
1308 let index = ComponentIndex::from_u32(component_index);
1309 self.instantiate_component(index, &args, ty)?
1310 }
1311 wasmparser::ComponentInstance::FromExports(exports) => {
1312 self.instantiate_component_from_exports(&exports, ty)?
1313 }
1314 };
1315 self.result.initializers.push(init);
1316 index += 1;
1317 }
1318 }
1319
1320 Payload::ComponentExportSection(s) => {
1326 self.validator.component_export_section(&s)?;
1327 for export in s {
1328 let export = export?;
1329 let item = self.kind_to_item(export.kind, export.index)?;
1330 let prev = self
1331 .result
1332 .exports
1333 .insert(export.name.name, (item, export.name));
1334 assert!(prev.is_none());
1335 self.result
1336 .initializers
1337 .push(LocalInitializer::Export(item));
1338 }
1339 }
1340
1341 Payload::ComponentStartSection { start, range } => {
1342 self.validator.component_start_section(&start, &range)?;
1343 unimplemented!("component start section");
1344 }
1345
1346 Payload::ComponentAliasSection(s) => {
1350 self.validator.component_alias_section(&s)?;
1351 for alias in s {
1352 let init = match alias? {
1353 wasmparser::ComponentAlias::InstanceExport {
1354 kind: _,
1355 instance_index,
1356 name,
1357 } => {
1358 let instance = ComponentInstanceIndex::from_u32(instance_index);
1359 LocalInitializer::AliasComponentExport(instance, name)
1360 }
1361 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1362 self.alias_component_outer(kind, count, index);
1363 continue;
1364 }
1365 wasmparser::ComponentAlias::CoreInstanceExport {
1366 kind,
1367 instance_index,
1368 name,
1369 } => {
1370 let instance = ModuleInstanceIndex::from_u32(instance_index);
1371 self.alias_module_instance_export(kind, instance, name)
1372 }
1373 };
1374 self.result.initializers.push(init);
1375 }
1376 }
1377
1378 Payload::CustomSection { .. } => {}
1383
1384 other => {
1390 self.validator.payload(&other)?;
1391 panic!("unimplemented section {other:?}");
1392 }
1393 }
1394
1395 Ok(Action::KeepGoing)
1396 }
1397
1398 fn instantiate_module(
1399 &mut self,
1400 module: ModuleIndex,
1401 raw_args: &[wasmparser::InstantiationArg<'data>],
1402 ) -> LocalInitializer<'data> {
1403 let mut args = HashMap::with_capacity(raw_args.len());
1404 for arg in raw_args {
1405 match arg.kind {
1406 wasmparser::InstantiationArgKind::Instance => {
1407 let idx = ModuleInstanceIndex::from_u32(arg.index);
1408 args.insert(arg.name, idx);
1409 }
1410 }
1411 }
1412 LocalInitializer::ModuleInstantiate(module, args)
1413 }
1414
1415 fn instantiate_module_from_exports(
1418 &mut self,
1419 exports: &[wasmparser::Export<'data>],
1420 ) -> LocalInitializer<'data> {
1421 let mut map = HashMap::with_capacity(exports.len());
1422 for export in exports {
1423 let idx = match export.kind {
1424 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1425 let index = FuncIndex::from_u32(export.index);
1426 EntityIndex::Function(index)
1427 }
1428 wasmparser::ExternalKind::Table => {
1429 let index = TableIndex::from_u32(export.index);
1430 EntityIndex::Table(index)
1431 }
1432 wasmparser::ExternalKind::Memory => {
1433 let index = MemoryIndex::from_u32(export.index);
1434 EntityIndex::Memory(index)
1435 }
1436 wasmparser::ExternalKind::Global => {
1437 let index = GlobalIndex::from_u32(export.index);
1438 EntityIndex::Global(index)
1439 }
1440 wasmparser::ExternalKind::Tag => {
1441 let index = TagIndex::from_u32(export.index);
1442 EntityIndex::Tag(index)
1443 }
1444 };
1445 map.insert(export.name, idx);
1446 }
1447 LocalInitializer::ModuleSynthetic(map)
1448 }
1449
1450 fn instantiate_component(
1451 &mut self,
1452 component: ComponentIndex,
1453 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1454 ty: ComponentInstanceTypeId,
1455 ) -> Result<LocalInitializer<'data>> {
1456 let mut args = HashMap::with_capacity(raw_args.len());
1457 for arg in raw_args {
1458 let idx = self.kind_to_item(arg.kind, arg.index)?;
1459 args.insert(arg.name, idx);
1460 }
1461
1462 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1463 }
1464
1465 fn instantiate_component_from_exports(
1468 &mut self,
1469 exports: &[wasmparser::ComponentExport<'data>],
1470 ty: ComponentInstanceTypeId,
1471 ) -> Result<LocalInitializer<'data>> {
1472 let mut map = HashMap::with_capacity(exports.len());
1473 for export in exports {
1474 let idx = self.kind_to_item(export.kind, export.index)?;
1475 map.insert(export.name.name, (idx, export.name));
1476 }
1477
1478 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1479 }
1480
1481 fn kind_to_item(
1482 &mut self,
1483 kind: wasmparser::ComponentExternalKind,
1484 index: u32,
1485 ) -> Result<ComponentItem> {
1486 Ok(match kind {
1487 wasmparser::ComponentExternalKind::Func => {
1488 let index = ComponentFuncIndex::from_u32(index);
1489 ComponentItem::Func(index)
1490 }
1491 wasmparser::ComponentExternalKind::Module => {
1492 let index = ModuleIndex::from_u32(index);
1493 ComponentItem::Module(index)
1494 }
1495 wasmparser::ComponentExternalKind::Instance => {
1496 let index = ComponentInstanceIndex::from_u32(index);
1497 ComponentItem::ComponentInstance(index)
1498 }
1499 wasmparser::ComponentExternalKind::Component => {
1500 let index = ComponentIndex::from_u32(index);
1501 ComponentItem::Component(index)
1502 }
1503 wasmparser::ComponentExternalKind::Value => {
1504 unimplemented!("component values");
1505 }
1506 wasmparser::ComponentExternalKind::Type => {
1507 let types = self.validator.types(0).unwrap();
1508 let ty = types.component_any_type_at(index);
1509 ComponentItem::Type(ty)
1510 }
1511 })
1512 }
1513
1514 fn alias_module_instance_export(
1515 &mut self,
1516 kind: wasmparser::ExternalKind,
1517 instance: ModuleInstanceIndex,
1518 name: &'data str,
1519 ) -> LocalInitializer<'data> {
1520 match kind {
1521 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1522 LocalInitializer::AliasExportFunc(instance, name)
1523 }
1524 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1525 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1526 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1527 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1528 }
1529 }
1530
1531 fn alias_component_outer(
1532 &mut self,
1533 kind: wasmparser::ComponentOuterAliasKind,
1534 count: u32,
1535 index: u32,
1536 ) {
1537 match kind {
1538 wasmparser::ComponentOuterAliasKind::CoreType
1539 | wasmparser::ComponentOuterAliasKind::Type => {}
1540
1541 wasmparser::ComponentOuterAliasKind::CoreModule => {
1548 let index = ModuleIndex::from_u32(index);
1549 let mut module = ClosedOverModule::Local(index);
1550 let depth = self.lexical_scopes.len() - (count as usize);
1551 for frame in self.lexical_scopes[depth..].iter_mut() {
1552 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1553 }
1554
1555 self.result
1560 .initializers
1561 .push(LocalInitializer::AliasModule(module));
1562 }
1563 wasmparser::ComponentOuterAliasKind::Component => {
1564 let index = ComponentIndex::from_u32(index);
1565 let mut component = ClosedOverComponent::Local(index);
1566 let depth = self.lexical_scopes.len() - (count as usize);
1567 for frame in self.lexical_scopes[depth..].iter_mut() {
1568 component =
1569 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1570 }
1571
1572 self.result
1573 .initializers
1574 .push(LocalInitializer::AliasComponent(component));
1575 }
1576 }
1577 }
1578
1579 fn canonical_options(
1580 &mut self,
1581 opts: &[wasmparser::CanonicalOption],
1582 core_func_index: u32,
1583 ) -> WasmResult<LocalCanonicalOptions> {
1584 let core_type = self.core_func_signature(core_func_index)?;
1585
1586 let mut string_encoding = StringEncoding::Utf8;
1587 let mut post_return = None;
1588 let mut async_ = false;
1589 let mut callback = None;
1590 let mut memory = None;
1591 let mut realloc = None;
1592 let mut gc = false;
1593
1594 for opt in opts {
1595 match opt {
1596 wasmparser::CanonicalOption::UTF8 => {
1597 string_encoding = StringEncoding::Utf8;
1598 }
1599 wasmparser::CanonicalOption::UTF16 => {
1600 string_encoding = StringEncoding::Utf16;
1601 }
1602 wasmparser::CanonicalOption::CompactUTF16 => {
1603 string_encoding = StringEncoding::CompactUtf16;
1604 }
1605 wasmparser::CanonicalOption::Memory(idx) => {
1606 let idx = MemoryIndex::from_u32(*idx);
1607 memory = Some(idx);
1608 }
1609 wasmparser::CanonicalOption::Realloc(idx) => {
1610 let idx = FuncIndex::from_u32(*idx);
1611 realloc = Some(idx);
1612 }
1613 wasmparser::CanonicalOption::PostReturn(idx) => {
1614 let idx = FuncIndex::from_u32(*idx);
1615 post_return = Some(idx);
1616 }
1617 wasmparser::CanonicalOption::Async => async_ = true,
1618 wasmparser::CanonicalOption::Callback(idx) => {
1619 let idx = FuncIndex::from_u32(*idx);
1620 callback = Some(idx);
1621 }
1622 wasmparser::CanonicalOption::CoreType(idx) => {
1623 if cfg!(debug_assertions) {
1624 let types = self.validator.types(0).unwrap();
1625 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1626 let interned = self
1627 .types
1628 .module_types_builder()
1629 .intern_type(types, core_ty_id)?;
1630 debug_assert_eq!(interned, core_type);
1631 }
1632 }
1633 wasmparser::CanonicalOption::Gc => {
1634 gc = true;
1635 }
1636 }
1637 }
1638
1639 Ok(LocalCanonicalOptions {
1640 string_encoding,
1641 post_return,
1642 cancellable: false,
1643 async_,
1644 callback,
1645 core_type,
1646 data_model: if gc {
1647 LocalDataModel::Gc {}
1648 } else {
1649 LocalDataModel::LinearMemory { memory, realloc }
1650 },
1651 })
1652 }
1653
1654 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1656 let types = self.validator.types(0).unwrap();
1657 let id = types.core_function_at(index);
1658 self.types.module_types_builder().intern_type(types, id)
1659 }
1660
1661 fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1662 self.lexical_scopes.is_empty()
1663 && self
1664 .unsafe_intrinsics_import
1665 .is_some_and(|name| import == name)
1666 }
1667
1668 fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1669 let types = &self.validator.types(0).unwrap();
1670
1671 let ComponentEntityType::Instance(instance_ty) = ty else {
1672 bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1673 };
1674 let instance_ty = &types[instance_ty];
1675
1676 ensure!(
1677 instance_ty.defined_resources.is_empty(),
1678 "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1679 );
1680 ensure!(
1681 instance_ty.explicit_resources.is_empty(),
1682 "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1683 );
1684
1685 for (name, ty) in &instance_ty.exports {
1686 let ComponentEntityType::Func(func_ty) = ty.ty else {
1687 bail!(
1688 "bad unsafe intrinsics import: imported instance `{import}` must \
1689 only export functions"
1690 )
1691 };
1692 let func_ty = &types[func_ty];
1693
1694 fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1695 use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1696 match (a, b) {
1697 (InterfaceType::U8, C::Primitive(P::U8)) => true,
1698 (InterfaceType::U8, _) => false,
1699
1700 (InterfaceType::U16, C::Primitive(P::U16)) => true,
1701 (InterfaceType::U16, _) => false,
1702
1703 (InterfaceType::U32, C::Primitive(P::U32)) => true,
1704 (InterfaceType::U32, _) => false,
1705
1706 (InterfaceType::U64, C::Primitive(P::U64)) => true,
1707 (InterfaceType::U64, _) => false,
1708
1709 (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1710 }
1711 }
1712
1713 fn check_types<'a>(
1714 expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1715 actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1716 kind: &str,
1717 import: &str,
1718 name: &str,
1719 ) -> Result<()> {
1720 let expected_len = expected.len();
1721 let actual_len = actual.len();
1722 ensure!(
1723 expected_len == actual_len,
1724 "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1725 {expected_len} {kind}, found {actual_len}"
1726 );
1727
1728 for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1729 ensure!(
1730 ty_eq(expected_ty, actual_ty),
1731 "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1732 `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1733 );
1734 }
1735 Ok(())
1736 }
1737
1738 let intrinsic = UnsafeIntrinsic::from_str(name)
1739 .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1740
1741 check_types(
1742 intrinsic.component_params().iter(),
1743 func_ty.params.iter().map(|(_name, ty)| ty),
1744 "parameters",
1745 &import,
1746 &name,
1747 )?;
1748 check_types(
1749 intrinsic.component_results().iter(),
1750 func_ty.result.iter(),
1751 "results",
1752 &import,
1753 &name,
1754 )?;
1755 }
1756
1757 Ok(())
1758 }
1759}
1760
1761impl Translation<'_> {
1762 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1763 self.types.as_ref().unwrap().as_ref()
1764 }
1765}
1766
1767mod pre_inlining {
1779 use super::*;
1780
1781 pub struct PreInliningComponentTypes<'a> {
1782 types: &'a mut ComponentTypesBuilder,
1783 }
1784
1785 impl<'a> PreInliningComponentTypes<'a> {
1786 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1787 Self { types }
1788 }
1789
1790 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1791 self.types.module_types_builder_mut()
1792 }
1793
1794 pub fn types(&self) -> &ComponentTypesBuilder {
1795 self.types
1796 }
1797
1798 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1801 self.types
1802 }
1803 }
1804
1805 impl TypeConvert for PreInliningComponentTypes<'_> {
1806 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1807 self.types.lookup_heap_type(index)
1808 }
1809
1810 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1811 self.types.lookup_type_index(index)
1812 }
1813 }
1814}
1815use pre_inlining::PreInliningComponentTypes;