cranelift_wasm/environ/
spec.rs

1//! All the runtime support necessary for the wasm to cranelift translation is formalized by the
2//! traits `FunctionEnvironment` and `ModuleEnvironment`.
3//!
4//! There are skeleton implementations of these traits in the `dummy` module, and complete
5//! implementations in [Wasmtime].
6//!
7//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
8
9use crate::state::FuncTranslationState;
10use crate::{
11    DataIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Heap, HeapData, Memory, MemoryIndex,
12    SignatureIndex, Table, TableIndex, Tag, TagIndex, TypeIndex, WasmError, WasmFuncType,
13    WasmResult, WasmType,
14};
15use core::convert::From;
16use cranelift_codegen::cursor::FuncCursor;
17use cranelift_codegen::ir::immediates::Offset32;
18use cranelift_codegen::ir::{self, InstBuilder};
19use cranelift_codegen::isa::TargetFrontendConfig;
20use cranelift_entity::PrimaryMap;
21use cranelift_frontend::FunctionBuilder;
22use std::boxed::Box;
23use std::string::ToString;
24use wasmparser::{FuncValidator, FunctionBody, Operator, ValidatorResources, WasmFeatures};
25
26/// The value of a WebAssembly global variable.
27#[derive(Clone, Copy)]
28pub enum GlobalVariable {
29    /// This is a constant global with a value known at compile time.
30    Const(ir::Value),
31
32    /// This is a variable in memory that should be referenced through a `GlobalValue`.
33    Memory {
34        /// The address of the global variable storage.
35        gv: ir::GlobalValue,
36        /// An offset to add to the address.
37        offset: Offset32,
38        /// The global variable's type.
39        ty: ir::Type,
40    },
41
42    /// This is a global variable that needs to be handled by the environment.
43    Custom,
44}
45
46/// Environment affecting the translation of a WebAssembly.
47pub trait TargetEnvironment {
48    /// Get the information needed to produce Cranelift IR for the given target.
49    fn target_config(&self) -> TargetFrontendConfig;
50
51    /// Whether to enable Spectre mitigations for heap accesses.
52    fn heap_access_spectre_mitigation(&self) -> bool;
53
54    /// Get the Cranelift integer type to use for native pointers.
55    ///
56    /// This returns `I64` for 64-bit architectures and `I32` for 32-bit architectures.
57    fn pointer_type(&self) -> ir::Type {
58        ir::Type::int(u16::from(self.target_config().pointer_bits())).unwrap()
59    }
60
61    /// Get the size of a native pointer, in bytes.
62    fn pointer_bytes(&self) -> u8 {
63        self.target_config().pointer_bytes()
64    }
65
66    /// Get the Cranelift reference type to use for the given Wasm reference
67    /// type.
68    ///
69    /// By default, this returns `R64` for 64-bit architectures and `R32` for
70    /// 32-bit architectures. If you override this, then you should also
71    /// override `FuncEnvironment::{translate_ref_null, translate_ref_is_null}`
72    /// as well.
73    fn reference_type(&self, ty: WasmType) -> ir::Type {
74        let _ = ty;
75        match self.pointer_type() {
76            ir::types::I32 => ir::types::R32,
77            ir::types::I64 => ir::types::R64,
78            _ => panic!("unsupported pointer type"),
79        }
80    }
81}
82
83/// Environment affecting the translation of a single WebAssembly function.
84///
85/// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cranelift
86/// IR. The function environment provides information about the WebAssembly module as well as the
87/// runtime environment.
88pub trait FuncEnvironment: TargetEnvironment {
89    /// Is the given parameter of the given function a wasm-level parameter, as opposed to a hidden
90    /// parameter added for use by the implementation?
91    fn is_wasm_parameter(&self, signature: &ir::Signature, index: usize) -> bool {
92        signature.params[index].purpose == ir::ArgumentPurpose::Normal
93    }
94
95    /// Is the given return of the given function a wasm-level parameter, as
96    /// opposed to a hidden parameter added for use by the implementation?
97    fn is_wasm_return(&self, signature: &ir::Signature, index: usize) -> bool {
98        signature.returns[index].purpose == ir::ArgumentPurpose::Normal
99    }
100
101    /// Called after the locals for a function have been parsed, and the number
102    /// of variables defined by this function is provided.
103    fn after_locals(&mut self, num_locals_defined: usize) {
104        drop(num_locals_defined);
105    }
106
107    /// Set up the necessary preamble definitions in `func` to access the global variable
108    /// identified by `index`.
109    ///
110    /// The index space covers both imported globals and globals defined by the module.
111    ///
112    /// Return the global variable reference that should be used to access the global and the
113    /// WebAssembly type of the global.
114    fn make_global(
115        &mut self,
116        func: &mut ir::Function,
117        index: GlobalIndex,
118    ) -> WasmResult<GlobalVariable>;
119
120    /// Get the heaps for this function environment.
121    ///
122    /// The returned map should provide heap format details (encoded in
123    /// `HeapData`) for each `Heap` that was previously returned by
124    /// `make_heap()`. The translator will first call make_heap for each Wasm
125    /// memory, and then later when translating code, will invoke `heaps()` to
126    /// learn how to access the environment's implementation of each memory.
127    fn heaps(&self) -> &PrimaryMap<Heap, HeapData>;
128
129    /// Set up the necessary preamble definitions in `func` to access the linear memory identified
130    /// by `index`.
131    ///
132    /// The index space covers both imported and locally declared memories.
133    fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> WasmResult<Heap>;
134
135    /// Set up the necessary preamble definitions in `func` to access the table identified
136    /// by `index`.
137    ///
138    /// The index space covers both imported and locally declared tables.
139    fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table>;
140
141    /// Set up a signature definition in the preamble of `func` that can be used for an indirect
142    /// call with signature `index`.
143    ///
144    /// The signature may contain additional arguments needed for an indirect call, but the
145    /// arguments marked as `ArgumentPurpose::Normal` must correspond to the WebAssembly signature
146    /// arguments.
147    ///
148    /// The signature will only be used for indirect calls, even if the module has direct function
149    /// calls with the same WebAssembly type.
150    fn make_indirect_sig(
151        &mut self,
152        func: &mut ir::Function,
153        index: TypeIndex,
154    ) -> WasmResult<ir::SigRef>;
155
156    /// Set up an external function definition in the preamble of `func` that can be used to
157    /// directly call the function `index`.
158    ///
159    /// The index space covers both imported functions and functions defined in the current module.
160    ///
161    /// The function's signature may contain additional arguments needed for a direct call, but the
162    /// arguments marked as `ArgumentPurpose::Normal` must correspond to the WebAssembly signature
163    /// arguments.
164    ///
165    /// The function's signature will only be used for direct calls, even if the module has
166    /// indirect calls with the same WebAssembly type.
167    fn make_direct_func(
168        &mut self,
169        func: &mut ir::Function,
170        index: FuncIndex,
171    ) -> WasmResult<ir::FuncRef>;
172
173    /// Translate a `call_indirect` WebAssembly instruction at `pos`.
174    ///
175    /// Insert instructions at `pos` for an indirect call to the function `callee` in the table
176    /// `table_index` with WebAssembly signature `sig_index`. The `callee` value will have type
177    /// `i32`.
178    ///
179    /// The signature `sig_ref` was previously created by `make_indirect_sig()`.
180    ///
181    /// Return the call instruction whose results are the WebAssembly return values.
182    #[allow(clippy::too_many_arguments)]
183    fn translate_call_indirect(
184        &mut self,
185        builder: &mut FunctionBuilder,
186        table_index: TableIndex,
187        table: ir::Table,
188        sig_index: TypeIndex,
189        sig_ref: ir::SigRef,
190        callee: ir::Value,
191        call_args: &[ir::Value],
192    ) -> WasmResult<ir::Inst>;
193
194    /// Translate a `call` WebAssembly instruction at `pos`.
195    ///
196    /// Insert instructions at `pos` for a direct call to the function `callee_index`.
197    ///
198    /// The function reference `callee` was previously created by `make_direct_func()`.
199    ///
200    /// Return the call instruction whose results are the WebAssembly return values.
201    fn translate_call(
202        &mut self,
203        mut pos: FuncCursor,
204        _callee_index: FuncIndex,
205        callee: ir::FuncRef,
206        call_args: &[ir::Value],
207    ) -> WasmResult<ir::Inst> {
208        Ok(pos.ins().call(callee, call_args))
209    }
210
211    /// Translate a `memory.grow` WebAssembly instruction.
212    ///
213    /// The `index` provided identifies the linear memory to grow, and `heap` is the heap reference
214    /// returned by `make_heap` for the same index.
215    ///
216    /// The `val` value is the requested memory size in pages.
217    ///
218    /// Returns the old size (in pages) of the memory.
219    fn translate_memory_grow(
220        &mut self,
221        pos: FuncCursor,
222        index: MemoryIndex,
223        heap: Heap,
224        val: ir::Value,
225    ) -> WasmResult<ir::Value>;
226
227    /// Translates a `memory.size` WebAssembly instruction.
228    ///
229    /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
230    /// returned by `make_heap` for the same index.
231    ///
232    /// Returns the size in pages of the memory.
233    fn translate_memory_size(
234        &mut self,
235        pos: FuncCursor,
236        index: MemoryIndex,
237        heap: Heap,
238    ) -> WasmResult<ir::Value>;
239
240    /// Translate a `memory.copy` WebAssembly instruction.
241    ///
242    /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
243    /// returned by `make_heap` for the same index.
244    fn translate_memory_copy(
245        &mut self,
246        pos: FuncCursor,
247        src_index: MemoryIndex,
248        src_heap: Heap,
249        dst_index: MemoryIndex,
250        dst_heap: Heap,
251        dst: ir::Value,
252        src: ir::Value,
253        len: ir::Value,
254    ) -> WasmResult<()>;
255
256    /// Translate a `memory.fill` WebAssembly instruction.
257    ///
258    /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
259    /// returned by `make_heap` for the same index.
260    fn translate_memory_fill(
261        &mut self,
262        pos: FuncCursor,
263        index: MemoryIndex,
264        heap: Heap,
265        dst: ir::Value,
266        val: ir::Value,
267        len: ir::Value,
268    ) -> WasmResult<()>;
269
270    /// Translate a `memory.init` WebAssembly instruction.
271    ///
272    /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
273    /// returned by `make_heap` for the same index. `seg_index` is the index of the segment to copy
274    /// from.
275    #[allow(clippy::too_many_arguments)]
276    fn translate_memory_init(
277        &mut self,
278        pos: FuncCursor,
279        index: MemoryIndex,
280        heap: Heap,
281        seg_index: u32,
282        dst: ir::Value,
283        src: ir::Value,
284        len: ir::Value,
285    ) -> WasmResult<()>;
286
287    /// Translate a `data.drop` WebAssembly instruction.
288    fn translate_data_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
289
290    /// Translate a `table.size` WebAssembly instruction.
291    fn translate_table_size(
292        &mut self,
293        pos: FuncCursor,
294        index: TableIndex,
295        table: ir::Table,
296    ) -> WasmResult<ir::Value>;
297
298    /// Translate a `table.grow` WebAssembly instruction.
299    fn translate_table_grow(
300        &mut self,
301        pos: FuncCursor,
302        table_index: TableIndex,
303        table: ir::Table,
304        delta: ir::Value,
305        init_value: ir::Value,
306    ) -> WasmResult<ir::Value>;
307
308    /// Translate a `table.get` WebAssembly instruction.
309    fn translate_table_get(
310        &mut self,
311        builder: &mut FunctionBuilder,
312        table_index: TableIndex,
313        table: ir::Table,
314        index: ir::Value,
315    ) -> WasmResult<ir::Value>;
316
317    /// Translate a `table.set` WebAssembly instruction.
318    fn translate_table_set(
319        &mut self,
320        builder: &mut FunctionBuilder,
321        table_index: TableIndex,
322        table: ir::Table,
323        value: ir::Value,
324        index: ir::Value,
325    ) -> WasmResult<()>;
326
327    /// Translate a `table.copy` WebAssembly instruction.
328    #[allow(clippy::too_many_arguments)]
329    fn translate_table_copy(
330        &mut self,
331        pos: FuncCursor,
332        dst_table_index: TableIndex,
333        dst_table: ir::Table,
334        src_table_index: TableIndex,
335        src_table: ir::Table,
336        dst: ir::Value,
337        src: ir::Value,
338        len: ir::Value,
339    ) -> WasmResult<()>;
340
341    /// Translate a `table.fill` WebAssembly instruction.
342    fn translate_table_fill(
343        &mut self,
344        pos: FuncCursor,
345        table_index: TableIndex,
346        dst: ir::Value,
347        val: ir::Value,
348        len: ir::Value,
349    ) -> WasmResult<()>;
350
351    /// Translate a `table.init` WebAssembly instruction.
352    #[allow(clippy::too_many_arguments)]
353    fn translate_table_init(
354        &mut self,
355        pos: FuncCursor,
356        seg_index: u32,
357        table_index: TableIndex,
358        table: ir::Table,
359        dst: ir::Value,
360        src: ir::Value,
361        len: ir::Value,
362    ) -> WasmResult<()>;
363
364    /// Translate a `elem.drop` WebAssembly instruction.
365    fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
366
367    /// Translate a `ref.null T` WebAssembly instruction.
368    ///
369    /// By default, translates into a null reference type.
370    ///
371    /// Override this if you don't use Cranelift reference types for all Wasm
372    /// reference types (e.g. you use a raw pointer for `funcref`s) or if the
373    /// null sentinel is not a null reference type pointer for your type. If you
374    /// override this method, then you should also override
375    /// `translate_ref_is_null` as well.
376    fn translate_ref_null(&mut self, mut pos: FuncCursor, ty: WasmType) -> WasmResult<ir::Value> {
377        let _ = ty;
378        Ok(pos.ins().null(self.reference_type(ty)))
379    }
380
381    /// Translate a `ref.is_null` WebAssembly instruction.
382    ///
383    /// By default, assumes that `value` is a Cranelift reference type, and that
384    /// a null Cranelift reference type is the null value for all Wasm reference
385    /// types.
386    ///
387    /// If you override this method, you probably also want to override
388    /// `translate_ref_null` as well.
389    fn translate_ref_is_null(
390        &mut self,
391        mut pos: FuncCursor,
392        value: ir::Value,
393    ) -> WasmResult<ir::Value> {
394        let is_null = pos.ins().is_null(value);
395        Ok(pos.ins().uextend(ir::types::I32, is_null))
396    }
397
398    /// Translate a `ref.func` WebAssembly instruction.
399    fn translate_ref_func(
400        &mut self,
401        pos: FuncCursor,
402        func_index: FuncIndex,
403    ) -> WasmResult<ir::Value>;
404
405    /// Translate a `global.get` WebAssembly instruction at `pos` for a global
406    /// that is custom.
407    fn translate_custom_global_get(
408        &mut self,
409        pos: FuncCursor,
410        global_index: GlobalIndex,
411    ) -> WasmResult<ir::Value>;
412
413    /// Translate a `global.set` WebAssembly instruction at `pos` for a global
414    /// that is custom.
415    fn translate_custom_global_set(
416        &mut self,
417        pos: FuncCursor,
418        global_index: GlobalIndex,
419        val: ir::Value,
420    ) -> WasmResult<()>;
421
422    /// Translate an `i32.atomic.wait` or `i64.atomic.wait` WebAssembly instruction.
423    /// The `index` provided identifies the linear memory containing the value
424    /// to wait on, and `heap` is the heap reference returned by `make_heap`
425    /// for the same index.  Whether the waited-on value is 32- or 64-bit can be
426    /// determined by examining the type of `expected`, which must be only I32 or I64.
427    ///
428    /// Note that the `addr` here is the host linear memory address rather
429    /// than a relative wasm linear memory address. The type of this value is
430    /// the same as the host's pointer.
431    ///
432    /// Returns an i32, which is negative if the helper call failed.
433    fn translate_atomic_wait(
434        &mut self,
435        pos: FuncCursor,
436        index: MemoryIndex,
437        heap: Heap,
438        addr: ir::Value,
439        expected: ir::Value,
440        timeout: ir::Value,
441    ) -> WasmResult<ir::Value>;
442
443    /// Translate an `atomic.notify` WebAssembly instruction.
444    /// The `index` provided identifies the linear memory containing the value
445    /// to wait on, and `heap` is the heap reference returned by `make_heap`
446    /// for the same index.
447    ///
448    /// Note that the `addr` here is the host linear memory address rather
449    /// than a relative wasm linear memory address. The type of this value is
450    /// the same as the host's pointer.
451    ///
452    /// Returns an i64, which is negative if the helper call failed.
453    fn translate_atomic_notify(
454        &mut self,
455        pos: FuncCursor,
456        index: MemoryIndex,
457        heap: Heap,
458        addr: ir::Value,
459        count: ir::Value,
460    ) -> WasmResult<ir::Value>;
461
462    /// Emit code at the beginning of every wasm loop.
463    ///
464    /// This can be used to insert explicit interrupt or safepoint checking at
465    /// the beginnings of loops.
466    fn translate_loop_header(&mut self, _builder: &mut FunctionBuilder) -> WasmResult<()> {
467        // By default, don't emit anything.
468        Ok(())
469    }
470
471    /// Optional callback for the `FunctionEnvironment` performing this translation to maintain
472    /// internal state or prepare custom state for the operator to translate
473    fn before_translate_operator(
474        &mut self,
475        _op: &Operator,
476        _builder: &mut FunctionBuilder,
477        _state: &FuncTranslationState,
478    ) -> WasmResult<()> {
479        Ok(())
480    }
481
482    /// Optional callback for the `FunctionEnvironment` performing this translation to maintain
483    /// internal state or finalize custom state for the operator that was translated
484    fn after_translate_operator(
485        &mut self,
486        _op: &Operator,
487        _builder: &mut FunctionBuilder,
488        _state: &FuncTranslationState,
489    ) -> WasmResult<()> {
490        Ok(())
491    }
492
493    /// Optional callback for the `FuncEnvironment` performing this translation
494    /// to maintain, prepare, or finalize custom, internal state when we
495    /// statically determine that a Wasm memory access will unconditionally
496    /// trap, rendering the rest of the block unreachable. Called just before
497    /// the unconditional trap is emitted.
498    fn before_unconditionally_trapping_memory_access(
499        &mut self,
500        _builder: &mut FunctionBuilder,
501    ) -> WasmResult<()> {
502        Ok(())
503    }
504
505    /// Optional callback for the `FunctionEnvironment` performing this translation to perform work
506    /// before the function body is translated.
507    fn before_translate_function(
508        &mut self,
509        _builder: &mut FunctionBuilder,
510        _state: &FuncTranslationState,
511    ) -> WasmResult<()> {
512        Ok(())
513    }
514
515    /// Optional callback for the `FunctionEnvironment` performing this translation to perform work
516    /// after the function body is translated.
517    fn after_translate_function(
518        &mut self,
519        _builder: &mut FunctionBuilder,
520        _state: &FuncTranslationState,
521    ) -> WasmResult<()> {
522        Ok(())
523    }
524
525    /// Returns the target ISA's condition to check for unsigned addition
526    /// overflowing.
527    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC;
528
529    /// Whether or not to force relaxed simd instructions to have deterministic
530    /// lowerings meaning they will produce the same results across all hosts,
531    /// regardless of the cost to performance.
532    fn relaxed_simd_deterministic(&self) -> bool {
533        true
534    }
535
536    /// Whether or not the target being translated for has a native fma
537    /// instruction. If it does not then when relaxed simd isn't deterministic
538    /// the translation of the `f32x4.relaxed_fma` instruction, for example,
539    /// will do a multiplication and then an add instead of the fused version.
540    fn has_native_fma(&self) -> bool {
541        false
542    }
543
544    /// Returns whether this is an x86 target, which may alter lowerings of
545    /// relaxed simd instructions.
546    fn is_x86(&self) -> bool {
547        false
548    }
549}
550
551/// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the
552/// [`translate_module`](fn.translate_module.html) function. These methods should not be called
553/// by the user, they are only for `cranelift-wasm` internal use.
554pub trait ModuleEnvironment<'data> {
555    /// Provides the number of types up front. By default this does nothing, but
556    /// implementations can use this to preallocate memory if desired.
557    fn reserve_types(&mut self, _num: u32) -> WasmResult<()> {
558        Ok(())
559    }
560
561    /// Declares a function signature to the environment.
562    fn declare_type_func(&mut self, wasm_func_type: WasmFuncType) -> WasmResult<()>;
563
564    /// Translates a type index to its signature index, only called for type
565    /// indices which point to functions.
566    fn type_to_signature(&self, index: TypeIndex) -> WasmResult<SignatureIndex> {
567        drop(index);
568        Err(WasmError::Unsupported("module linking".to_string()))
569    }
570
571    /// Provides the number of imports up front. By default this does nothing, but
572    /// implementations can use this to preallocate memory if desired.
573    fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
574        Ok(())
575    }
576
577    /// Declares a function import to the environment.
578    fn declare_func_import(
579        &mut self,
580        index: TypeIndex,
581        module: &'data str,
582        field: &'data str,
583    ) -> WasmResult<()>;
584
585    /// Declares a table import to the environment.
586    fn declare_table_import(
587        &mut self,
588        table: Table,
589        module: &'data str,
590        field: &'data str,
591    ) -> WasmResult<()>;
592
593    /// Declares a memory import to the environment.
594    fn declare_memory_import(
595        &mut self,
596        memory: Memory,
597        module: &'data str,
598        field: &'data str,
599    ) -> WasmResult<()>;
600
601    /// Declares an tag import to the environment.
602    fn declare_tag_import(
603        &mut self,
604        tag: Tag,
605        module: &'data str,
606        field: &'data str,
607    ) -> WasmResult<()> {
608        drop((tag, module, field));
609        Err(WasmError::Unsupported("wasm tags".to_string()))
610    }
611
612    /// Declares a global import to the environment.
613    fn declare_global_import(
614        &mut self,
615        global: Global,
616        module: &'data str,
617        field: &'data str,
618    ) -> WasmResult<()>;
619
620    /// Notifies the implementation that all imports have been declared.
621    fn finish_imports(&mut self) -> WasmResult<()> {
622        Ok(())
623    }
624
625    /// Provides the number of defined functions up front. By default this does nothing, but
626    /// implementations can use this to preallocate memory if desired.
627    fn reserve_func_types(&mut self, _num: u32) -> WasmResult<()> {
628        Ok(())
629    }
630
631    /// Declares the type (signature) of a local function in the module.
632    fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()>;
633
634    /// Provides the number of defined tables up front. By default this does nothing, but
635    /// implementations can use this to preallocate memory if desired.
636    fn reserve_tables(&mut self, _num: u32) -> WasmResult<()> {
637        Ok(())
638    }
639
640    /// Declares a table to the environment.
641    fn declare_table(&mut self, table: Table) -> WasmResult<()>;
642
643    /// Provides the number of defined memories up front. By default this does nothing, but
644    /// implementations can use this to preallocate memory if desired.
645    fn reserve_memories(&mut self, _num: u32) -> WasmResult<()> {
646        Ok(())
647    }
648
649    /// Declares a memory to the environment
650    fn declare_memory(&mut self, memory: Memory) -> WasmResult<()>;
651
652    /// Provides the number of defined tags up front. By default this does nothing, but
653    /// implementations can use this to preallocate memory if desired.
654    fn reserve_tags(&mut self, _num: u32) -> WasmResult<()> {
655        Ok(())
656    }
657
658    /// Declares an tag to the environment
659    fn declare_tag(&mut self, tag: Tag) -> WasmResult<()> {
660        drop(tag);
661        Err(WasmError::Unsupported("wasm tags".to_string()))
662    }
663
664    /// Provides the number of defined globals up front. By default this does nothing, but
665    /// implementations can use this to preallocate memory if desired.
666    fn reserve_globals(&mut self, _num: u32) -> WasmResult<()> {
667        Ok(())
668    }
669
670    /// Declares a global to the environment.
671    fn declare_global(&mut self, global: Global) -> WasmResult<()>;
672
673    /// Provides the number of exports up front. By default this does nothing, but
674    /// implementations can use this to preallocate memory if desired.
675    fn reserve_exports(&mut self, _num: u32) -> WasmResult<()> {
676        Ok(())
677    }
678
679    /// Declares a function export to the environment.
680    fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>;
681
682    /// Declares a table export to the environment.
683    fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str)
684        -> WasmResult<()>;
685
686    /// Declares a memory export to the environment.
687    fn declare_memory_export(
688        &mut self,
689        memory_index: MemoryIndex,
690        name: &'data str,
691    ) -> WasmResult<()>;
692
693    /// Declares an tag export to the environment.
694    fn declare_tag_export(&mut self, tag_index: TagIndex, name: &'data str) -> WasmResult<()> {
695        drop((tag_index, name));
696        Err(WasmError::Unsupported("wasm tags".to_string()))
697    }
698
699    /// Declares a global export to the environment.
700    fn declare_global_export(
701        &mut self,
702        global_index: GlobalIndex,
703        name: &'data str,
704    ) -> WasmResult<()>;
705
706    /// Notifies the implementation that all exports have been declared.
707    fn finish_exports(&mut self) -> WasmResult<()> {
708        Ok(())
709    }
710
711    /// Declares the optional start function.
712    fn declare_start_func(&mut self, index: FuncIndex) -> WasmResult<()>;
713
714    /// Provides the number of element initializers up front. By default this does nothing, but
715    /// implementations can use this to preallocate memory if desired.
716    fn reserve_table_elements(&mut self, _num: u32) -> WasmResult<()> {
717        Ok(())
718    }
719
720    /// Fills a declared table with references to functions in the module.
721    fn declare_table_elements(
722        &mut self,
723        table_index: TableIndex,
724        base: Option<GlobalIndex>,
725        offset: u32,
726        elements: Box<[FuncIndex]>,
727    ) -> WasmResult<()>;
728
729    /// Declare a passive element segment.
730    fn declare_passive_element(
731        &mut self,
732        index: ElemIndex,
733        elements: Box<[FuncIndex]>,
734    ) -> WasmResult<()>;
735
736    /// Indicates that a declarative element segment was seen in the wasm
737    /// module.
738    fn declare_elements(&mut self, elements: Box<[FuncIndex]>) -> WasmResult<()> {
739        drop(elements);
740        Ok(())
741    }
742
743    /// Provides the number of passive data segments up front.
744    ///
745    /// By default this does nothing, but implementations may use this to
746    /// pre-allocate memory if desired.
747    fn reserve_passive_data(&mut self, count: u32) -> WasmResult<()> {
748        let _ = count;
749        Ok(())
750    }
751
752    /// Declare a passive data segment.
753    fn declare_passive_data(&mut self, data_index: DataIndex, data: &'data [u8]) -> WasmResult<()>;
754
755    /// Indicates how many functions the code section reports and the byte
756    /// offset of where the code sections starts.
757    fn reserve_function_bodies(&mut self, bodies: u32, code_section_offset: u64) {
758        drop((bodies, code_section_offset));
759    }
760
761    /// Provides the contents of a function body.
762    fn define_function_body(
763        &mut self,
764        validator: FuncValidator<ValidatorResources>,
765        body: FunctionBody<'data>,
766    ) -> WasmResult<()>;
767
768    /// Provides the number of data initializers up front. By default this does nothing, but
769    /// implementations can use this to preallocate memory if desired.
770    fn reserve_data_initializers(&mut self, _num: u32) -> WasmResult<()> {
771        Ok(())
772    }
773
774    /// Fills a declared memory with bytes at module instantiation.
775    fn declare_data_initialization(
776        &mut self,
777        memory_index: MemoryIndex,
778        base: Option<GlobalIndex>,
779        offset: u64,
780        data: &'data [u8],
781    ) -> WasmResult<()>;
782
783    /// Declares the name of a module to the environment.
784    ///
785    /// By default this does nothing, but implementations can use this to read
786    /// the module name subsection of the custom name section if desired.
787    fn declare_module_name(&mut self, _name: &'data str) {}
788
789    /// Declares the name of a function to the environment.
790    ///
791    /// By default this does nothing, but implementations can use this to read
792    /// the function name subsection of the custom name section if desired.
793    fn declare_func_name(&mut self, _func_index: FuncIndex, _name: &'data str) {}
794
795    /// Declares the name of a function's local to the environment.
796    ///
797    /// By default this does nothing, but implementations can use this to read
798    /// the local name subsection of the custom name section if desired.
799    fn declare_local_name(&mut self, _func_index: FuncIndex, _local_index: u32, _name: &'data str) {
800    }
801
802    /// Indicates that a custom section has been found in the wasm file
803    fn custom_section(&mut self, _name: &'data str, _data: &'data [u8]) -> WasmResult<()> {
804        Ok(())
805    }
806
807    /// Returns the list of enabled wasm features this translation will be using.
808    fn wasm_features(&self) -> WasmFeatures {
809        WasmFeatures::default()
810    }
811}