wasmer_compiler/translator/
environ.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
3use super::state::ModuleTranslationState;
4use crate::lib::std::string::ToString;
5use crate::lib::std::{boxed::Box, string::String, vec::Vec};
6use crate::translate_module;
7use crate::wasmparser::{Operator, ValType};
8use std::collections::HashMap;
9use std::convert::{TryFrom, TryInto};
10use std::ops::Range;
11use wasmer_types::FunctionType;
12use wasmer_types::entity::PrimaryMap;
13use wasmer_types::{
14    CustomSectionIndex, DataIndex, DataInitializer, DataInitializerLocation, ElemIndex,
15    ExportIndex, FunctionIndex, GlobalIndex, GlobalInit, GlobalType, ImportIndex,
16    LocalFunctionIndex, MemoryIndex, MemoryType, ModuleInfo, SignatureIndex, TableIndex,
17    TableInitializer, TableType,
18};
19use wasmer_types::{TagIndex, WasmResult};
20
21/// Contains function data: bytecode and its offset in the module.
22#[derive(Hash)]
23pub struct FunctionBodyData<'a> {
24    /// Function body bytecode.
25    pub data: &'a [u8],
26
27    /// Body offset relative to the module file.
28    pub module_offset: usize,
29}
30
31/// Trait for iterating over the operators of a Wasm Function
32pub trait FunctionBinaryReader<'a> {
33    /// Read a `count` indicating the number of times to call `read_local_decl`.
34    fn read_local_count(&mut self) -> WasmResult<u32>;
35
36    /// Read a `(count, value_type)` declaration of local variables of the same type.
37    fn read_local_decl(&mut self) -> WasmResult<(u32, ValType)>;
38
39    /// Reads the next available `Operator`.
40    fn read_operator(&mut self) -> WasmResult<Operator<'a>>;
41
42    /// Returns the current position.
43    fn current_position(&self) -> usize;
44
45    /// Returns the original position (with the offset)
46    fn original_position(&self) -> usize;
47
48    /// Returns the number of bytes remaining.
49    fn bytes_remaining(&self) -> usize;
50
51    /// Returns whether the readers has reached the end of the file.
52    fn eof(&self) -> bool;
53
54    /// Return the range (original offset, original offset + data length)
55    fn range(&self) -> Range<usize>;
56}
57
58/// The result of translating via `ModuleEnvironment`. Function bodies are not
59/// yet translated, and data initializers have not yet been copied out of the
60/// original buffer.
61/// The function bodies will be translated by a specific compiler backend.
62pub struct ModuleEnvironment<'data> {
63    /// ModuleInfo information.
64    pub module: ModuleInfo,
65
66    /// References to the function bodies.
67    pub function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
68
69    /// References to the data initializers.
70    pub data_initializers: Vec<DataInitializer<'data>>,
71
72    /// The decoded Wasm types for the module.
73    pub module_translation_state: Option<ModuleTranslationState>,
74}
75
76impl<'data> ModuleEnvironment<'data> {
77    /// Allocates the environment data structures.
78    pub fn new() -> Self {
79        Self {
80            module: ModuleInfo::new(),
81            function_body_inputs: PrimaryMap::new(),
82            data_initializers: Vec::new(),
83            module_translation_state: None,
84        }
85    }
86
87    /// Translate a wasm module using this environment. This consumes the
88    /// `ModuleEnvironment` and produces a `ModuleInfoTranslation`.
89    pub fn translate(mut self, data: &'data [u8]) -> WasmResult<Self> {
90        assert!(self.module_translation_state.is_none());
91        let module_translation_state = translate_module(data, &mut self)?;
92        self.module_translation_state = Some(module_translation_state);
93
94        Ok(self)
95    }
96
97    pub(crate) fn declare_export(&mut self, export: ExportIndex, name: &str) -> WasmResult<()> {
98        self.module.exports.insert(String::from(name), export);
99        Ok(())
100    }
101
102    pub(crate) fn declare_import(
103        &mut self,
104        import: ImportIndex,
105        module: &str,
106        field: &str,
107    ) -> WasmResult<()> {
108        self.module.imports.insert(
109            (
110                String::from(module),
111                String::from(field),
112                self.module.imports.len().try_into().unwrap(),
113            )
114                .into(),
115            import,
116        );
117        Ok(())
118    }
119
120    pub(crate) fn reserve_signatures(&mut self, num: u32) -> WasmResult<()> {
121        self.module
122            .signatures
123            .reserve_exact(usize::try_from(num).unwrap());
124        Ok(())
125    }
126
127    pub(crate) fn declare_signature(&mut self, sig: FunctionType) -> WasmResult<()> {
128        // TODO: Deduplicate signatures.
129        self.module.signatures.push(sig);
130        Ok(())
131    }
132
133    pub(crate) fn declare_func_import(
134        &mut self,
135        sig_index: SignatureIndex,
136        module: &str,
137        field: &str,
138    ) -> WasmResult<()> {
139        debug_assert_eq!(
140            self.module.functions.len(),
141            self.module.num_imported_functions,
142            "Imported functions must be declared first"
143        );
144        self.declare_import(
145            ImportIndex::Function(FunctionIndex::from_u32(
146                self.module.num_imported_functions as _,
147            )),
148            module,
149            field,
150        )?;
151        self.module.functions.push(sig_index);
152        self.module.num_imported_functions += 1;
153        Ok(())
154    }
155
156    pub(crate) fn declare_tag_import(
157        &mut self,
158        t: wasmparser::TagType,
159        module_name: &str,
160        field_name: &str,
161    ) -> WasmResult<()> {
162        debug_assert_eq!(
163            self.module.tags.len(),
164            self.module.num_imported_tags,
165            "Imported tags must be declared first"
166        );
167
168        let tag = SignatureIndex::from_u32(t.func_type_idx);
169        debug_assert!(
170            self.module
171                .signatures
172                .get(SignatureIndex::from_u32(t.func_type_idx))
173                .is_some(),
174            "Imported tags must mach a declared signature!"
175        );
176
177        self.declare_import(
178            ImportIndex::Tag(TagIndex::from_u32(self.module.num_imported_tags as _)),
179            module_name,
180            field_name,
181        )?;
182
183        self.module.num_imported_tags += 1;
184        self.module.tags.push(tag);
185
186        Ok(())
187    }
188
189    pub(crate) fn declare_table_import(
190        &mut self,
191        table: TableType,
192        module: &str,
193        field: &str,
194    ) -> WasmResult<()> {
195        debug_assert_eq!(
196            self.module.tables.len(),
197            self.module.num_imported_tables,
198            "Imported tables must be declared first"
199        );
200        self.declare_import(
201            ImportIndex::Table(TableIndex::from_u32(self.module.num_imported_tables as _)),
202            module,
203            field,
204        )?;
205        self.module.tables.push(table);
206        self.module.num_imported_tables += 1;
207        Ok(())
208    }
209
210    pub(crate) fn declare_memory_import(
211        &mut self,
212        memory: MemoryType,
213        module: &str,
214        field: &str,
215    ) -> WasmResult<()> {
216        debug_assert_eq!(
217            self.module.memories.len(),
218            self.module.num_imported_memories,
219            "Imported memories must be declared first"
220        );
221        self.declare_import(
222            ImportIndex::Memory(MemoryIndex::from_u32(
223                self.module.num_imported_memories as _,
224            )),
225            module,
226            field,
227        )?;
228        self.module.memories.push(memory);
229        self.module.num_imported_memories += 1;
230        Ok(())
231    }
232
233    pub(crate) fn declare_global_import(
234        &mut self,
235        global: GlobalType,
236        module: &str,
237        field: &str,
238    ) -> WasmResult<()> {
239        debug_assert_eq!(
240            self.module.globals.len(),
241            self.module.num_imported_globals,
242            "Imported globals must be declared first"
243        );
244        self.declare_import(
245            ImportIndex::Global(GlobalIndex::from_u32(self.module.num_imported_globals as _)),
246            module,
247            field,
248        )?;
249        self.module.globals.push(global);
250        self.module.num_imported_globals += 1;
251        Ok(())
252    }
253
254    pub(crate) fn finish_imports(&mut self) -> WasmResult<()> {
255        Ok(())
256    }
257
258    pub(crate) fn reserve_func_types(&mut self, num: u32) -> WasmResult<()> {
259        self.module
260            .functions
261            .reserve_exact(usize::try_from(num).unwrap());
262        self.function_body_inputs
263            .reserve_exact(usize::try_from(num).unwrap());
264        Ok(())
265    }
266
267    pub(crate) fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
268        self.module.functions.push(sig_index);
269        Ok(())
270    }
271
272    pub(crate) fn reserve_tables(&mut self, num: u32) -> WasmResult<()> {
273        self.module
274            .tables
275            .reserve_exact(usize::try_from(num).unwrap());
276        Ok(())
277    }
278
279    pub(crate) fn declare_table(&mut self, table: TableType) -> WasmResult<()> {
280        self.module.tables.push(table);
281        Ok(())
282    }
283
284    pub(crate) fn reserve_memories(&mut self, num: u32) -> WasmResult<()> {
285        self.module
286            .memories
287            .reserve_exact(usize::try_from(num).unwrap());
288        Ok(())
289    }
290
291    pub(crate) fn declare_memory(&mut self, memory: MemoryType) -> WasmResult<()> {
292        self.module.memories.push(memory);
293        Ok(())
294    }
295
296    pub(crate) fn reserve_tags(&mut self, num: u32) -> WasmResult<()> {
297        self.module
298            .tags
299            .reserve_exact(usize::try_from(num).unwrap());
300        Ok(())
301    }
302
303    pub(crate) fn declare_tag(&mut self, tag: SignatureIndex) -> WasmResult<()> {
304        self.module.tags.push(tag);
305        Ok(())
306    }
307
308    pub(crate) fn reserve_globals(&mut self, num: u32) -> WasmResult<()> {
309        self.module
310            .globals
311            .reserve_exact(usize::try_from(num).unwrap());
312        Ok(())
313    }
314
315    pub(crate) fn declare_global(
316        &mut self,
317        global: GlobalType,
318        initializer: GlobalInit,
319    ) -> WasmResult<()> {
320        self.module.globals.push(global);
321        self.module.global_initializers.push(initializer);
322        Ok(())
323    }
324
325    pub(crate) fn reserve_exports(&mut self, num: u32) -> WasmResult<()> {
326        self.module.exports.reserve(usize::try_from(num).unwrap());
327        Ok(())
328    }
329
330    pub(crate) fn declare_func_export(
331        &mut self,
332        func_index: FunctionIndex,
333        name: &str,
334    ) -> WasmResult<()> {
335        self.declare_export(ExportIndex::Function(func_index), name)
336    }
337
338    pub(crate) fn declare_table_export(
339        &mut self,
340        table_index: TableIndex,
341        name: &str,
342    ) -> WasmResult<()> {
343        self.declare_export(ExportIndex::Table(table_index), name)
344    }
345
346    pub(crate) fn declare_memory_export(
347        &mut self,
348        memory_index: MemoryIndex,
349        name: &str,
350    ) -> WasmResult<()> {
351        self.declare_export(ExportIndex::Memory(memory_index), name)
352    }
353
354    pub(crate) fn declare_tag_export(&mut self, tag_index: TagIndex, name: &str) -> WasmResult<()> {
355        self.declare_export(ExportIndex::Tag(tag_index), name)
356    }
357
358    pub(crate) fn declare_global_export(
359        &mut self,
360        global_index: GlobalIndex,
361        name: &str,
362    ) -> WasmResult<()> {
363        self.declare_export(ExportIndex::Global(global_index), name)
364    }
365
366    pub(crate) fn declare_start_function(&mut self, func_index: FunctionIndex) -> WasmResult<()> {
367        debug_assert!(self.module.start_function.is_none());
368        self.module.start_function = Some(func_index);
369        Ok(())
370    }
371
372    pub(crate) fn reserve_table_initializers(&mut self, num: u32) -> WasmResult<()> {
373        self.module
374            .table_initializers
375            .reserve_exact(usize::try_from(num).unwrap());
376        Ok(())
377    }
378
379    pub(crate) fn declare_table_initializers(
380        &mut self,
381        table_index: TableIndex,
382        base: Option<GlobalIndex>,
383        offset: usize,
384        elements: Box<[FunctionIndex]>,
385    ) -> WasmResult<()> {
386        self.module.table_initializers.push(TableInitializer {
387            table_index,
388            base,
389            offset,
390            elements,
391        });
392        Ok(())
393    }
394
395    pub(crate) fn declare_passive_element(
396        &mut self,
397        elem_index: ElemIndex,
398        segments: Box<[FunctionIndex]>,
399    ) -> WasmResult<()> {
400        let old = self.module.passive_elements.insert(elem_index, segments);
401        debug_assert!(
402            old.is_none(),
403            "should never get duplicate element indices, that would be a bug in `wasmer_compiler`'s \
404             translation"
405        );
406        Ok(())
407    }
408
409    pub(crate) fn define_function_body(
410        &mut self,
411        _module_translation_state: &ModuleTranslationState,
412        body_bytes: &'data [u8],
413        body_offset: usize,
414    ) -> WasmResult<()> {
415        self.function_body_inputs.push(FunctionBodyData {
416            data: body_bytes,
417            module_offset: body_offset,
418        });
419        Ok(())
420    }
421
422    pub(crate) fn reserve_data_initializers(&mut self, num: u32) -> WasmResult<()> {
423        self.data_initializers
424            .reserve_exact(usize::try_from(num).unwrap());
425        Ok(())
426    }
427
428    pub(crate) fn declare_data_initialization(
429        &mut self,
430        memory_index: MemoryIndex,
431        base: Option<GlobalIndex>,
432        offset: usize,
433        data: &'data [u8],
434    ) -> WasmResult<()> {
435        self.data_initializers.push(DataInitializer {
436            location: DataInitializerLocation {
437                memory_index,
438                base,
439                offset,
440            },
441            data,
442        });
443        Ok(())
444    }
445
446    pub(crate) fn reserve_passive_data(&mut self, count: u32) -> WasmResult<()> {
447        let count = usize::try_from(count).unwrap();
448        self.module.passive_data.reserve(count);
449        Ok(())
450    }
451
452    pub(crate) fn declare_passive_data(
453        &mut self,
454        data_index: DataIndex,
455        data: &'data [u8],
456    ) -> WasmResult<()> {
457        let old = self.module.passive_data.insert(data_index, Box::from(data));
458        debug_assert!(
459            old.is_none(),
460            "a module can't have duplicate indices, this would be a wasmer-compiler bug"
461        );
462        Ok(())
463    }
464
465    pub(crate) fn declare_module_name(&mut self, name: &'data str) -> WasmResult<()> {
466        self.module.name = Some(name.to_string());
467        Ok(())
468    }
469
470    pub(crate) fn declare_function_names(
471        &mut self,
472        functions: HashMap<FunctionIndex, String>,
473    ) -> WasmResult<()> {
474        self.module.function_names = functions;
475        Ok(())
476    }
477
478    /// Provides the number of imports up front. By default this does nothing, but
479    /// implementations can use this to preallocate memory if desired.
480    pub(crate) fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
481        Ok(())
482    }
483
484    /// Notifies the implementation that all exports have been declared.
485    pub(crate) fn finish_exports(&mut self) -> WasmResult<()> {
486        Ok(())
487    }
488
489    /// Indicates that a custom section has been found in the wasm file
490    pub(crate) fn custom_section(&mut self, name: &'data str, data: &'data [u8]) -> WasmResult<()> {
491        let custom_section = CustomSectionIndex::from_u32(
492            self.module.custom_sections_data.len().try_into().unwrap(),
493        );
494        self.module
495            .custom_sections
496            .insert(String::from(name), custom_section);
497        self.module.custom_sections_data.push(Box::from(data));
498        Ok(())
499    }
500}