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