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, InitExpr,
16    LocalFunctionIndex, MemoryIndex, MemoryType, ModuleInfo, SignatureHash, SignatureIndex,
17    TableIndex, 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.validate_signature_hashes()?;
93        self.module_translation_state = Some(module_translation_state);
94
95        Ok(self)
96    }
97
98    pub(crate) fn declare_export(&mut self, export: ExportIndex, name: &str) -> WasmResult<()> {
99        self.module.exports.insert(String::from(name), export);
100        Ok(())
101    }
102
103    pub(crate) fn declare_import(
104        &mut self,
105        import: ImportIndex,
106        module: &str,
107        field: &str,
108    ) -> WasmResult<()> {
109        self.module.imports.insert(
110            (
111                String::from(module),
112                String::from(field),
113                self.module.imports.len().try_into().unwrap(),
114            )
115                .into(),
116            import,
117        );
118        Ok(())
119    }
120
121    pub(crate) fn reserve_signatures(&mut self, num: u32) -> WasmResult<()> {
122        self.module
123            .signatures
124            .reserve_exact(usize::try_from(num).unwrap());
125        Ok(())
126    }
127
128    pub(crate) fn declare_signature(&mut self, sig: FunctionType) -> WasmResult<()> {
129        // TODO: Deduplicate signatures.
130        let signature_hash = SignatureHash::new(sig.signature_hash());
131        self.module.signatures.push(sig);
132        self.module.signature_hashes.push(signature_hash);
133        Ok(())
134    }
135
136    pub(crate) fn declare_func_import(
137        &mut self,
138        sig_index: SignatureIndex,
139        module: &str,
140        field: &str,
141    ) -> WasmResult<()> {
142        debug_assert_eq!(
143            self.module.functions.len(),
144            self.module.num_imported_functions,
145            "Imported functions must be declared first"
146        );
147        self.declare_import(
148            ImportIndex::Function(FunctionIndex::from_u32(
149                self.module.num_imported_functions as _,
150            )),
151            module,
152            field,
153        )?;
154        self.module.functions.push(sig_index);
155        self.module.num_imported_functions += 1;
156        Ok(())
157    }
158
159    pub(crate) fn declare_tag_import(
160        &mut self,
161        t: wasmparser::TagType,
162        module_name: &str,
163        field_name: &str,
164    ) -> WasmResult<()> {
165        debug_assert_eq!(
166            self.module.tags.len(),
167            self.module.num_imported_tags,
168            "Imported tags must be declared first"
169        );
170
171        let tag = SignatureIndex::from_u32(t.func_type_idx);
172        debug_assert!(
173            self.module
174                .signatures
175                .get(SignatureIndex::from_u32(t.func_type_idx))
176                .is_some(),
177            "Imported tags must mach a declared signature!"
178        );
179
180        self.declare_import(
181            ImportIndex::Tag(TagIndex::from_u32(self.module.num_imported_tags as _)),
182            module_name,
183            field_name,
184        )?;
185
186        self.module.num_imported_tags += 1;
187        self.module.tags.push(tag);
188
189        Ok(())
190    }
191
192    pub(crate) fn declare_table_import(
193        &mut self,
194        table: TableType,
195        module: &str,
196        field: &str,
197    ) -> WasmResult<()> {
198        debug_assert_eq!(
199            self.module.tables.len(),
200            self.module.num_imported_tables,
201            "Imported tables must be declared first"
202        );
203        self.declare_import(
204            ImportIndex::Table(TableIndex::from_u32(self.module.num_imported_tables as _)),
205            module,
206            field,
207        )?;
208        self.module.tables.push(table);
209        self.module.num_imported_tables += 1;
210        Ok(())
211    }
212
213    pub(crate) fn declare_memory_import(
214        &mut self,
215        memory: MemoryType,
216        module: &str,
217        field: &str,
218    ) -> WasmResult<()> {
219        debug_assert_eq!(
220            self.module.memories.len(),
221            self.module.num_imported_memories,
222            "Imported memories must be declared first"
223        );
224        self.declare_import(
225            ImportIndex::Memory(MemoryIndex::from_u32(
226                self.module.num_imported_memories as _,
227            )),
228            module,
229            field,
230        )?;
231        self.module.memories.push(memory);
232        self.module.num_imported_memories += 1;
233        Ok(())
234    }
235
236    pub(crate) fn declare_global_import(
237        &mut self,
238        global: GlobalType,
239        module: &str,
240        field: &str,
241    ) -> WasmResult<()> {
242        debug_assert_eq!(
243            self.module.globals.len(),
244            self.module.num_imported_globals,
245            "Imported globals must be declared first"
246        );
247        self.declare_import(
248            ImportIndex::Global(GlobalIndex::from_u32(self.module.num_imported_globals as _)),
249            module,
250            field,
251        )?;
252        self.module.globals.push(global);
253        self.module.num_imported_globals += 1;
254        Ok(())
255    }
256
257    pub(crate) fn finish_imports(&mut self) -> WasmResult<()> {
258        Ok(())
259    }
260
261    pub(crate) fn reserve_func_types(&mut self, num: u32) -> WasmResult<()> {
262        self.module
263            .functions
264            .reserve_exact(usize::try_from(num).unwrap());
265        self.function_body_inputs
266            .reserve_exact(usize::try_from(num).unwrap());
267        Ok(())
268    }
269
270    pub(crate) fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
271        self.module.functions.push(sig_index);
272        Ok(())
273    }
274
275    pub(crate) fn reserve_tables(&mut self, num: u32) -> WasmResult<()> {
276        self.module
277            .tables
278            .reserve_exact(usize::try_from(num).unwrap());
279        Ok(())
280    }
281
282    pub(crate) fn declare_table(&mut self, table: TableType) -> WasmResult<()> {
283        self.module.tables.push(table);
284        Ok(())
285    }
286
287    pub(crate) fn reserve_memories(&mut self, num: u32) -> WasmResult<()> {
288        self.module
289            .memories
290            .reserve_exact(usize::try_from(num).unwrap());
291        Ok(())
292    }
293
294    pub(crate) fn declare_memory(&mut self, memory: MemoryType) -> WasmResult<()> {
295        self.module.memories.push(memory);
296        Ok(())
297    }
298
299    pub(crate) fn reserve_tags(&mut self, num: u32) -> WasmResult<()> {
300        self.module
301            .tags
302            .reserve_exact(usize::try_from(num).unwrap());
303        Ok(())
304    }
305
306    pub(crate) fn declare_tag(&mut self, tag: SignatureIndex) -> WasmResult<()> {
307        self.module.tags.push(tag);
308        Ok(())
309    }
310
311    pub(crate) fn reserve_globals(&mut self, num: u32) -> WasmResult<()> {
312        self.module
313            .globals
314            .reserve_exact(usize::try_from(num).unwrap());
315        Ok(())
316    }
317
318    pub(crate) fn declare_global(
319        &mut self,
320        global: GlobalType,
321        initializer: GlobalInit,
322    ) -> WasmResult<()> {
323        self.module.globals.push(global);
324        self.module.global_initializers.push(initializer);
325        Ok(())
326    }
327
328    pub(crate) fn reserve_exports(&mut self, num: u32) -> WasmResult<()> {
329        self.module.exports.reserve(usize::try_from(num).unwrap());
330        Ok(())
331    }
332
333    pub(crate) fn declare_func_export(
334        &mut self,
335        func_index: FunctionIndex,
336        name: &str,
337    ) -> WasmResult<()> {
338        self.declare_export(ExportIndex::Function(func_index), name)
339    }
340
341    pub(crate) fn declare_table_export(
342        &mut self,
343        table_index: TableIndex,
344        name: &str,
345    ) -> WasmResult<()> {
346        self.declare_export(ExportIndex::Table(table_index), name)
347    }
348
349    pub(crate) fn declare_memory_export(
350        &mut self,
351        memory_index: MemoryIndex,
352        name: &str,
353    ) -> WasmResult<()> {
354        self.declare_export(ExportIndex::Memory(memory_index), name)
355    }
356
357    pub(crate) fn declare_tag_export(&mut self, tag_index: TagIndex, name: &str) -> WasmResult<()> {
358        self.declare_export(ExportIndex::Tag(tag_index), name)
359    }
360
361    pub(crate) fn declare_global_export(
362        &mut self,
363        global_index: GlobalIndex,
364        name: &str,
365    ) -> WasmResult<()> {
366        self.declare_export(ExportIndex::Global(global_index), name)
367    }
368
369    pub(crate) fn declare_start_function(&mut self, func_index: FunctionIndex) -> WasmResult<()> {
370        debug_assert!(self.module.start_function.is_none());
371        self.module.start_function = Some(func_index);
372        Ok(())
373    }
374
375    pub(crate) fn reserve_table_initializers(&mut self, num: u32) -> WasmResult<()> {
376        self.module
377            .table_initializers
378            .reserve_exact(usize::try_from(num).unwrap());
379        Ok(())
380    }
381
382    pub(crate) fn declare_table_initializers(
383        &mut self,
384        table_index: TableIndex,
385        offset_expr: InitExpr,
386        elements: Box<[FunctionIndex]>,
387    ) -> WasmResult<()> {
388        self.module.table_initializers.push(TableInitializer {
389            table_index,
390            offset_expr,
391            elements,
392        });
393        Ok(())
394    }
395
396    pub(crate) fn declare_passive_element(
397        &mut self,
398        elem_index: ElemIndex,
399        segments: Box<[FunctionIndex]>,
400    ) -> WasmResult<()> {
401        let old = self.module.passive_elements.insert(elem_index, segments);
402        debug_assert!(
403            old.is_none(),
404            "should never get duplicate element indices, that would be a bug in `wasmer_compiler`'s \
405             translation"
406        );
407        Ok(())
408    }
409
410    pub(crate) fn define_function_body(
411        &mut self,
412        _module_translation_state: &ModuleTranslationState,
413        body_bytes: &'data [u8],
414        body_offset: usize,
415    ) -> WasmResult<()> {
416        self.function_body_inputs.push(FunctionBodyData {
417            data: body_bytes,
418            module_offset: body_offset,
419        });
420        Ok(())
421    }
422
423    pub(crate) fn reserve_data_initializers(&mut self, num: u32) -> WasmResult<()> {
424        self.data_initializers
425            .reserve_exact(usize::try_from(num).unwrap());
426        Ok(())
427    }
428
429    pub(crate) fn declare_data_initialization(
430        &mut self,
431        memory_index: MemoryIndex,
432        offset_expr: InitExpr,
433        data: &'data [u8],
434    ) -> WasmResult<()> {
435        self.data_initializers.push(DataInitializer {
436            location: DataInitializerLocation {
437                memory_index,
438                offset_expr,
439            },
440            data,
441        });
442        Ok(())
443    }
444
445    pub(crate) fn reserve_passive_data(&mut self, count: u32) -> WasmResult<()> {
446        let count = usize::try_from(count).unwrap();
447        self.module.passive_data.reserve(count);
448        Ok(())
449    }
450
451    pub(crate) fn declare_passive_data(
452        &mut self,
453        data_index: DataIndex,
454        data: &'data [u8],
455    ) -> WasmResult<()> {
456        let old = self.module.passive_data.insert(data_index, Box::from(data));
457        debug_assert!(
458            old.is_none(),
459            "a module can't have duplicate indices, this would be a wasmer-compiler bug"
460        );
461        Ok(())
462    }
463
464    pub(crate) fn declare_module_name(&mut self, name: &'data str) -> WasmResult<()> {
465        self.module.name = Some(name.to_string());
466        Ok(())
467    }
468
469    pub(crate) fn declare_function_names(
470        &mut self,
471        functions: HashMap<FunctionIndex, String>,
472    ) -> WasmResult<()> {
473        self.module.function_names = functions;
474        Ok(())
475    }
476
477    /// Provides the number of imports up front. By default this does nothing, but
478    /// implementations can use this to preallocate memory if desired.
479    pub(crate) fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
480        Ok(())
481    }
482
483    /// Notifies the implementation that all exports have been declared.
484    pub(crate) fn finish_exports(&mut self) -> WasmResult<()> {
485        Ok(())
486    }
487
488    /// Indicates that a custom section has been found in the wasm file
489    pub(crate) fn custom_section(&mut self, name: &'data str, data: &'data [u8]) -> WasmResult<()> {
490        let custom_section = CustomSectionIndex::from_u32(
491            self.module.custom_sections_data.len().try_into().unwrap(),
492        );
493        self.module
494            .custom_sections
495            .insert(String::from(name), custom_section);
496        self.module.custom_sections_data.push(Box::from(data));
497        Ok(())
498    }
499}