1use crate::environ::{FuncEnvironment, GlobalVariable, ModuleEnvironment, TargetEnvironment};
9use crate::func_translator::FuncTranslator;
10use crate::state::FuncTranslationState;
11use crate::WasmType;
12use crate::{
13 DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Heap, HeapData,
14 HeapStyle, Memory, MemoryIndex, Table, TableIndex, TypeIndex, WasmFuncType, WasmResult,
15};
16use core::convert::TryFrom;
17use cranelift_codegen::cursor::FuncCursor;
18use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
19use cranelift_codegen::ir::{self, InstBuilder};
20use cranelift_codegen::ir::{types::*, UserFuncName};
21use cranelift_codegen::isa::{CallConv, TargetFrontendConfig};
22use cranelift_entity::{EntityRef, PrimaryMap, SecondaryMap};
23use cranelift_frontend::FunctionBuilder;
24use std::boxed::Box;
25use std::string::String;
26use std::vec::Vec;
27use wasmparser::{FuncValidator, FunctionBody, Operator, ValidatorResources, WasmFeatures};
28
29pub struct Exportable<T> {
31 pub entity: T,
33
34 pub export_names: Vec<String>,
36}
37
38impl<T> Exportable<T> {
39 pub fn new(entity: T) -> Self {
40 Self {
41 entity,
42 export_names: Vec::new(),
43 }
44 }
45}
46
47pub struct DummyModuleInfo {
51 config: TargetFrontendConfig,
53
54 pub signatures: PrimaryMap<TypeIndex, ir::Signature>,
56
57 pub imported_funcs: Vec<(String, String)>,
59
60 pub imported_globals: Vec<(String, String)>,
62
63 pub imported_tables: Vec<(String, String)>,
65
66 pub imported_memories: Vec<(String, String)>,
68
69 pub functions: PrimaryMap<FuncIndex, Exportable<TypeIndex>>,
71
72 pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
74
75 pub tables: PrimaryMap<TableIndex, Exportable<Table>>,
77
78 pub memories: PrimaryMap<MemoryIndex, Exportable<Memory>>,
80
81 pub globals: PrimaryMap<GlobalIndex, Exportable<Global>>,
83
84 pub start_func: Option<FuncIndex>,
86}
87
88impl DummyModuleInfo {
89 pub fn new(config: TargetFrontendConfig) -> Self {
91 Self {
92 config,
93 signatures: PrimaryMap::new(),
94 imported_funcs: Vec::new(),
95 imported_globals: Vec::new(),
96 imported_tables: Vec::new(),
97 imported_memories: Vec::new(),
98 functions: PrimaryMap::new(),
99 function_bodies: PrimaryMap::new(),
100 tables: PrimaryMap::new(),
101 memories: PrimaryMap::new(),
102 globals: PrimaryMap::new(),
103 start_func: None,
104 }
105 }
106}
107
108#[derive(Clone)]
111pub struct ExpectedReachability {
112 reachability: Vec<(bool, bool)>,
114 before_idx: usize,
115 after_idx: usize,
116}
117
118impl ExpectedReachability {
119 fn check_before(&mut self, reachable: bool) {
120 assert_eq!(reachable, self.reachability[self.before_idx].0);
121 self.before_idx += 1;
122 }
123 fn check_after(&mut self, reachable: bool) {
124 assert_eq!(reachable, self.reachability[self.after_idx].1);
125 self.after_idx += 1;
126 }
127 fn check_end(&self) {
128 assert_eq!(self.before_idx, self.reachability.len());
129 assert_eq!(self.after_idx, self.reachability.len());
130 }
131}
132
133pub struct DummyEnvironment {
137 pub info: DummyModuleInfo,
139
140 pub trans: FuncTranslator,
142
143 pub func_bytecode_sizes: Vec<usize>,
145
146 pub debug_info: bool,
148
149 pub module_name: Option<String>,
151
152 function_names: SecondaryMap<FuncIndex, String>,
154
155 #[doc(hidden)]
157 pub expected_reachability: Option<ExpectedReachability>,
158}
159
160impl DummyEnvironment {
161 pub fn new(config: TargetFrontendConfig, debug_info: bool) -> Self {
163 Self {
164 info: DummyModuleInfo::new(config),
165 trans: FuncTranslator::new(),
166 func_bytecode_sizes: Vec::new(),
167 debug_info,
168 module_name: None,
169 function_names: SecondaryMap::new(),
170 expected_reachability: None,
171 }
172 }
173
174 pub fn func_env(&self) -> DummyFuncEnvironment {
177 DummyFuncEnvironment::new(&self.info, self.expected_reachability.clone())
178 }
179
180 pub fn get_func_type(&self, func_index: FuncIndex) -> TypeIndex {
182 self.info.functions[func_index].entity
183 }
184
185 pub fn get_num_func_imports(&self) -> usize {
187 self.info.imported_funcs.len()
188 }
189
190 pub fn get_func_name(&self, func_index: FuncIndex) -> Option<&str> {
193 self.function_names.get(func_index).map(String::as_ref)
194 }
195
196 pub fn test_expected_reachability(&mut self, reachability: Vec<(bool, bool)>) {
200 self.expected_reachability = Some(ExpectedReachability {
201 reachability,
202 before_idx: 0,
203 after_idx: 0,
204 });
205 }
206}
207
208pub struct DummyFuncEnvironment<'dummy_environment> {
210 pub mod_info: &'dummy_environment DummyModuleInfo,
212
213 expected_reachability: Option<ExpectedReachability>,
215
216 pub heaps: PrimaryMap<Heap, HeapData>,
218}
219
220impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> {
221 pub fn new(
223 mod_info: &'dummy_environment DummyModuleInfo,
224 expected_reachability: Option<ExpectedReachability>,
225 ) -> Self {
226 Self {
227 mod_info,
228 expected_reachability,
229 heaps: Default::default(),
230 }
231 }
232
233 pub fn vmctx_sig(&self, sigidx: TypeIndex) -> ir::Signature {
236 let mut sig = self.mod_info.signatures[sigidx].clone();
237 sig.params.push(ir::AbiParam::special(
238 self.pointer_type(),
239 ir::ArgumentPurpose::VMContext,
240 ));
241 sig
242 }
243
244 fn reference_type(&self) -> ir::Type {
245 match self.pointer_type() {
246 ir::types::I32 => ir::types::R32,
247 ir::types::I64 => ir::types::R64,
248 _ => panic!("unsupported pointer type"),
249 }
250 }
251}
252
253impl<'dummy_environment> TargetEnvironment for DummyFuncEnvironment<'dummy_environment> {
254 fn target_config(&self) -> TargetFrontendConfig {
255 self.mod_info.config
256 }
257
258 fn heap_access_spectre_mitigation(&self) -> bool {
259 false
260 }
261}
262
263impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> {
264 fn make_global(
265 &mut self,
266 func: &mut ir::Function,
267 index: GlobalIndex,
268 ) -> WasmResult<GlobalVariable> {
269 let offset = i32::try_from((index.index() * 8) + 8).unwrap().into();
271 let vmctx = func.create_global_value(ir::GlobalValueData::VMContext {});
272 Ok(GlobalVariable::Memory {
273 gv: vmctx,
274 offset,
275 ty: match self.mod_info.globals[index].entity.wasm_ty {
276 WasmType::I32 => ir::types::I32,
277 WasmType::I64 => ir::types::I64,
278 WasmType::F32 => ir::types::F32,
279 WasmType::F64 => ir::types::F64,
280 WasmType::V128 => ir::types::I8X16,
281 WasmType::FuncRef | WasmType::ExternRef => ir::types::R64,
282 },
283 })
284 }
285
286 fn heaps(&self) -> &PrimaryMap<Heap, HeapData> {
287 &self.heaps
288 }
289
290 fn make_heap(&mut self, func: &mut ir::Function, _index: MemoryIndex) -> WasmResult<Heap> {
291 let addr = func.create_global_value(ir::GlobalValueData::VMContext);
293 let gv = func.create_global_value(ir::GlobalValueData::Load {
294 base: addr,
295 offset: Offset32::new(0),
296 global_type: self.pointer_type(),
297 readonly: true,
298 });
299
300 Ok(self.heaps.push(HeapData {
301 base: gv,
302 min_size: 0,
303 offset_guard_size: 0x8000_0000,
304 style: HeapStyle::Static {
305 bound: 0x1_0000_0000,
306 },
307 index_type: I32,
308 }))
309 }
310
311 fn make_table(&mut self, func: &mut ir::Function, _index: TableIndex) -> WasmResult<ir::Table> {
312 let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
314 let base_gv = func.create_global_value(ir::GlobalValueData::Load {
315 base: vmctx,
316 offset: Offset32::new(0),
317 global_type: self.pointer_type(),
318 readonly: true, });
320 let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
321 base: vmctx,
322 offset: Offset32::new(0),
323 global_type: I32,
324 readonly: true,
325 });
326
327 Ok(func.create_table(ir::TableData {
328 base_gv,
329 min_size: Uimm64::new(0),
330 bound_gv,
331 element_size: Uimm64::from(u64::from(self.pointer_bytes()) * 2),
332 index_type: I32,
333 }))
334 }
335
336 fn make_indirect_sig(
337 &mut self,
338 func: &mut ir::Function,
339 index: TypeIndex,
340 ) -> WasmResult<ir::SigRef> {
341 Ok(func.import_signature(self.vmctx_sig(index)))
344 }
345
346 fn make_direct_func(
347 &mut self,
348 func: &mut ir::Function,
349 index: FuncIndex,
350 ) -> WasmResult<ir::FuncRef> {
351 let sigidx = self.mod_info.functions[index].entity;
352 let signature = func.import_signature(self.vmctx_sig(sigidx));
355 let name =
356 ir::ExternalName::User(func.declare_imported_user_function(ir::UserExternalName {
357 namespace: 0,
358 index: index.as_u32(),
359 }));
360 Ok(func.import_function(ir::ExtFuncData {
361 name,
362 signature,
363 colocated: false,
364 }))
365 }
366
367 fn before_translate_operator(
368 &mut self,
369 _op: &Operator,
370 _builder: &mut FunctionBuilder,
371 state: &FuncTranslationState,
372 ) -> WasmResult<()> {
373 if let Some(ref mut r) = &mut self.expected_reachability {
374 r.check_before(state.reachable());
375 }
376 Ok(())
377 }
378
379 fn after_translate_operator(
380 &mut self,
381 _op: &Operator,
382 _builder: &mut FunctionBuilder,
383 state: &FuncTranslationState,
384 ) -> WasmResult<()> {
385 if let Some(ref mut r) = &mut self.expected_reachability {
386 r.check_after(state.reachable());
387 }
388 Ok(())
389 }
390
391 fn after_translate_function(
392 &mut self,
393 _builder: &mut FunctionBuilder,
394 _state: &FuncTranslationState,
395 ) -> WasmResult<()> {
396 if let Some(ref mut r) = &mut self.expected_reachability {
397 r.check_end();
398 }
399 Ok(())
400 }
401
402 fn translate_call_indirect(
403 &mut self,
404 builder: &mut FunctionBuilder,
405 _table_index: TableIndex,
406 _table: ir::Table,
407 _sig_index: TypeIndex,
408 sig_ref: ir::SigRef,
409 callee: ir::Value,
410 call_args: &[ir::Value],
411 ) -> WasmResult<ir::Inst> {
412 let vmctx = builder
414 .func
415 .special_param(ir::ArgumentPurpose::VMContext)
416 .expect("Missing vmctx parameter");
417
418 let ptr = self.pointer_type();
422 let callee_offset = if ptr == I32 {
423 builder.ins().imul_imm(callee, 4)
424 } else {
425 let ext = builder.ins().uextend(I64, callee);
426 builder.ins().imul_imm(ext, 4)
427 };
428 let mflags = ir::MemFlags::trusted();
429 let func_ptr = builder.ins().load(ptr, mflags, callee_offset, 0);
430
431 let mut args = ir::ValueList::default();
434 args.push(func_ptr, &mut builder.func.dfg.value_lists);
435 args.extend(call_args.iter().cloned(), &mut builder.func.dfg.value_lists);
436 args.push(vmctx, &mut builder.func.dfg.value_lists);
437
438 Ok(builder
439 .ins()
440 .CallIndirect(ir::Opcode::CallIndirect, INVALID, sig_ref, args)
441 .0)
442 }
443
444 fn translate_call(
445 &mut self,
446 mut pos: FuncCursor,
447 _callee_index: FuncIndex,
448 callee: ir::FuncRef,
449 call_args: &[ir::Value],
450 ) -> WasmResult<ir::Inst> {
451 let vmctx = pos
453 .func
454 .special_param(ir::ArgumentPurpose::VMContext)
455 .expect("Missing vmctx parameter");
456
457 let mut args = ir::ValueList::default();
460 args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists);
461 args.push(vmctx, &mut pos.func.dfg.value_lists);
462
463 Ok(pos.ins().Call(ir::Opcode::Call, INVALID, callee, args).0)
464 }
465
466 fn translate_memory_grow(
467 &mut self,
468 mut pos: FuncCursor,
469 _index: MemoryIndex,
470 _heap: Heap,
471 _val: ir::Value,
472 ) -> WasmResult<ir::Value> {
473 Ok(pos.ins().iconst(I32, -1))
474 }
475
476 fn translate_memory_size(
477 &mut self,
478 mut pos: FuncCursor,
479 _index: MemoryIndex,
480 _heap: Heap,
481 ) -> WasmResult<ir::Value> {
482 Ok(pos.ins().iconst(I32, -1))
483 }
484
485 fn translate_memory_copy(
486 &mut self,
487 _pos: FuncCursor,
488 _src_index: MemoryIndex,
489 _src_heap: Heap,
490 _dst_index: MemoryIndex,
491 _dst_heap: Heap,
492 _dst: ir::Value,
493 _src: ir::Value,
494 _len: ir::Value,
495 ) -> WasmResult<()> {
496 Ok(())
497 }
498
499 fn translate_memory_fill(
500 &mut self,
501 _pos: FuncCursor,
502 _index: MemoryIndex,
503 _heap: Heap,
504 _dst: ir::Value,
505 _val: ir::Value,
506 _len: ir::Value,
507 ) -> WasmResult<()> {
508 Ok(())
509 }
510
511 fn translate_memory_init(
512 &mut self,
513 _pos: FuncCursor,
514 _index: MemoryIndex,
515 _heap: Heap,
516 _seg_index: u32,
517 _dst: ir::Value,
518 _src: ir::Value,
519 _len: ir::Value,
520 ) -> WasmResult<()> {
521 Ok(())
522 }
523
524 fn translate_data_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
525 Ok(())
526 }
527
528 fn translate_table_size(
529 &mut self,
530 mut pos: FuncCursor,
531 _index: TableIndex,
532 _table: ir::Table,
533 ) -> WasmResult<ir::Value> {
534 Ok(pos.ins().iconst(I32, -1))
535 }
536
537 fn translate_table_grow(
538 &mut self,
539 mut pos: FuncCursor,
540 _table_index: TableIndex,
541 _table: ir::Table,
542 _delta: ir::Value,
543 _init_value: ir::Value,
544 ) -> WasmResult<ir::Value> {
545 Ok(pos.ins().iconst(I32, -1))
546 }
547
548 fn translate_table_get(
549 &mut self,
550 builder: &mut FunctionBuilder,
551 _table_index: TableIndex,
552 _table: ir::Table,
553 _index: ir::Value,
554 ) -> WasmResult<ir::Value> {
555 Ok(builder.ins().null(self.reference_type()))
556 }
557
558 fn translate_table_set(
559 &mut self,
560 _builder: &mut FunctionBuilder,
561 _table_index: TableIndex,
562 _table: ir::Table,
563 _value: ir::Value,
564 _index: ir::Value,
565 ) -> WasmResult<()> {
566 Ok(())
567 }
568
569 fn translate_table_copy(
570 &mut self,
571 _pos: FuncCursor,
572 _dst_index: TableIndex,
573 _dst_table: ir::Table,
574 _src_index: TableIndex,
575 _src_table: ir::Table,
576 _dst: ir::Value,
577 _src: ir::Value,
578 _len: ir::Value,
579 ) -> WasmResult<()> {
580 Ok(())
581 }
582
583 fn translate_table_fill(
584 &mut self,
585 _pos: FuncCursor,
586 _table_index: TableIndex,
587 _dst: ir::Value,
588 _val: ir::Value,
589 _len: ir::Value,
590 ) -> WasmResult<()> {
591 Ok(())
592 }
593
594 fn translate_table_init(
595 &mut self,
596 _pos: FuncCursor,
597 _seg_index: u32,
598 _table_index: TableIndex,
599 _table: ir::Table,
600 _dst: ir::Value,
601 _src: ir::Value,
602 _len: ir::Value,
603 ) -> WasmResult<()> {
604 Ok(())
605 }
606
607 fn translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
608 Ok(())
609 }
610
611 fn translate_ref_func(
612 &mut self,
613 mut pos: FuncCursor,
614 _func_index: FuncIndex,
615 ) -> WasmResult<ir::Value> {
616 Ok(pos.ins().null(self.reference_type()))
617 }
618
619 fn translate_custom_global_get(
620 &mut self,
621 mut pos: FuncCursor,
622 _global_index: GlobalIndex,
623 ) -> WasmResult<ir::Value> {
624 Ok(pos.ins().iconst(I32, -1))
625 }
626
627 fn translate_custom_global_set(
628 &mut self,
629 _pos: FuncCursor,
630 _global_index: GlobalIndex,
631 _val: ir::Value,
632 ) -> WasmResult<()> {
633 Ok(())
634 }
635
636 fn translate_atomic_wait(
637 &mut self,
638 mut pos: FuncCursor,
639 _index: MemoryIndex,
640 _heap: Heap,
641 _addr: ir::Value,
642 _expected: ir::Value,
643 _timeout: ir::Value,
644 ) -> WasmResult<ir::Value> {
645 Ok(pos.ins().iconst(I32, -1))
646 }
647
648 fn translate_atomic_notify(
649 &mut self,
650 mut pos: FuncCursor,
651 _index: MemoryIndex,
652 _heap: Heap,
653 _addr: ir::Value,
654 _count: ir::Value,
655 ) -> WasmResult<ir::Value> {
656 Ok(pos.ins().iconst(I32, 0))
657 }
658
659 fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
660 unimplemented!()
661 }
662}
663
664impl TargetEnvironment for DummyEnvironment {
665 fn target_config(&self) -> TargetFrontendConfig {
666 self.info.config
667 }
668
669 fn heap_access_spectre_mitigation(&self) -> bool {
670 false
671 }
672}
673
674impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
675 fn declare_type_func(&mut self, wasm: WasmFuncType) -> WasmResult<()> {
676 let mut sig = ir::Signature::new(CallConv::Fast);
677 let mut cvt = |ty: &WasmType| {
678 let reference_type = match self.pointer_type() {
679 ir::types::I32 => ir::types::R32,
680 ir::types::I64 => ir::types::R64,
681 _ => panic!("unsupported pointer type"),
682 };
683 ir::AbiParam::new(match ty {
684 WasmType::I32 => ir::types::I32,
685 WasmType::I64 => ir::types::I64,
686 WasmType::F32 => ir::types::F32,
687 WasmType::F64 => ir::types::F64,
688 WasmType::V128 => ir::types::I8X16,
689 WasmType::FuncRef | WasmType::ExternRef => reference_type,
690 })
691 };
692 sig.params.extend(wasm.params().iter().map(&mut cvt));
693 sig.returns.extend(wasm.returns().iter().map(&mut cvt));
694 self.info.signatures.push(sig);
695 Ok(())
696 }
697
698 fn declare_func_import(
699 &mut self,
700 index: TypeIndex,
701 module: &'data str,
702 field: &'data str,
703 ) -> WasmResult<()> {
704 assert_eq!(
705 self.info.functions.len(),
706 self.info.imported_funcs.len(),
707 "Imported functions must be declared first"
708 );
709 self.info.functions.push(Exportable::new(index));
710 self.info
711 .imported_funcs
712 .push((String::from(module), String::from(field)));
713 Ok(())
714 }
715
716 fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()> {
717 self.info.functions.push(Exportable::new(index));
718 Ok(())
719 }
720
721 fn declare_global(&mut self, global: Global) -> WasmResult<()> {
722 self.info.globals.push(Exportable::new(global));
723 Ok(())
724 }
725
726 fn declare_global_import(
727 &mut self,
728 global: Global,
729 module: &'data str,
730 field: &'data str,
731 ) -> WasmResult<()> {
732 self.info.globals.push(Exportable::new(global));
733 self.info
734 .imported_globals
735 .push((String::from(module), String::from(field)));
736 Ok(())
737 }
738
739 fn declare_table(&mut self, table: Table) -> WasmResult<()> {
740 self.info.tables.push(Exportable::new(table));
741 Ok(())
742 }
743
744 fn declare_table_import(
745 &mut self,
746 table: Table,
747 module: &'data str,
748 field: &'data str,
749 ) -> WasmResult<()> {
750 self.info.tables.push(Exportable::new(table));
751 self.info
752 .imported_tables
753 .push((String::from(module), String::from(field)));
754 Ok(())
755 }
756
757 fn declare_table_elements(
758 &mut self,
759 _table_index: TableIndex,
760 _base: Option<GlobalIndex>,
761 _offset: u32,
762 _elements: Box<[FuncIndex]>,
763 ) -> WasmResult<()> {
764 Ok(())
766 }
767
768 fn declare_passive_element(
769 &mut self,
770 _elem_index: ElemIndex,
771 _segments: Box<[FuncIndex]>,
772 ) -> WasmResult<()> {
773 Ok(())
774 }
775
776 fn declare_passive_data(
777 &mut self,
778 _elem_index: DataIndex,
779 _segments: &'data [u8],
780 ) -> WasmResult<()> {
781 Ok(())
782 }
783
784 fn declare_memory(&mut self, memory: Memory) -> WasmResult<()> {
785 self.info.memories.push(Exportable::new(memory));
786 Ok(())
787 }
788
789 fn declare_memory_import(
790 &mut self,
791 memory: Memory,
792 module: &'data str,
793 field: &'data str,
794 ) -> WasmResult<()> {
795 self.info.memories.push(Exportable::new(memory));
796 self.info
797 .imported_memories
798 .push((String::from(module), String::from(field)));
799 Ok(())
800 }
801
802 fn declare_data_initialization(
803 &mut self,
804 _memory_index: MemoryIndex,
805 _base: Option<GlobalIndex>,
806 _offset: u64,
807 _data: &'data [u8],
808 ) -> WasmResult<()> {
809 Ok(())
811 }
812
813 fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()> {
814 self.info.functions[func_index]
815 .export_names
816 .push(String::from(name));
817 Ok(())
818 }
819
820 fn declare_table_export(
821 &mut self,
822 table_index: TableIndex,
823 name: &'data str,
824 ) -> WasmResult<()> {
825 self.info.tables[table_index]
826 .export_names
827 .push(String::from(name));
828 Ok(())
829 }
830
831 fn declare_memory_export(
832 &mut self,
833 memory_index: MemoryIndex,
834 name: &'data str,
835 ) -> WasmResult<()> {
836 self.info.memories[memory_index]
837 .export_names
838 .push(String::from(name));
839 Ok(())
840 }
841
842 fn declare_global_export(
843 &mut self,
844 global_index: GlobalIndex,
845 name: &'data str,
846 ) -> WasmResult<()> {
847 self.info.globals[global_index]
848 .export_names
849 .push(String::from(name));
850 Ok(())
851 }
852
853 fn declare_start_func(&mut self, func_index: FuncIndex) -> WasmResult<()> {
854 debug_assert!(self.info.start_func.is_none());
855 self.info.start_func = Some(func_index);
856 Ok(())
857 }
858
859 fn define_function_body(
860 &mut self,
861 mut validator: FuncValidator<ValidatorResources>,
862 body: FunctionBody<'data>,
863 ) -> WasmResult<()> {
864 self.func_bytecode_sizes
865 .push(body.get_binary_reader().bytes_remaining());
866 let func = {
867 let mut func_environ =
868 DummyFuncEnvironment::new(&self.info, self.expected_reachability.clone());
869 let func_index =
870 FuncIndex::new(self.get_num_func_imports() + self.info.function_bodies.len());
871
872 let sig = func_environ.vmctx_sig(self.get_func_type(func_index));
873 let mut func =
874 ir::Function::with_name_signature(UserFuncName::user(0, func_index.as_u32()), sig);
875
876 if self.debug_info {
877 func.collect_debug_info();
878 }
879
880 self.trans
881 .translate_body(&mut validator, body, &mut func, &mut func_environ)?;
882 func
883 };
884 self.info.function_bodies.push(func);
885 Ok(())
886 }
887
888 fn declare_module_name(&mut self, name: &'data str) {
889 self.module_name = Some(String::from(name));
890 }
891
892 fn declare_func_name(&mut self, func_index: FuncIndex, name: &'data str) {
893 self.function_names[func_index] = String::from(name);
894 }
895
896 fn wasm_features(&self) -> WasmFeatures {
897 WasmFeatures {
898 multi_value: true,
899 simd: true,
900 reference_types: true,
901 bulk_memory: true,
902 ..WasmFeatures::default()
903 }
904 }
905}