1 //! "Dummy" implementations of `ModuleEnvironment` and `FuncEnvironment` for testing
2 //! wasm translation. For complete implementations of `ModuleEnvironment` and
3 //! `FuncEnvironment`, see [wasmtime-environ] in [Wasmtime].
4 //!
5 //! [wasmtime-environ]: https://crates.io/crates/wasmtime-environ
6 //! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
7 
8 use crate::environ::{
9     FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, WasmResult,
10 };
11 use crate::func_translator::FuncTranslator;
12 use crate::state::ModuleTranslationState;
13 use crate::translation_utils::{
14     DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
15     SignatureIndex, Table, TableIndex,
16 };
17 use core::convert::TryFrom;
18 use cranelift_codegen::cursor::FuncCursor;
19 use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
20 use cranelift_codegen::ir::types::*;
21 use cranelift_codegen::ir::{self, InstBuilder};
22 use cranelift_codegen::isa::TargetFrontendConfig;
23 use cranelift_entity::{EntityRef, PrimaryMap, SecondaryMap};
24 use std::boxed::Box;
25 use std::string::String;
26 use std::vec::Vec;
27 
28 /// Compute a `ir::ExternalName` for a given wasm function index.
get_func_name(func_index: FuncIndex) -> ir::ExternalName29 fn get_func_name(func_index: FuncIndex) -> ir::ExternalName {
30     ir::ExternalName::user(0, func_index.as_u32())
31 }
32 
33 /// A collection of names under which a given entity is exported.
34 pub struct Exportable<T> {
35     /// A wasm entity.
36     pub entity: T,
37 
38     /// Names under which the entity is exported.
39     pub export_names: Vec<String>,
40 }
41 
42 impl<T> Exportable<T> {
new(entity: T) -> Self43     pub fn new(entity: T) -> Self {
44         Self {
45             entity,
46             export_names: Vec::new(),
47         }
48     }
49 }
50 
51 /// The main state belonging to a `DummyEnvironment`. This is split out from
52 /// `DummyEnvironment` to allow it to be borrowed separately from the
53 /// `FuncTranslator` field.
54 pub struct DummyModuleInfo {
55     /// Target description relevant to frontends producing Cranelift IR.
56     config: TargetFrontendConfig,
57 
58     /// Signatures as provided by `declare_signature`.
59     pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
60 
61     /// Module and field names of imported functions as provided by `declare_func_import`.
62     pub imported_funcs: Vec<(String, String)>,
63 
64     /// Module and field names of imported globals as provided by `declare_global_import`.
65     pub imported_globals: Vec<(String, String)>,
66 
67     /// Module and field names of imported tables as provided by `declare_table_import`.
68     pub imported_tables: Vec<(String, String)>,
69 
70     /// Module and field names of imported memories as provided by `declare_memory_import`.
71     pub imported_memories: Vec<(String, String)>,
72 
73     /// Functions, imported and local.
74     pub functions: PrimaryMap<FuncIndex, Exportable<SignatureIndex>>,
75 
76     /// Function bodies.
77     pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
78 
79     /// Tables as provided by `declare_table`.
80     pub tables: PrimaryMap<TableIndex, Exportable<Table>>,
81 
82     /// Memories as provided by `declare_memory`.
83     pub memories: PrimaryMap<MemoryIndex, Exportable<Memory>>,
84 
85     /// Globals as provided by `declare_global`.
86     pub globals: PrimaryMap<GlobalIndex, Exportable<Global>>,
87 
88     /// The start function.
89     pub start_func: Option<FuncIndex>,
90 }
91 
92 impl DummyModuleInfo {
93     /// Creates a new `DummyModuleInfo` instance.
new(config: TargetFrontendConfig) -> Self94     pub fn new(config: TargetFrontendConfig) -> Self {
95         Self {
96             config,
97             signatures: PrimaryMap::new(),
98             imported_funcs: Vec::new(),
99             imported_globals: Vec::new(),
100             imported_tables: Vec::new(),
101             imported_memories: Vec::new(),
102             functions: PrimaryMap::new(),
103             function_bodies: PrimaryMap::new(),
104             tables: PrimaryMap::new(),
105             memories: PrimaryMap::new(),
106             globals: PrimaryMap::new(),
107             start_func: None,
108         }
109     }
110 }
111 
112 /// This `ModuleEnvironment` implementation is a "naïve" one, doing essentially nothing and
113 /// emitting placeholders when forced to. Don't try to execute code translated for this
114 /// environment, essentially here for translation debug purposes.
115 pub struct DummyEnvironment {
116     /// Module information.
117     pub info: DummyModuleInfo,
118 
119     /// Function translation.
120     trans: FuncTranslator,
121 
122     /// Vector of wasm bytecode size for each function.
123     pub func_bytecode_sizes: Vec<usize>,
124 
125     /// How to return from functions.
126     return_mode: ReturnMode,
127 
128     /// Instructs to collect debug data during translation.
129     debug_info: bool,
130 
131     /// Name of the module from the wasm file.
132     pub module_name: Option<String>,
133 
134     /// Function names.
135     function_names: SecondaryMap<FuncIndex, String>,
136 }
137 
138 impl DummyEnvironment {
139     /// Creates a new `DummyEnvironment` instance.
new(config: TargetFrontendConfig, return_mode: ReturnMode, debug_info: bool) -> Self140     pub fn new(config: TargetFrontendConfig, return_mode: ReturnMode, debug_info: bool) -> Self {
141         Self {
142             info: DummyModuleInfo::new(config),
143             trans: FuncTranslator::new(),
144             func_bytecode_sizes: Vec::new(),
145             return_mode,
146             debug_info,
147             module_name: None,
148             function_names: SecondaryMap::new(),
149         }
150     }
151 
152     /// Return a `DummyFuncEnvironment` for translating functions within this
153     /// `DummyEnvironment`.
func_env(&self) -> DummyFuncEnvironment154     pub fn func_env(&self) -> DummyFuncEnvironment {
155         DummyFuncEnvironment::new(&self.info, self.return_mode)
156     }
157 
get_func_type(&self, func_index: FuncIndex) -> SignatureIndex158     fn get_func_type(&self, func_index: FuncIndex) -> SignatureIndex {
159         self.info.functions[func_index].entity
160     }
161 
162     /// Return the number of imported functions within this `DummyEnvironment`.
get_num_func_imports(&self) -> usize163     pub fn get_num_func_imports(&self) -> usize {
164         self.info.imported_funcs.len()
165     }
166 
167     /// Return the name of the function, if a name for the function with
168     /// the corresponding index exists.
get_func_name(&self, func_index: FuncIndex) -> Option<&str>169     pub fn get_func_name(&self, func_index: FuncIndex) -> Option<&str> {
170         self.function_names.get(func_index).map(String::as_ref)
171     }
172 }
173 
174 /// The `FuncEnvironment` implementation for use by the `DummyEnvironment`.
175 pub struct DummyFuncEnvironment<'dummy_environment> {
176     pub mod_info: &'dummy_environment DummyModuleInfo,
177 
178     return_mode: ReturnMode,
179 }
180 
181 impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> {
new(mod_info: &'dummy_environment DummyModuleInfo, return_mode: ReturnMode) -> Self182     pub fn new(mod_info: &'dummy_environment DummyModuleInfo, return_mode: ReturnMode) -> Self {
183         Self {
184             mod_info,
185             return_mode,
186         }
187     }
188 
189     // Create a signature for `sigidx` amended with a `vmctx` argument after the standard wasm
190     // arguments.
vmctx_sig(&self, sigidx: SignatureIndex) -> ir::Signature191     fn vmctx_sig(&self, sigidx: SignatureIndex) -> ir::Signature {
192         let mut sig = self.mod_info.signatures[sigidx].clone();
193         sig.params.push(ir::AbiParam::special(
194             self.pointer_type(),
195             ir::ArgumentPurpose::VMContext,
196         ));
197         sig
198     }
199 }
200 
201 impl<'dummy_environment> TargetEnvironment for DummyFuncEnvironment<'dummy_environment> {
target_config(&self) -> TargetFrontendConfig202     fn target_config(&self) -> TargetFrontendConfig {
203         self.mod_info.config
204     }
205 }
206 
207 impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> {
return_mode(&self) -> ReturnMode208     fn return_mode(&self) -> ReturnMode {
209         self.return_mode
210     }
211 
make_global( &mut self, func: &mut ir::Function, index: GlobalIndex, ) -> WasmResult<GlobalVariable>212     fn make_global(
213         &mut self,
214         func: &mut ir::Function,
215         index: GlobalIndex,
216     ) -> WasmResult<GlobalVariable> {
217         // Just create a dummy `vmctx` global.
218         let offset = i32::try_from((index.index() * 8) + 8).unwrap().into();
219         let vmctx = func.create_global_value(ir::GlobalValueData::VMContext {});
220         Ok(GlobalVariable::Memory {
221             gv: vmctx,
222             offset,
223             ty: self.mod_info.globals[index].entity.ty,
224         })
225     }
226 
make_heap(&mut self, func: &mut ir::Function, _index: MemoryIndex) -> WasmResult<ir::Heap>227     fn make_heap(&mut self, func: &mut ir::Function, _index: MemoryIndex) -> WasmResult<ir::Heap> {
228         // Create a static heap whose base address is stored at `vmctx+0`.
229         let addr = func.create_global_value(ir::GlobalValueData::VMContext);
230         let gv = func.create_global_value(ir::GlobalValueData::Load {
231             base: addr,
232             offset: Offset32::new(0),
233             global_type: self.pointer_type(),
234             readonly: true,
235         });
236 
237         Ok(func.create_heap(ir::HeapData {
238             base: gv,
239             min_size: 0.into(),
240             offset_guard_size: 0x8000_0000.into(),
241             style: ir::HeapStyle::Static {
242                 bound: 0x1_0000_0000.into(),
243             },
244             index_type: I32,
245         }))
246     }
247 
make_table(&mut self, func: &mut ir::Function, _index: TableIndex) -> WasmResult<ir::Table>248     fn make_table(&mut self, func: &mut ir::Function, _index: TableIndex) -> WasmResult<ir::Table> {
249         // Create a table whose base address is stored at `vmctx+0`.
250         let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
251         let base_gv = func.create_global_value(ir::GlobalValueData::Load {
252             base: vmctx,
253             offset: Offset32::new(0),
254             global_type: self.pointer_type(),
255             readonly: true, // when tables in wasm become "growable", revisit whether this can be readonly or not.
256         });
257         let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
258             base: vmctx,
259             offset: Offset32::new(0),
260             global_type: I32,
261             readonly: true,
262         });
263 
264         Ok(func.create_table(ir::TableData {
265             base_gv,
266             min_size: Uimm64::new(0),
267             bound_gv,
268             element_size: Uimm64::from(u64::from(self.pointer_bytes()) * 2),
269             index_type: I32,
270         }))
271     }
272 
make_indirect_sig( &mut self, func: &mut ir::Function, index: SignatureIndex, ) -> WasmResult<ir::SigRef>273     fn make_indirect_sig(
274         &mut self,
275         func: &mut ir::Function,
276         index: SignatureIndex,
277     ) -> WasmResult<ir::SigRef> {
278         // A real implementation would probably change the calling convention and add `vmctx` and
279         // signature index arguments.
280         Ok(func.import_signature(self.vmctx_sig(index)))
281     }
282 
make_direct_func( &mut self, func: &mut ir::Function, index: FuncIndex, ) -> WasmResult<ir::FuncRef>283     fn make_direct_func(
284         &mut self,
285         func: &mut ir::Function,
286         index: FuncIndex,
287     ) -> WasmResult<ir::FuncRef> {
288         let sigidx = self.mod_info.functions[index].entity;
289         // A real implementation would probably add a `vmctx` argument.
290         // And maybe attempt some signature de-duplication.
291         let signature = func.import_signature(self.vmctx_sig(sigidx));
292         let name = get_func_name(index);
293         Ok(func.import_function(ir::ExtFuncData {
294             name,
295             signature,
296             colocated: false,
297         }))
298     }
299 
translate_call_indirect( &mut self, mut pos: FuncCursor, _table_index: TableIndex, _table: ir::Table, _sig_index: SignatureIndex, sig_ref: ir::SigRef, callee: ir::Value, call_args: &[ir::Value], ) -> WasmResult<ir::Inst>300     fn translate_call_indirect(
301         &mut self,
302         mut pos: FuncCursor,
303         _table_index: TableIndex,
304         _table: ir::Table,
305         _sig_index: SignatureIndex,
306         sig_ref: ir::SigRef,
307         callee: ir::Value,
308         call_args: &[ir::Value],
309     ) -> WasmResult<ir::Inst> {
310         // Pass the current function's vmctx parameter on to the callee.
311         let vmctx = pos
312             .func
313             .special_param(ir::ArgumentPurpose::VMContext)
314             .expect("Missing vmctx parameter");
315 
316         // The `callee` value is an index into a table of function pointers.
317         // Apparently, that table is stored at absolute address 0 in this dummy environment.
318         // TODO: Generate bounds checking code.
319         let ptr = self.pointer_type();
320         let callee_offset = if ptr == I32 {
321             pos.ins().imul_imm(callee, 4)
322         } else {
323             let ext = pos.ins().uextend(I64, callee);
324             pos.ins().imul_imm(ext, 4)
325         };
326         let mflags = ir::MemFlags::trusted();
327         let func_ptr = pos.ins().load(ptr, mflags, callee_offset, 0);
328 
329         // Build a value list for the indirect call instruction containing the callee, call_args,
330         // and the vmctx parameter.
331         let mut args = ir::ValueList::default();
332         args.push(func_ptr, &mut pos.func.dfg.value_lists);
333         args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists);
334         args.push(vmctx, &mut pos.func.dfg.value_lists);
335 
336         Ok(pos
337             .ins()
338             .CallIndirect(ir::Opcode::CallIndirect, INVALID, sig_ref, args)
339             .0)
340     }
341 
translate_call( &mut self, mut pos: FuncCursor, _callee_index: FuncIndex, callee: ir::FuncRef, call_args: &[ir::Value], ) -> WasmResult<ir::Inst>342     fn translate_call(
343         &mut self,
344         mut pos: FuncCursor,
345         _callee_index: FuncIndex,
346         callee: ir::FuncRef,
347         call_args: &[ir::Value],
348     ) -> WasmResult<ir::Inst> {
349         // Pass the current function's vmctx parameter on to the callee.
350         let vmctx = pos
351             .func
352             .special_param(ir::ArgumentPurpose::VMContext)
353             .expect("Missing vmctx parameter");
354 
355         // Build a value list for the call instruction containing the call_args and the vmctx
356         // parameter.
357         let mut args = ir::ValueList::default();
358         args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists);
359         args.push(vmctx, &mut pos.func.dfg.value_lists);
360 
361         Ok(pos.ins().Call(ir::Opcode::Call, INVALID, callee, args).0)
362     }
363 
translate_memory_grow( &mut self, mut pos: FuncCursor, _index: MemoryIndex, _heap: ir::Heap, _val: ir::Value, ) -> WasmResult<ir::Value>364     fn translate_memory_grow(
365         &mut self,
366         mut pos: FuncCursor,
367         _index: MemoryIndex,
368         _heap: ir::Heap,
369         _val: ir::Value,
370     ) -> WasmResult<ir::Value> {
371         Ok(pos.ins().iconst(I32, -1))
372     }
373 
translate_memory_size( &mut self, mut pos: FuncCursor, _index: MemoryIndex, _heap: ir::Heap, ) -> WasmResult<ir::Value>374     fn translate_memory_size(
375         &mut self,
376         mut pos: FuncCursor,
377         _index: MemoryIndex,
378         _heap: ir::Heap,
379     ) -> WasmResult<ir::Value> {
380         Ok(pos.ins().iconst(I32, -1))
381     }
382 
translate_memory_copy( &mut self, _pos: FuncCursor, _index: MemoryIndex, _heap: ir::Heap, _dst: ir::Value, _src: ir::Value, _len: ir::Value, ) -> WasmResult<()>383     fn translate_memory_copy(
384         &mut self,
385         _pos: FuncCursor,
386         _index: MemoryIndex,
387         _heap: ir::Heap,
388         _dst: ir::Value,
389         _src: ir::Value,
390         _len: ir::Value,
391     ) -> WasmResult<()> {
392         Ok(())
393     }
394 
translate_memory_fill( &mut self, _pos: FuncCursor, _index: MemoryIndex, _heap: ir::Heap, _dst: ir::Value, _val: ir::Value, _len: ir::Value, ) -> WasmResult<()>395     fn translate_memory_fill(
396         &mut self,
397         _pos: FuncCursor,
398         _index: MemoryIndex,
399         _heap: ir::Heap,
400         _dst: ir::Value,
401         _val: ir::Value,
402         _len: ir::Value,
403     ) -> WasmResult<()> {
404         Ok(())
405     }
406 
translate_memory_init( &mut self, _pos: FuncCursor, _index: MemoryIndex, _heap: ir::Heap, _seg_index: u32, _dst: ir::Value, _src: ir::Value, _len: ir::Value, ) -> WasmResult<()>407     fn translate_memory_init(
408         &mut self,
409         _pos: FuncCursor,
410         _index: MemoryIndex,
411         _heap: ir::Heap,
412         _seg_index: u32,
413         _dst: ir::Value,
414         _src: ir::Value,
415         _len: ir::Value,
416     ) -> WasmResult<()> {
417         Ok(())
418     }
419 
translate_data_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()>420     fn translate_data_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
421         Ok(())
422     }
423 
translate_table_size( &mut self, mut pos: FuncCursor, _index: TableIndex, _table: ir::Table, ) -> WasmResult<ir::Value>424     fn translate_table_size(
425         &mut self,
426         mut pos: FuncCursor,
427         _index: TableIndex,
428         _table: ir::Table,
429     ) -> WasmResult<ir::Value> {
430         Ok(pos.ins().iconst(I32, -1))
431     }
432 
translate_table_grow( &mut self, mut pos: FuncCursor, _table_index: u32, _delta: ir::Value, _init_value: ir::Value, ) -> WasmResult<ir::Value>433     fn translate_table_grow(
434         &mut self,
435         mut pos: FuncCursor,
436         _table_index: u32,
437         _delta: ir::Value,
438         _init_value: ir::Value,
439     ) -> WasmResult<ir::Value> {
440         Ok(pos.ins().iconst(I32, -1))
441     }
442 
translate_table_get( &mut self, mut pos: FuncCursor, _table_index: u32, _index: ir::Value, ) -> WasmResult<ir::Value>443     fn translate_table_get(
444         &mut self,
445         mut pos: FuncCursor,
446         _table_index: u32,
447         _index: ir::Value,
448     ) -> WasmResult<ir::Value> {
449         Ok(pos.ins().null(self.reference_type()))
450     }
451 
translate_table_set( &mut self, _pos: FuncCursor, _table_index: u32, _value: ir::Value, _index: ir::Value, ) -> WasmResult<()>452     fn translate_table_set(
453         &mut self,
454         _pos: FuncCursor,
455         _table_index: u32,
456         _value: ir::Value,
457         _index: ir::Value,
458     ) -> WasmResult<()> {
459         Ok(())
460     }
461 
translate_table_copy( &mut self, _pos: FuncCursor, _dst_index: TableIndex, _dst_table: ir::Table, _src_index: TableIndex, _src_table: ir::Table, _dst: ir::Value, _src: ir::Value, _len: ir::Value, ) -> WasmResult<()>462     fn translate_table_copy(
463         &mut self,
464         _pos: FuncCursor,
465         _dst_index: TableIndex,
466         _dst_table: ir::Table,
467         _src_index: TableIndex,
468         _src_table: ir::Table,
469         _dst: ir::Value,
470         _src: ir::Value,
471         _len: ir::Value,
472     ) -> WasmResult<()> {
473         Ok(())
474     }
475 
translate_table_fill( &mut self, _pos: FuncCursor, _table_index: u32, _dst: ir::Value, _val: ir::Value, _len: ir::Value, ) -> WasmResult<()>476     fn translate_table_fill(
477         &mut self,
478         _pos: FuncCursor,
479         _table_index: u32,
480         _dst: ir::Value,
481         _val: ir::Value,
482         _len: ir::Value,
483     ) -> WasmResult<()> {
484         Ok(())
485     }
486 
translate_table_init( &mut self, _pos: FuncCursor, _seg_index: u32, _table_index: TableIndex, _table: ir::Table, _dst: ir::Value, _src: ir::Value, _len: ir::Value, ) -> WasmResult<()>487     fn translate_table_init(
488         &mut self,
489         _pos: FuncCursor,
490         _seg_index: u32,
491         _table_index: TableIndex,
492         _table: ir::Table,
493         _dst: ir::Value,
494         _src: ir::Value,
495         _len: ir::Value,
496     ) -> WasmResult<()> {
497         Ok(())
498     }
499 
translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()>500     fn translate_elem_drop(&mut self, _pos: FuncCursor, _seg_index: u32) -> WasmResult<()> {
501         Ok(())
502     }
503 
translate_ref_func( &mut self, mut pos: FuncCursor, _func_index: u32, ) -> WasmResult<ir::Value>504     fn translate_ref_func(
505         &mut self,
506         mut pos: FuncCursor,
507         _func_index: u32,
508     ) -> WasmResult<ir::Value> {
509         Ok(pos.ins().null(self.reference_type()))
510     }
511 
translate_custom_global_get( &mut self, mut pos: FuncCursor, _global_index: GlobalIndex, ) -> WasmResult<ir::Value>512     fn translate_custom_global_get(
513         &mut self,
514         mut pos: FuncCursor,
515         _global_index: GlobalIndex,
516     ) -> WasmResult<ir::Value> {
517         Ok(pos.ins().iconst(I32, -1))
518     }
519 
translate_custom_global_set( &mut self, _pos: FuncCursor, _global_index: GlobalIndex, _val: ir::Value, ) -> WasmResult<()>520     fn translate_custom_global_set(
521         &mut self,
522         _pos: FuncCursor,
523         _global_index: GlobalIndex,
524         _val: ir::Value,
525     ) -> WasmResult<()> {
526         Ok(())
527     }
528 }
529 
530 impl TargetEnvironment for DummyEnvironment {
target_config(&self) -> TargetFrontendConfig531     fn target_config(&self) -> TargetFrontendConfig {
532         self.info.config
533     }
534 }
535 
536 impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()>537     fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()> {
538         self.info.signatures.push(sig);
539         Ok(())
540     }
541 
declare_func_import( &mut self, sig_index: SignatureIndex, module: &'data str, field: &'data str, ) -> WasmResult<()>542     fn declare_func_import(
543         &mut self,
544         sig_index: SignatureIndex,
545         module: &'data str,
546         field: &'data str,
547     ) -> WasmResult<()> {
548         assert_eq!(
549             self.info.functions.len(),
550             self.info.imported_funcs.len(),
551             "Imported functions must be declared first"
552         );
553         self.info.functions.push(Exportable::new(sig_index));
554         self.info
555             .imported_funcs
556             .push((String::from(module), String::from(field)));
557         Ok(())
558     }
559 
declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()>560     fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
561         self.info.functions.push(Exportable::new(sig_index));
562         Ok(())
563     }
564 
declare_global(&mut self, global: Global) -> WasmResult<()>565     fn declare_global(&mut self, global: Global) -> WasmResult<()> {
566         self.info.globals.push(Exportable::new(global));
567         Ok(())
568     }
569 
declare_global_import( &mut self, global: Global, module: &'data str, field: &'data str, ) -> WasmResult<()>570     fn declare_global_import(
571         &mut self,
572         global: Global,
573         module: &'data str,
574         field: &'data str,
575     ) -> WasmResult<()> {
576         self.info.globals.push(Exportable::new(global));
577         self.info
578             .imported_globals
579             .push((String::from(module), String::from(field)));
580         Ok(())
581     }
582 
declare_table(&mut self, table: Table) -> WasmResult<()>583     fn declare_table(&mut self, table: Table) -> WasmResult<()> {
584         self.info.tables.push(Exportable::new(table));
585         Ok(())
586     }
587 
declare_table_import( &mut self, table: Table, module: &'data str, field: &'data str, ) -> WasmResult<()>588     fn declare_table_import(
589         &mut self,
590         table: Table,
591         module: &'data str,
592         field: &'data str,
593     ) -> WasmResult<()> {
594         self.info.tables.push(Exportable::new(table));
595         self.info
596             .imported_tables
597             .push((String::from(module), String::from(field)));
598         Ok(())
599     }
600 
declare_table_elements( &mut self, _table_index: TableIndex, _base: Option<GlobalIndex>, _offset: usize, _elements: Box<[FuncIndex]>, ) -> WasmResult<()>601     fn declare_table_elements(
602         &mut self,
603         _table_index: TableIndex,
604         _base: Option<GlobalIndex>,
605         _offset: usize,
606         _elements: Box<[FuncIndex]>,
607     ) -> WasmResult<()> {
608         // We do nothing
609         Ok(())
610     }
611 
declare_passive_element( &mut self, _elem_index: ElemIndex, _segments: Box<[FuncIndex]>, ) -> WasmResult<()>612     fn declare_passive_element(
613         &mut self,
614         _elem_index: ElemIndex,
615         _segments: Box<[FuncIndex]>,
616     ) -> WasmResult<()> {
617         Ok(())
618     }
619 
declare_passive_data( &mut self, _elem_index: DataIndex, _segments: &'data [u8], ) -> WasmResult<()>620     fn declare_passive_data(
621         &mut self,
622         _elem_index: DataIndex,
623         _segments: &'data [u8],
624     ) -> WasmResult<()> {
625         Ok(())
626     }
627 
declare_memory(&mut self, memory: Memory) -> WasmResult<()>628     fn declare_memory(&mut self, memory: Memory) -> WasmResult<()> {
629         self.info.memories.push(Exportable::new(memory));
630         Ok(())
631     }
632 
declare_memory_import( &mut self, memory: Memory, module: &'data str, field: &'data str, ) -> WasmResult<()>633     fn declare_memory_import(
634         &mut self,
635         memory: Memory,
636         module: &'data str,
637         field: &'data str,
638     ) -> WasmResult<()> {
639         self.info.memories.push(Exportable::new(memory));
640         self.info
641             .imported_memories
642             .push((String::from(module), String::from(field)));
643         Ok(())
644     }
645 
declare_data_initialization( &mut self, _memory_index: MemoryIndex, _base: Option<GlobalIndex>, _offset: usize, _data: &'data [u8], ) -> WasmResult<()>646     fn declare_data_initialization(
647         &mut self,
648         _memory_index: MemoryIndex,
649         _base: Option<GlobalIndex>,
650         _offset: usize,
651         _data: &'data [u8],
652     ) -> WasmResult<()> {
653         // We do nothing
654         Ok(())
655     }
656 
declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>657     fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()> {
658         self.info.functions[func_index]
659             .export_names
660             .push(String::from(name));
661         Ok(())
662     }
663 
declare_table_export( &mut self, table_index: TableIndex, name: &'data str, ) -> WasmResult<()>664     fn declare_table_export(
665         &mut self,
666         table_index: TableIndex,
667         name: &'data str,
668     ) -> WasmResult<()> {
669         self.info.tables[table_index]
670             .export_names
671             .push(String::from(name));
672         Ok(())
673     }
674 
declare_memory_export( &mut self, memory_index: MemoryIndex, name: &'data str, ) -> WasmResult<()>675     fn declare_memory_export(
676         &mut self,
677         memory_index: MemoryIndex,
678         name: &'data str,
679     ) -> WasmResult<()> {
680         self.info.memories[memory_index]
681             .export_names
682             .push(String::from(name));
683         Ok(())
684     }
685 
declare_global_export( &mut self, global_index: GlobalIndex, name: &'data str, ) -> WasmResult<()>686     fn declare_global_export(
687         &mut self,
688         global_index: GlobalIndex,
689         name: &'data str,
690     ) -> WasmResult<()> {
691         self.info.globals[global_index]
692             .export_names
693             .push(String::from(name));
694         Ok(())
695     }
696 
declare_start_func(&mut self, func_index: FuncIndex) -> WasmResult<()>697     fn declare_start_func(&mut self, func_index: FuncIndex) -> WasmResult<()> {
698         debug_assert!(self.info.start_func.is_none());
699         self.info.start_func = Some(func_index);
700         Ok(())
701     }
702 
define_function_body( &mut self, module_translation_state: &ModuleTranslationState, body_bytes: &'data [u8], body_offset: usize, ) -> WasmResult<()>703     fn define_function_body(
704         &mut self,
705         module_translation_state: &ModuleTranslationState,
706         body_bytes: &'data [u8],
707         body_offset: usize,
708     ) -> WasmResult<()> {
709         let func = {
710             let mut func_environ = DummyFuncEnvironment::new(&self.info, self.return_mode);
711             let func_index =
712                 FuncIndex::new(self.get_num_func_imports() + self.info.function_bodies.len());
713             let name = get_func_name(func_index);
714             let sig = func_environ.vmctx_sig(self.get_func_type(func_index));
715             let mut func = ir::Function::with_name_signature(name, sig);
716             if self.debug_info {
717                 func.collect_debug_info();
718             }
719             self.trans.translate(
720                 module_translation_state,
721                 body_bytes,
722                 body_offset,
723                 &mut func,
724                 &mut func_environ,
725             )?;
726             func
727         };
728         self.func_bytecode_sizes.push(body_bytes.len());
729         self.info.function_bodies.push(func);
730         Ok(())
731     }
732 
declare_module_name(&mut self, name: &'data str) -> WasmResult<()>733     fn declare_module_name(&mut self, name: &'data str) -> WasmResult<()> {
734         self.module_name = Some(String::from(name));
735         Ok(())
736     }
737 
declare_func_name(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>738     fn declare_func_name(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()> {
739         self.function_names[func_index] = String::from(name);
740         Ok(())
741     }
742 }
743