linera_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::entity::PrimaryMap;
11use wasmer_types::FunctionType;
12use wasmer_types::WasmResult;
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};
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<ModuleEnvironment<'data>> {
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_table_import(
156        &mut self,
157        table: TableType,
158        module: &str,
159        field: &str,
160    ) -> WasmResult<()> {
161        debug_assert_eq!(
162            self.module.tables.len(),
163            self.module.num_imported_tables,
164            "Imported tables must be declared first"
165        );
166        self.declare_import(
167            ImportIndex::Table(TableIndex::from_u32(self.module.num_imported_tables as _)),
168            module,
169            field,
170        )?;
171        self.module.tables.push(table);
172        self.module.num_imported_tables += 1;
173        Ok(())
174    }
175
176    pub(crate) fn declare_memory_import(
177        &mut self,
178        memory: MemoryType,
179        module: &str,
180        field: &str,
181    ) -> WasmResult<()> {
182        debug_assert_eq!(
183            self.module.memories.len(),
184            self.module.num_imported_memories,
185            "Imported memories must be declared first"
186        );
187        self.declare_import(
188            ImportIndex::Memory(MemoryIndex::from_u32(
189                self.module.num_imported_memories as _,
190            )),
191            module,
192            field,
193        )?;
194        self.module.memories.push(memory);
195        self.module.num_imported_memories += 1;
196        Ok(())
197    }
198
199    pub(crate) fn declare_global_import(
200        &mut self,
201        global: GlobalType,
202        module: &str,
203        field: &str,
204    ) -> WasmResult<()> {
205        debug_assert_eq!(
206            self.module.globals.len(),
207            self.module.num_imported_globals,
208            "Imported globals must be declared first"
209        );
210        self.declare_import(
211            ImportIndex::Global(GlobalIndex::from_u32(self.module.num_imported_globals as _)),
212            module,
213            field,
214        )?;
215        self.module.globals.push(global);
216        self.module.num_imported_globals += 1;
217        Ok(())
218    }
219
220    pub(crate) fn finish_imports(&mut self) -> WasmResult<()> {
221        Ok(())
222    }
223
224    pub(crate) fn reserve_func_types(&mut self, num: u32) -> WasmResult<()> {
225        self.module
226            .functions
227            .reserve_exact(usize::try_from(num).unwrap());
228        self.function_body_inputs
229            .reserve_exact(usize::try_from(num).unwrap());
230        Ok(())
231    }
232
233    pub(crate) fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
234        self.module.functions.push(sig_index);
235        Ok(())
236    }
237
238    pub(crate) fn reserve_tables(&mut self, num: u32) -> WasmResult<()> {
239        self.module
240            .tables
241            .reserve_exact(usize::try_from(num).unwrap());
242        Ok(())
243    }
244
245    pub(crate) fn declare_table(&mut self, table: TableType) -> WasmResult<()> {
246        self.module.tables.push(table);
247        Ok(())
248    }
249
250    pub(crate) fn reserve_memories(&mut self, num: u32) -> WasmResult<()> {
251        self.module
252            .memories
253            .reserve_exact(usize::try_from(num).unwrap());
254        Ok(())
255    }
256
257    pub(crate) fn declare_memory(&mut self, memory: MemoryType) -> WasmResult<()> {
258        self.module.memories.push(memory);
259        Ok(())
260    }
261
262    pub(crate) fn reserve_globals(&mut self, num: u32) -> WasmResult<()> {
263        self.module
264            .globals
265            .reserve_exact(usize::try_from(num).unwrap());
266        Ok(())
267    }
268
269    pub(crate) fn declare_global(
270        &mut self,
271        global: GlobalType,
272        initializer: GlobalInit,
273    ) -> WasmResult<()> {
274        self.module.globals.push(global);
275        self.module.global_initializers.push(initializer);
276        Ok(())
277    }
278
279    pub(crate) fn reserve_exports(&mut self, num: u32) -> WasmResult<()> {
280        self.module.exports.reserve(usize::try_from(num).unwrap());
281        Ok(())
282    }
283
284    pub(crate) fn declare_func_export(
285        &mut self,
286        func_index: FunctionIndex,
287        name: &str,
288    ) -> WasmResult<()> {
289        self.declare_export(ExportIndex::Function(func_index), name)
290    }
291
292    pub(crate) fn declare_table_export(
293        &mut self,
294        table_index: TableIndex,
295        name: &str,
296    ) -> WasmResult<()> {
297        self.declare_export(ExportIndex::Table(table_index), name)
298    }
299
300    pub(crate) fn declare_memory_export(
301        &mut self,
302        memory_index: MemoryIndex,
303        name: &str,
304    ) -> WasmResult<()> {
305        self.declare_export(ExportIndex::Memory(memory_index), name)
306    }
307
308    pub(crate) fn declare_global_export(
309        &mut self,
310        global_index: GlobalIndex,
311        name: &str,
312    ) -> WasmResult<()> {
313        self.declare_export(ExportIndex::Global(global_index), name)
314    }
315
316    pub(crate) fn declare_start_function(&mut self, func_index: FunctionIndex) -> WasmResult<()> {
317        debug_assert!(self.module.start_function.is_none());
318        self.module.start_function = Some(func_index);
319        Ok(())
320    }
321
322    pub(crate) fn reserve_table_initializers(&mut self, num: u32) -> WasmResult<()> {
323        self.module
324            .table_initializers
325            .reserve_exact(usize::try_from(num).unwrap());
326        Ok(())
327    }
328
329    pub(crate) fn declare_table_initializers(
330        &mut self,
331        table_index: TableIndex,
332        base: Option<GlobalIndex>,
333        offset: usize,
334        elements: Box<[FunctionIndex]>,
335    ) -> WasmResult<()> {
336        self.module.table_initializers.push(TableInitializer {
337            table_index,
338            base,
339            offset,
340            elements,
341        });
342        Ok(())
343    }
344
345    pub(crate) fn declare_passive_element(
346        &mut self,
347        elem_index: ElemIndex,
348        segments: Box<[FunctionIndex]>,
349    ) -> WasmResult<()> {
350        let old = self.module.passive_elements.insert(elem_index, segments);
351        debug_assert!(
352            old.is_none(),
353            "should never get duplicate element indices, that would be a bug in `wasmer_compiler`'s \
354             translation"
355        );
356        Ok(())
357    }
358
359    pub(crate) fn define_function_body(
360        &mut self,
361        _module_translation_state: &ModuleTranslationState,
362        body_bytes: &'data [u8],
363        body_offset: usize,
364    ) -> WasmResult<()> {
365        self.function_body_inputs.push(FunctionBodyData {
366            data: body_bytes,
367            module_offset: body_offset,
368        });
369        Ok(())
370    }
371
372    pub(crate) fn reserve_data_initializers(&mut self, num: u32) -> WasmResult<()> {
373        self.data_initializers
374            .reserve_exact(usize::try_from(num).unwrap());
375        Ok(())
376    }
377
378    pub(crate) fn declare_data_initialization(
379        &mut self,
380        memory_index: MemoryIndex,
381        base: Option<GlobalIndex>,
382        offset: usize,
383        data: &'data [u8],
384    ) -> WasmResult<()> {
385        self.data_initializers.push(DataInitializer {
386            location: DataInitializerLocation {
387                memory_index,
388                base,
389                offset,
390            },
391            data,
392        });
393        Ok(())
394    }
395
396    pub(crate) fn reserve_passive_data(&mut self, count: u32) -> WasmResult<()> {
397        let count = usize::try_from(count).unwrap();
398        self.module.passive_data.reserve(count);
399        Ok(())
400    }
401
402    pub(crate) fn declare_passive_data(
403        &mut self,
404        data_index: DataIndex,
405        data: &'data [u8],
406    ) -> WasmResult<()> {
407        let old = self.module.passive_data.insert(data_index, Box::from(data));
408        debug_assert!(
409            old.is_none(),
410            "a module can't have duplicate indices, this would be a wasmer-compiler bug"
411        );
412        Ok(())
413    }
414
415    pub(crate) fn declare_module_name(&mut self, name: &'data str) -> WasmResult<()> {
416        self.module.name = Some(name.to_string());
417        Ok(())
418    }
419
420    pub(crate) fn declare_function_name(
421        &mut self,
422        func_index: FunctionIndex,
423        name: &'data str,
424    ) -> WasmResult<()> {
425        self.module
426            .function_names
427            .insert(func_index, name.to_string());
428        Ok(())
429    }
430
431    /// Provides the number of imports up front. By default this does nothing, but
432    /// implementations can use this to preallocate memory if desired.
433    pub(crate) fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
434        Ok(())
435    }
436
437    /// Notifies the implementation that all exports have been declared.
438    pub(crate) fn finish_exports(&mut self) -> WasmResult<()> {
439        Ok(())
440    }
441
442    /// Indicates that a custom section has been found in the wasm file
443    pub(crate) fn custom_section(&mut self, name: &'data str, data: &'data [u8]) -> WasmResult<()> {
444        let custom_section = CustomSectionIndex::from_u32(
445            self.module.custom_sections_data.len().try_into().unwrap(),
446        );
447        self.module
448            .custom_sections
449            .insert(String::from(name), custom_section);
450        self.module.custom_sections_data.push(Box::from(data));
451        Ok(())
452    }
453}