1use crate::Abi;
2use crate::component::dfg::AbstractInstantiations;
3use crate::component::*;
4use crate::prelude::*;
5use crate::{
6 EngineOrModuleTypeIndex, EntityIndex, FuncKey, ModuleEnvironment, ModuleInternedTypeIndex,
7 ModuleTranslation, ModuleTypesBuilder, PrimaryMap, ScopeVec, TagIndex, Tunables, TypeConvert,
8 WasmHeapType, WasmResult, WasmValType,
9};
10use core::str::FromStr;
11use cranelift_entity::SecondaryMap;
12use cranelift_entity::packed_option::PackedOption;
13use indexmap::IndexMap;
14use std::collections::HashMap;
15use std::mem;
16use wasmparser::component_types::{
17 AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
18 ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
19};
20use wasmparser::types::Types;
21use wasmparser::{Chunk, ComponentExternName, Encoding, Parser, Payload, Validator};
22
23mod adapt;
24pub use self::adapt::*;
25mod inline;
26
27pub struct Translator<'a, 'data> {
29 result: Translation<'data>,
34
35 parser: Parser,
38
39 lexical_scopes: Vec<LexicalScope<'data>>,
47
48 validator: &'a mut Validator,
51
52 types: PreInliningComponentTypes<'a>,
57
58 tunables: &'a Tunables,
60
61 scope_vec: &'data ScopeVec<u8>,
63
64 static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
69
70 static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
75
76 unsafe_intrinsics_import: Option<&'a str>,
78}
79
80struct LexicalScope<'data> {
133 parser: Parser,
135 translation: Translation<'data>,
137 closure_args: ClosedOverVars,
140}
141
142#[derive(Default)]
152struct Translation<'data> {
153 initializers: Vec<LocalInitializer<'data>>,
159
160 exports: IndexMap<&'data str, (ComponentItem, 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(_) => continue,
627
628 CoreDef::UnsafeIntrinsic(i) => FuncKey::UnsafeIntrinsic(Abi::Wasm, *i),
632
633 CoreDef::Export(export) => {
637 let Some(arg_module) = &instance_to_module[export.instance].expand() else {
638 continue;
643 };
644
645 let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
646 else {
647 unreachable!("function imports must be functions")
648 };
649
650 let Some(arg_module_def_func) = self.static_modules[*arg_module]
651 .module
652 .defined_func_index(*arg_func)
653 else {
654 continue;
661 };
662
663 FuncKey::DefinedWasmFunction(*arg_module, arg_module_def_func)
664 }
665 };
666
667 assert!(
668 self.static_modules[module].known_imported_functions[imported_func].is_none()
669 );
670 self.static_modules[module].known_imported_functions[imported_func] =
671 Some(known_func);
672 }
673 }
674 }
675
676 fn translate_payload(
677 &mut self,
678 payload: Payload<'data>,
679 component: &'data [u8],
680 ) -> Result<Action> {
681 match payload {
682 Payload::Version {
683 num,
684 encoding,
685 range,
686 } => {
687 self.validator.version(num, encoding, &range)?;
688
689 match encoding {
690 Encoding::Component => {}
691 Encoding::Module => {
692 bail!("attempted to parse a wasm module with a component parser");
693 }
694 }
695 }
696
697 Payload::End(offset) => {
698 assert!(self.result.types.is_none());
699 self.result.types = Some(self.validator.end(offset)?);
700
701 let LexicalScope {
706 parser,
707 translation,
708 closure_args,
709 } = match self.lexical_scopes.pop() {
710 Some(frame) => frame,
711 None => return Ok(Action::Done),
712 };
713 self.parser = parser;
714 let component = mem::replace(&mut self.result, translation);
715 let static_idx = self.static_components.push(component);
716 self.result
717 .initializers
718 .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
719 }
720
721 Payload::ComponentTypeSection(s) => {
730 let mut component_type_index =
731 self.validator.types(0).unwrap().component_type_count();
732 self.validator.component_type_section(&s)?;
733
734 let types = self.validator.types(0).unwrap();
738 for ty in s {
739 match ty? {
740 wasmparser::ComponentType::Resource { rep, dtor } => {
741 let rep = self.types.convert_valtype(rep)?;
742 let id = types
743 .component_any_type_at(component_type_index)
744 .unwrap_resource();
745 let dtor = dtor.map(FuncIndex::from_u32);
746 self.result
747 .initializers
748 .push(LocalInitializer::Resource(id, rep, dtor));
749 }
750
751 wasmparser::ComponentType::Defined(_)
753 | wasmparser::ComponentType::Func(_)
754 | wasmparser::ComponentType::Instance(_)
755 | wasmparser::ComponentType::Component(_) => {}
756 }
757
758 component_type_index += 1;
759 }
760 }
761 Payload::CoreTypeSection(s) => {
762 self.validator.core_type_section(&s)?;
763 }
764
765 Payload::ComponentImportSection(s) => {
769 self.validator.component_import_section(&s)?;
770 for import in s {
771 let import = import?;
772 let types = self.validator.types(0).unwrap();
773 let ty = types
774 .component_item_for_import(import.name.name)
775 .unwrap()
776 .ty;
777
778 if self.is_unsafe_intrinsics_import(import.name.name) {
779 self.check_unsafe_intrinsics_import(import.name.name, ty)?;
780 self.result
781 .initializers
782 .push(LocalInitializer::IntrinsicsImport);
783 } else {
784 self.result
785 .initializers
786 .push(LocalInitializer::Import(import.name, ty));
787 }
788 }
789 }
790
791 Payload::ComponentCanonicalSection(s) => {
794 let types = self.validator.types(0).unwrap();
795 let mut core_func_index = types.function_count();
796 self.validator.component_canonical_section(&s)?;
797 for func in s {
798 let init = match func? {
799 wasmparser::CanonicalFunction::Lift {
800 type_index,
801 core_func_index,
802 options,
803 } => {
804 let ty = self
805 .validator
806 .types(0)
807 .unwrap()
808 .component_any_type_at(type_index)
809 .unwrap_func();
810
811 let func = FuncIndex::from_u32(core_func_index);
812 let options = self.canonical_options(&options, core_func_index)?;
813 LocalInitializer::Lift(ty, func, options)
814 }
815 wasmparser::CanonicalFunction::Lower {
816 func_index,
817 options,
818 } => {
819 let lower_ty = self
820 .validator
821 .types(0)
822 .unwrap()
823 .component_function_at(func_index);
824 let func = ComponentFuncIndex::from_u32(func_index);
825 let options = self.canonical_options(&options, core_func_index)?;
826 core_func_index += 1;
827 LocalInitializer::Lower {
828 func,
829 options,
830 lower_ty,
831 }
832 }
833 wasmparser::CanonicalFunction::ResourceNew { resource } => {
834 let resource = self
835 .validator
836 .types(0)
837 .unwrap()
838 .component_any_type_at(resource)
839 .unwrap_resource();
840 let ty = self.core_func_signature(core_func_index)?;
841 core_func_index += 1;
842 LocalInitializer::ResourceNew(resource, ty)
843 }
844 wasmparser::CanonicalFunction::ResourceDrop { resource } => {
845 let resource = self
846 .validator
847 .types(0)
848 .unwrap()
849 .component_any_type_at(resource)
850 .unwrap_resource();
851 let ty = self.core_func_signature(core_func_index)?;
852 core_func_index += 1;
853 LocalInitializer::ResourceDrop(resource, ty)
854 }
855 wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
856 let _ = resource;
857 bail!("support for `resource.drop async` not implemented yet")
858 }
859 wasmparser::CanonicalFunction::ResourceRep { resource } => {
860 let resource = self
861 .validator
862 .types(0)
863 .unwrap()
864 .component_any_type_at(resource)
865 .unwrap_resource();
866 let ty = self.core_func_signature(core_func_index)?;
867 core_func_index += 1;
868 LocalInitializer::ResourceRep(resource, ty)
869 }
870 wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
871 | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
872 | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
873 bail!("unsupported intrinsic")
874 }
875 wasmparser::CanonicalFunction::BackpressureInc => {
876 let core_type = self.core_func_signature(core_func_index)?;
877 core_func_index += 1;
878 LocalInitializer::BackpressureInc { func: core_type }
879 }
880 wasmparser::CanonicalFunction::BackpressureDec => {
881 let core_type = self.core_func_signature(core_func_index)?;
882 core_func_index += 1;
883 LocalInitializer::BackpressureDec { func: core_type }
884 }
885
886 wasmparser::CanonicalFunction::TaskReturn { result, options } => {
887 let result = result.map(|ty| match ty {
888 wasmparser::ComponentValType::Primitive(ty) => {
889 ComponentValType::Primitive(ty)
890 }
891 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
892 self.validator
893 .types(0)
894 .unwrap()
895 .component_defined_type_at(ty),
896 ),
897 });
898 let options = self.canonical_options(&options, core_func_index)?;
899 core_func_index += 1;
900 LocalInitializer::TaskReturn { result, options }
901 }
902 wasmparser::CanonicalFunction::TaskCancel => {
903 let func = self.core_func_signature(core_func_index)?;
904 core_func_index += 1;
905 LocalInitializer::TaskCancel { func }
906 }
907 wasmparser::CanonicalFunction::WaitableSetNew => {
908 let func = self.core_func_signature(core_func_index)?;
909 core_func_index += 1;
910 LocalInitializer::WaitableSetNew { func }
911 }
912 wasmparser::CanonicalFunction::WaitableSetWait {
913 cancellable,
914 memory,
915 } => {
916 let core_type = self.core_func_signature(core_func_index)?;
917 core_func_index += 1;
918 LocalInitializer::WaitableSetWait {
919 options: LocalCanonicalOptions {
920 core_type,
921 cancellable,
922 async_: false,
923 data_model: LocalDataModel::LinearMemory {
924 memory: Some(MemoryIndex::from_u32(memory)),
925 realloc: None,
926 },
927 post_return: None,
928 callback: None,
929 string_encoding: StringEncoding::Utf8,
930 },
931 }
932 }
933 wasmparser::CanonicalFunction::WaitableSetPoll {
934 cancellable,
935 memory,
936 } => {
937 let core_type = self.core_func_signature(core_func_index)?;
938 core_func_index += 1;
939 LocalInitializer::WaitableSetPoll {
940 options: LocalCanonicalOptions {
941 core_type,
942 async_: false,
943 cancellable,
944 data_model: LocalDataModel::LinearMemory {
945 memory: Some(MemoryIndex::from_u32(memory)),
946 realloc: None,
947 },
948 post_return: None,
949 callback: None,
950 string_encoding: StringEncoding::Utf8,
951 },
952 }
953 }
954 wasmparser::CanonicalFunction::WaitableSetDrop => {
955 let func = self.core_func_signature(core_func_index)?;
956 core_func_index += 1;
957 LocalInitializer::WaitableSetDrop { func }
958 }
959 wasmparser::CanonicalFunction::WaitableJoin => {
960 let func = self.core_func_signature(core_func_index)?;
961 core_func_index += 1;
962 LocalInitializer::WaitableJoin { func }
963 }
964 wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
965 let func = self.core_func_signature(core_func_index)?;
966 core_func_index += 1;
967 LocalInitializer::ThreadYield { func, cancellable }
968 }
969 wasmparser::CanonicalFunction::SubtaskDrop => {
970 let func = self.core_func_signature(core_func_index)?;
971 core_func_index += 1;
972 LocalInitializer::SubtaskDrop { func }
973 }
974 wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
975 let func = self.core_func_signature(core_func_index)?;
976 core_func_index += 1;
977 LocalInitializer::SubtaskCancel { func, async_ }
978 }
979 wasmparser::CanonicalFunction::StreamNew { ty } => {
980 let ty = self
981 .validator
982 .types(0)
983 .unwrap()
984 .component_defined_type_at(ty);
985 let func = self.core_func_signature(core_func_index)?;
986 core_func_index += 1;
987 LocalInitializer::StreamNew { ty, func }
988 }
989 wasmparser::CanonicalFunction::StreamRead { ty, options } => {
990 let ty = self
991 .validator
992 .types(0)
993 .unwrap()
994 .component_defined_type_at(ty);
995 let options = self.canonical_options(&options, core_func_index)?;
996 core_func_index += 1;
997 LocalInitializer::StreamRead { ty, options }
998 }
999 wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
1000 let ty = self
1001 .validator
1002 .types(0)
1003 .unwrap()
1004 .component_defined_type_at(ty);
1005 let options = self.canonical_options(&options, core_func_index)?;
1006 core_func_index += 1;
1007 LocalInitializer::StreamWrite { ty, options }
1008 }
1009 wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1010 let ty = self
1011 .validator
1012 .types(0)
1013 .unwrap()
1014 .component_defined_type_at(ty);
1015 let func = self.core_func_signature(core_func_index)?;
1016 core_func_index += 1;
1017 LocalInitializer::StreamCancelRead { ty, func, async_ }
1018 }
1019 wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1020 let ty = self
1021 .validator
1022 .types(0)
1023 .unwrap()
1024 .component_defined_type_at(ty);
1025 let func = self.core_func_signature(core_func_index)?;
1026 core_func_index += 1;
1027 LocalInitializer::StreamCancelWrite { ty, func, async_ }
1028 }
1029 wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1030 let ty = self
1031 .validator
1032 .types(0)
1033 .unwrap()
1034 .component_defined_type_at(ty);
1035 let func = self.core_func_signature(core_func_index)?;
1036 core_func_index += 1;
1037 LocalInitializer::StreamDropReadable { ty, func }
1038 }
1039 wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1040 let ty = self
1041 .validator
1042 .types(0)
1043 .unwrap()
1044 .component_defined_type_at(ty);
1045 let func = self.core_func_signature(core_func_index)?;
1046 core_func_index += 1;
1047 LocalInitializer::StreamDropWritable { ty, func }
1048 }
1049 wasmparser::CanonicalFunction::FutureNew { ty } => {
1050 let ty = self
1051 .validator
1052 .types(0)
1053 .unwrap()
1054 .component_defined_type_at(ty);
1055 let func = self.core_func_signature(core_func_index)?;
1056 core_func_index += 1;
1057 LocalInitializer::FutureNew { ty, func }
1058 }
1059 wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1060 let ty = self
1061 .validator
1062 .types(0)
1063 .unwrap()
1064 .component_defined_type_at(ty);
1065 let options = self.canonical_options(&options, core_func_index)?;
1066 core_func_index += 1;
1067 LocalInitializer::FutureRead { ty, options }
1068 }
1069 wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1070 let ty = self
1071 .validator
1072 .types(0)
1073 .unwrap()
1074 .component_defined_type_at(ty);
1075 let options = self.canonical_options(&options, core_func_index)?;
1076 core_func_index += 1;
1077 LocalInitializer::FutureWrite { ty, options }
1078 }
1079 wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1080 let ty = self
1081 .validator
1082 .types(0)
1083 .unwrap()
1084 .component_defined_type_at(ty);
1085 let func = self.core_func_signature(core_func_index)?;
1086 core_func_index += 1;
1087 LocalInitializer::FutureCancelRead { ty, func, async_ }
1088 }
1089 wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1090 let ty = self
1091 .validator
1092 .types(0)
1093 .unwrap()
1094 .component_defined_type_at(ty);
1095 let func = self.core_func_signature(core_func_index)?;
1096 core_func_index += 1;
1097 LocalInitializer::FutureCancelWrite { ty, func, async_ }
1098 }
1099 wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1100 let ty = self
1101 .validator
1102 .types(0)
1103 .unwrap()
1104 .component_defined_type_at(ty);
1105 let func = self.core_func_signature(core_func_index)?;
1106 core_func_index += 1;
1107 LocalInitializer::FutureDropReadable { ty, func }
1108 }
1109 wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1110 let ty = self
1111 .validator
1112 .types(0)
1113 .unwrap()
1114 .component_defined_type_at(ty);
1115 let func = self.core_func_signature(core_func_index)?;
1116 core_func_index += 1;
1117 LocalInitializer::FutureDropWritable { ty, func }
1118 }
1119 wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1120 let options = self.canonical_options(&options, core_func_index)?;
1121 core_func_index += 1;
1122 LocalInitializer::ErrorContextNew { options }
1123 }
1124 wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1125 let options = self.canonical_options(&options, core_func_index)?;
1126 core_func_index += 1;
1127 LocalInitializer::ErrorContextDebugMessage { options }
1128 }
1129 wasmparser::CanonicalFunction::ErrorContextDrop => {
1130 let func = self.core_func_signature(core_func_index)?;
1131 core_func_index += 1;
1132 LocalInitializer::ErrorContextDrop { func }
1133 }
1134 wasmparser::CanonicalFunction::ContextGet { slot, ty } => {
1135 if ty != wasmparser::ValType::I32 {
1136 bail!("unsupported context.get type: {ty:?}");
1137 }
1138 let func = self.core_func_signature(core_func_index)?;
1139 core_func_index += 1;
1140 LocalInitializer::ContextGet { i: slot, func }
1141 }
1142 wasmparser::CanonicalFunction::ContextSet { slot, ty } => {
1143 if ty != wasmparser::ValType::I32 {
1144 bail!("unsupported context.set type: {ty:?}");
1145 }
1146 let func = self.core_func_signature(core_func_index)?;
1147 core_func_index += 1;
1148 LocalInitializer::ContextSet { i: slot, func }
1149 }
1150 wasmparser::CanonicalFunction::ThreadIndex => {
1151 let func = self.core_func_signature(core_func_index)?;
1152 core_func_index += 1;
1153 LocalInitializer::ThreadIndex { func }
1154 }
1155 wasmparser::CanonicalFunction::ThreadNewIndirect {
1156 func_ty_index,
1157 table_index,
1158 } => {
1159 let func = self.core_func_signature(core_func_index)?;
1160 core_func_index += 1;
1161 LocalInitializer::ThreadNewIndirect {
1162 func,
1163 start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1164 start_func_table_index: TableIndex::from_u32(table_index),
1165 }
1166 }
1167 wasmparser::CanonicalFunction::ThreadSuspendToSuspended { cancellable } => {
1168 let func = self.core_func_signature(core_func_index)?;
1169 core_func_index += 1;
1170 LocalInitializer::ThreadSuspendToSuspended { func, cancellable }
1171 }
1172 wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1173 let func = self.core_func_signature(core_func_index)?;
1174 core_func_index += 1;
1175 LocalInitializer::ThreadSuspend { func, cancellable }
1176 }
1177 wasmparser::CanonicalFunction::ThreadSuspendTo { cancellable } => {
1178 let func = self.core_func_signature(core_func_index)?;
1179 core_func_index += 1;
1180 LocalInitializer::ThreadSuspendTo { func, cancellable }
1181 }
1182 wasmparser::CanonicalFunction::ThreadUnsuspend => {
1183 let func = self.core_func_signature(core_func_index)?;
1184 core_func_index += 1;
1185 LocalInitializer::ThreadUnsuspend { func }
1186 }
1187 wasmparser::CanonicalFunction::ThreadYieldToSuspended { cancellable } => {
1188 let func = self.core_func_signature(core_func_index)?;
1189 core_func_index += 1;
1190 LocalInitializer::ThreadYieldToSuspended { func, cancellable }
1191 }
1192 };
1193 self.result.initializers.push(init);
1194 }
1195 }
1196
1197 Payload::ModuleSection {
1206 parser,
1207 unchecked_range,
1208 } => {
1209 let index = self.validator.types(0).unwrap().module_count();
1210 self.validator.module_section(&unchecked_range)?;
1211 let static_module_index = self.static_modules.next_key();
1212 let mut translation = ModuleEnvironment::new(
1213 self.tunables,
1214 self.validator,
1215 self.types.module_types_builder(),
1216 static_module_index,
1217 )
1218 .translate(
1219 parser,
1220 component
1221 .get(unchecked_range.start..unchecked_range.end)
1222 .ok_or_else(|| {
1223 format_err!(
1224 "section range {}..{} is out of bounds (bound = {})",
1225 unchecked_range.start,
1226 unchecked_range.end,
1227 component.len()
1228 )
1229 .context("wasm component contains an invalid module section")
1230 })?,
1231 )?;
1232
1233 translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap();
1234 let static_module_index2 = self.static_modules.push(translation);
1235 assert_eq!(static_module_index, static_module_index2);
1236 let types = self.validator.types(0).unwrap();
1237 let ty = types.module_at(index);
1238 self.result
1239 .initializers
1240 .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1241 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1242 }
1243
1244 Payload::ComponentSection {
1253 parser,
1254 unchecked_range,
1255 } => {
1256 self.validator.component_section(&unchecked_range)?;
1257 self.lexical_scopes.push(LexicalScope {
1258 parser: mem::replace(&mut self.parser, parser),
1259 translation: mem::take(&mut self.result),
1260 closure_args: ClosedOverVars::default(),
1261 });
1262 }
1263
1264 Payload::InstanceSection(s) => {
1269 self.validator.instance_section(&s)?;
1270 for instance in s {
1271 let init = match instance? {
1272 wasmparser::Instance::Instantiate { module_index, args } => {
1273 let index = ModuleIndex::from_u32(module_index);
1274 self.instantiate_module(index, &args)
1275 }
1276 wasmparser::Instance::FromExports(exports) => {
1277 self.instantiate_module_from_exports(&exports)
1278 }
1279 };
1280 self.result.initializers.push(init);
1281 }
1282 }
1283 Payload::ComponentInstanceSection(s) => {
1284 let mut index = self.validator.types(0).unwrap().component_instance_count();
1285 self.validator.component_instance_section(&s)?;
1286 for instance in s {
1287 let types = self.validator.types(0).unwrap();
1288 let ty = types.component_instance_at(index);
1289 let init = match instance? {
1290 wasmparser::ComponentInstance::Instantiate {
1291 component_index,
1292 args,
1293 } => {
1294 let index = ComponentIndex::from_u32(component_index);
1295 self.instantiate_component(index, &args, ty)?
1296 }
1297 wasmparser::ComponentInstance::FromExports(exports) => {
1298 self.instantiate_component_from_exports(&exports, ty)?
1299 }
1300 };
1301 self.result.initializers.push(init);
1302 index += 1;
1303 }
1304 }
1305
1306 Payload::ComponentExportSection(s) => {
1312 self.validator.component_export_section(&s)?;
1313 for export in s {
1314 let export = export?;
1315 let item = self.kind_to_item(export.kind, export.index)?;
1316 let prev = self
1317 .result
1318 .exports
1319 .insert(export.name.name, (item, export.name));
1320 assert!(prev.is_none());
1321 self.result
1322 .initializers
1323 .push(LocalInitializer::Export(item));
1324 }
1325 }
1326
1327 Payload::ComponentStartSection { start, range } => {
1328 self.validator.component_start_section(&start, &range)?;
1329 unimplemented!("component start section");
1330 }
1331
1332 Payload::ComponentAliasSection(s) => {
1336 self.validator.component_alias_section(&s)?;
1337 for alias in s {
1338 let init = match alias? {
1339 wasmparser::ComponentAlias::InstanceExport {
1340 kind: _,
1341 instance_index,
1342 name,
1343 } => {
1344 let instance = ComponentInstanceIndex::from_u32(instance_index);
1345 LocalInitializer::AliasComponentExport(instance, name)
1346 }
1347 wasmparser::ComponentAlias::Outer { kind, count, index } => {
1348 self.alias_component_outer(kind, count, index);
1349 continue;
1350 }
1351 wasmparser::ComponentAlias::CoreInstanceExport {
1352 kind,
1353 instance_index,
1354 name,
1355 } => {
1356 let instance = ModuleInstanceIndex::from_u32(instance_index);
1357 self.alias_module_instance_export(kind, instance, name)
1358 }
1359 };
1360 self.result.initializers.push(init);
1361 }
1362 }
1363
1364 Payload::CustomSection { .. } => {}
1369
1370 other => {
1376 self.validator.payload(&other)?;
1377 panic!("unimplemented section {other:?}");
1378 }
1379 }
1380
1381 Ok(Action::KeepGoing)
1382 }
1383
1384 fn instantiate_module(
1385 &mut self,
1386 module: ModuleIndex,
1387 raw_args: &[wasmparser::InstantiationArg<'data>],
1388 ) -> LocalInitializer<'data> {
1389 let mut args = HashMap::with_capacity(raw_args.len());
1390 for arg in raw_args {
1391 match arg.kind {
1392 wasmparser::InstantiationArgKind::Instance => {
1393 let idx = ModuleInstanceIndex::from_u32(arg.index);
1394 args.insert(arg.name, idx);
1395 }
1396 }
1397 }
1398 LocalInitializer::ModuleInstantiate(module, args)
1399 }
1400
1401 fn instantiate_module_from_exports(
1404 &mut self,
1405 exports: &[wasmparser::Export<'data>],
1406 ) -> LocalInitializer<'data> {
1407 let mut map = HashMap::with_capacity(exports.len());
1408 for export in exports {
1409 let idx = match export.kind {
1410 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1411 let index = FuncIndex::from_u32(export.index);
1412 EntityIndex::Function(index)
1413 }
1414 wasmparser::ExternalKind::Table => {
1415 let index = TableIndex::from_u32(export.index);
1416 EntityIndex::Table(index)
1417 }
1418 wasmparser::ExternalKind::Memory => {
1419 let index = MemoryIndex::from_u32(export.index);
1420 EntityIndex::Memory(index)
1421 }
1422 wasmparser::ExternalKind::Global => {
1423 let index = GlobalIndex::from_u32(export.index);
1424 EntityIndex::Global(index)
1425 }
1426 wasmparser::ExternalKind::Tag => {
1427 let index = TagIndex::from_u32(export.index);
1428 EntityIndex::Tag(index)
1429 }
1430 };
1431 map.insert(export.name, idx);
1432 }
1433 LocalInitializer::ModuleSynthetic(map)
1434 }
1435
1436 fn instantiate_component(
1437 &mut self,
1438 component: ComponentIndex,
1439 raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1440 ty: ComponentInstanceTypeId,
1441 ) -> Result<LocalInitializer<'data>> {
1442 let mut args = HashMap::with_capacity(raw_args.len());
1443 for arg in raw_args {
1444 let idx = self.kind_to_item(arg.kind, arg.index)?;
1445 args.insert(arg.name, idx);
1446 }
1447
1448 Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1449 }
1450
1451 fn instantiate_component_from_exports(
1454 &mut self,
1455 exports: &[wasmparser::ComponentExport<'data>],
1456 ty: ComponentInstanceTypeId,
1457 ) -> Result<LocalInitializer<'data>> {
1458 let mut map = HashMap::with_capacity(exports.len());
1459 for export in exports {
1460 let idx = self.kind_to_item(export.kind, export.index)?;
1461 map.insert(export.name.name, (idx, export.name));
1462 }
1463
1464 Ok(LocalInitializer::ComponentSynthetic(map, ty))
1465 }
1466
1467 fn kind_to_item(
1468 &mut self,
1469 kind: wasmparser::ComponentExternalKind,
1470 index: u32,
1471 ) -> Result<ComponentItem> {
1472 Ok(match kind {
1473 wasmparser::ComponentExternalKind::Func => {
1474 let index = ComponentFuncIndex::from_u32(index);
1475 ComponentItem::Func(index)
1476 }
1477 wasmparser::ComponentExternalKind::Module => {
1478 let index = ModuleIndex::from_u32(index);
1479 ComponentItem::Module(index)
1480 }
1481 wasmparser::ComponentExternalKind::Instance => {
1482 let index = ComponentInstanceIndex::from_u32(index);
1483 ComponentItem::ComponentInstance(index)
1484 }
1485 wasmparser::ComponentExternalKind::Component => {
1486 let index = ComponentIndex::from_u32(index);
1487 ComponentItem::Component(index)
1488 }
1489 wasmparser::ComponentExternalKind::Value => {
1490 unimplemented!("component values");
1491 }
1492 wasmparser::ComponentExternalKind::Type => {
1493 let types = self.validator.types(0).unwrap();
1494 let ty = types.component_any_type_at(index);
1495 ComponentItem::Type(ty)
1496 }
1497 })
1498 }
1499
1500 fn alias_module_instance_export(
1501 &mut self,
1502 kind: wasmparser::ExternalKind,
1503 instance: ModuleInstanceIndex,
1504 name: &'data str,
1505 ) -> LocalInitializer<'data> {
1506 match kind {
1507 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1508 LocalInitializer::AliasExportFunc(instance, name)
1509 }
1510 wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1511 wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1512 wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1513 wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1514 }
1515 }
1516
1517 fn alias_component_outer(
1518 &mut self,
1519 kind: wasmparser::ComponentOuterAliasKind,
1520 count: u32,
1521 index: u32,
1522 ) {
1523 match kind {
1524 wasmparser::ComponentOuterAliasKind::CoreType
1525 | wasmparser::ComponentOuterAliasKind::Type => {}
1526
1527 wasmparser::ComponentOuterAliasKind::CoreModule => {
1534 let index = ModuleIndex::from_u32(index);
1535 let mut module = ClosedOverModule::Local(index);
1536 let depth = self.lexical_scopes.len() - (count as usize);
1537 for frame in self.lexical_scopes[depth..].iter_mut() {
1538 module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1539 }
1540
1541 self.result
1546 .initializers
1547 .push(LocalInitializer::AliasModule(module));
1548 }
1549 wasmparser::ComponentOuterAliasKind::Component => {
1550 let index = ComponentIndex::from_u32(index);
1551 let mut component = ClosedOverComponent::Local(index);
1552 let depth = self.lexical_scopes.len() - (count as usize);
1553 for frame in self.lexical_scopes[depth..].iter_mut() {
1554 component =
1555 ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1556 }
1557
1558 self.result
1559 .initializers
1560 .push(LocalInitializer::AliasComponent(component));
1561 }
1562 }
1563 }
1564
1565 fn canonical_options(
1566 &mut self,
1567 opts: &[wasmparser::CanonicalOption],
1568 core_func_index: u32,
1569 ) -> WasmResult<LocalCanonicalOptions> {
1570 let core_type = self.core_func_signature(core_func_index)?;
1571
1572 let mut string_encoding = StringEncoding::Utf8;
1573 let mut post_return = None;
1574 let mut async_ = false;
1575 let mut callback = None;
1576 let mut memory = None;
1577 let mut realloc = None;
1578 let mut gc = false;
1579
1580 for opt in opts {
1581 match opt {
1582 wasmparser::CanonicalOption::UTF8 => {
1583 string_encoding = StringEncoding::Utf8;
1584 }
1585 wasmparser::CanonicalOption::UTF16 => {
1586 string_encoding = StringEncoding::Utf16;
1587 }
1588 wasmparser::CanonicalOption::CompactUTF16 => {
1589 string_encoding = StringEncoding::CompactUtf16;
1590 }
1591 wasmparser::CanonicalOption::Memory(idx) => {
1592 let idx = MemoryIndex::from_u32(*idx);
1593 memory = Some(idx);
1594 }
1595 wasmparser::CanonicalOption::Realloc(idx) => {
1596 let idx = FuncIndex::from_u32(*idx);
1597 realloc = Some(idx);
1598 }
1599 wasmparser::CanonicalOption::PostReturn(idx) => {
1600 let idx = FuncIndex::from_u32(*idx);
1601 post_return = Some(idx);
1602 }
1603 wasmparser::CanonicalOption::Async => async_ = true,
1604 wasmparser::CanonicalOption::Callback(idx) => {
1605 let idx = FuncIndex::from_u32(*idx);
1606 callback = Some(idx);
1607 }
1608 wasmparser::CanonicalOption::CoreType(idx) => {
1609 if cfg!(debug_assertions) {
1610 let types = self.validator.types(0).unwrap();
1611 let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1612 let interned = self
1613 .types
1614 .module_types_builder()
1615 .intern_type(types, core_ty_id)?;
1616 debug_assert_eq!(interned, core_type);
1617 }
1618 }
1619 wasmparser::CanonicalOption::Gc => {
1620 gc = true;
1621 }
1622 }
1623 }
1624
1625 Ok(LocalCanonicalOptions {
1626 string_encoding,
1627 post_return,
1628 cancellable: false,
1629 async_,
1630 callback,
1631 core_type,
1632 data_model: if gc {
1633 LocalDataModel::Gc {}
1634 } else {
1635 LocalDataModel::LinearMemory { memory, realloc }
1636 },
1637 })
1638 }
1639
1640 fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1642 let types = self.validator.types(0).unwrap();
1643 let id = types.core_function_at(index);
1644 self.types.module_types_builder().intern_type(types, id)
1645 }
1646
1647 fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1648 self.lexical_scopes.is_empty()
1649 && self
1650 .unsafe_intrinsics_import
1651 .is_some_and(|name| import == name)
1652 }
1653
1654 fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1655 let types = &self.validator.types(0).unwrap();
1656
1657 let ComponentEntityType::Instance(instance_ty) = ty else {
1658 bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1659 };
1660 let instance_ty = &types[instance_ty];
1661
1662 ensure!(
1663 instance_ty.defined_resources.is_empty(),
1664 "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1665 );
1666 ensure!(
1667 instance_ty.explicit_resources.is_empty(),
1668 "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1669 );
1670
1671 for (name, ty) in &instance_ty.exports {
1672 let ComponentEntityType::Func(func_ty) = ty.ty else {
1673 bail!(
1674 "bad unsafe intrinsics import: imported instance `{import}` must \
1675 only export functions"
1676 )
1677 };
1678 let func_ty = &types[func_ty];
1679
1680 fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1681 use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1682 match (a, b) {
1683 (InterfaceType::U8, C::Primitive(P::U8)) => true,
1684 (InterfaceType::U8, _) => false,
1685
1686 (InterfaceType::U16, C::Primitive(P::U16)) => true,
1687 (InterfaceType::U16, _) => false,
1688
1689 (InterfaceType::U32, C::Primitive(P::U32)) => true,
1690 (InterfaceType::U32, _) => false,
1691
1692 (InterfaceType::U64, C::Primitive(P::U64)) => true,
1693 (InterfaceType::U64, _) => false,
1694
1695 (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1696 }
1697 }
1698
1699 fn check_types<'a>(
1700 expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1701 actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1702 kind: &str,
1703 import: &str,
1704 name: &str,
1705 ) -> Result<()> {
1706 let expected_len = expected.len();
1707 let actual_len = actual.len();
1708 ensure!(
1709 expected_len == actual_len,
1710 "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1711 {expected_len} {kind}, found {actual_len}"
1712 );
1713
1714 for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1715 ensure!(
1716 ty_eq(expected_ty, actual_ty),
1717 "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1718 `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1719 );
1720 }
1721 Ok(())
1722 }
1723
1724 let intrinsic = UnsafeIntrinsic::from_str(name)
1725 .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1726
1727 check_types(
1728 intrinsic.component_params().iter(),
1729 func_ty.params.iter().map(|(_name, ty)| ty),
1730 "parameters",
1731 &import,
1732 &name,
1733 )?;
1734 check_types(
1735 intrinsic.component_results().iter(),
1736 func_ty.result.iter(),
1737 "results",
1738 &import,
1739 &name,
1740 )?;
1741 }
1742
1743 Ok(())
1744 }
1745}
1746
1747impl Translation<'_> {
1748 fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1749 self.types.as_ref().unwrap().as_ref()
1750 }
1751}
1752
1753mod pre_inlining {
1765 use super::*;
1766
1767 pub struct PreInliningComponentTypes<'a> {
1768 types: &'a mut ComponentTypesBuilder,
1769 }
1770
1771 impl<'a> PreInliningComponentTypes<'a> {
1772 pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1773 Self { types }
1774 }
1775
1776 pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1777 self.types.module_types_builder_mut()
1778 }
1779
1780 pub fn types(&self) -> &ComponentTypesBuilder {
1781 self.types
1782 }
1783
1784 pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1787 self.types
1788 }
1789 }
1790
1791 impl TypeConvert for PreInliningComponentTypes<'_> {
1792 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1793 self.types.lookup_heap_type(index)
1794 }
1795
1796 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1797 self.types.lookup_type_index(index)
1798 }
1799 }
1800}
1801use pre_inlining::PreInliningComponentTypes;