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 
9 use crate::state::{FuncTranslationState, ModuleTranslationState};
10 use crate::translation_utils::{
11     DataIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex,
12     Table, TableIndex,
13 };
14 use core::convert::From;
15 use cranelift_codegen::cursor::FuncCursor;
16 use cranelift_codegen::ir::immediates::Offset32;
17 use cranelift_codegen::ir::{self, InstBuilder};
18 use cranelift_codegen::isa::TargetFrontendConfig;
19 use cranelift_frontend::FunctionBuilder;
20 use std::boxed::Box;
21 use thiserror::Error;
22 use wasmparser::BinaryReaderError;
23 use wasmparser::Operator;
24 
25 // Re-export `wasmparser`'s function and value types so that consumers can
26 // associate this the original Wasm signature with each compiled function. This
27 // is often necessary because while each Wasm signature gets compiled down into
28 // a single native signature, multiple Wasm signatures might compile down into
29 // the same native signature.
30 pub use wasmparser::{FuncType as WasmFuncType, Type as WasmType};
31 
32 /// The value of a WebAssembly global variable.
33 #[derive(Clone, Copy)]
34 pub enum GlobalVariable {
35     /// This is a constant global with a value known at compile time.
36     Const(ir::Value),
37 
38     /// This is a variable in memory that should be referenced through a `GlobalValue`.
39     Memory {
40         /// The address of the global variable storage.
41         gv: ir::GlobalValue,
42         /// An offset to add to the address.
43         offset: Offset32,
44         /// The global variable's type.
45         ty: ir::Type,
46     },
47 
48     /// This is a global variable that needs to be handled by the environment.
49     Custom,
50 }
51 
52 /// A WebAssembly translation error.
53 ///
54 /// When a WebAssembly function can't be translated, one of these error codes will be returned
55 /// to describe the failure.
56 #[derive(Error, Debug)]
57 pub enum WasmError {
58     /// The input WebAssembly code is invalid.
59     ///
60     /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly
61     /// code. This should never happen for validated WebAssembly code.
62     #[error("Invalid input WebAssembly code at offset {offset}: {message}")]
63     InvalidWebAssembly {
64         /// A string describing the validation error.
65         message: std::string::String,
66         /// The bytecode offset where the error occurred.
67         offset: usize,
68     },
69 
70     /// A feature used by the WebAssembly code is not supported by the embedding environment.
71     ///
72     /// Embedding environments may have their own limitations and feature restrictions.
73     #[error("Unsupported feature: {0}")]
74     Unsupported(std::string::String),
75 
76     /// An implementation limit was exceeded.
77     ///
78     /// Cranelift can compile very large and complicated functions, but the [implementation has
79     /// limits][limits] that cause compilation to fail when they are exceeded.
80     ///
81     /// [limits]: https://github.com/bytecodealliance/wasmtime/blob/master/cranelift/docs/ir.md#implementation-limits
82     #[error("Implementation limit exceeded")]
83     ImplLimitExceeded,
84 
85     /// Any user-defined error.
86     #[error("User error: {0}")]
87     User(std::string::String),
88 }
89 
90 /// Return an `Err(WasmError::Unsupported(msg))` where `msg` the string built by calling `format!`
91 /// on the arguments to this macro.
92 #[macro_export]
93 macro_rules! wasm_unsupported {
94     ($($arg:tt)*) => { $crate::environ::WasmError::Unsupported(format!($($arg)*)) }
95 }
96 
97 impl From<BinaryReaderError> for WasmError {
98     /// Convert from a `BinaryReaderError` to a `WasmError`.
from(e: BinaryReaderError) -> Self99     fn from(e: BinaryReaderError) -> Self {
100         Self::InvalidWebAssembly {
101             message: e.message().into(),
102             offset: e.offset(),
103         }
104     }
105 }
106 
107 /// A convenient alias for a `Result` that uses `WasmError` as the error type.
108 pub type WasmResult<T> = Result<T, WasmError>;
109 
110 /// How to return from functions.
111 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
112 pub enum ReturnMode {
113     /// Use normal return instructions as needed.
114     NormalReturns,
115     /// Use a single fallthrough return at the end of the function.
116     FallthroughReturn,
117 }
118 
119 /// Environment affecting the translation of a WebAssembly.
120 pub trait TargetEnvironment {
121     /// Get the information needed to produce Cranelift IR for the given target.
target_config(&self) -> TargetFrontendConfig122     fn target_config(&self) -> TargetFrontendConfig;
123 
124     /// Get the Cranelift integer type to use for native pointers.
125     ///
126     /// This returns `I64` for 64-bit architectures and `I32` for 32-bit architectures.
pointer_type(&self) -> ir::Type127     fn pointer_type(&self) -> ir::Type {
128         ir::Type::int(u16::from(self.target_config().pointer_bits())).unwrap()
129     }
130 
131     /// Get the size of a native pointer, in bytes.
pointer_bytes(&self) -> u8132     fn pointer_bytes(&self) -> u8 {
133         self.target_config().pointer_bytes()
134     }
135 
136     /// Get the Cranelift reference type to use for native references.
137     ///
138     /// This returns `R64` for 64-bit architectures and `R32` for 32-bit architectures.
reference_type(&self) -> ir::Type139     fn reference_type(&self) -> ir::Type {
140         match self.pointer_type() {
141             ir::types::I32 => ir::types::R32,
142             ir::types::I64 => ir::types::R64,
143             _ => panic!("unsupported pointer type"),
144         }
145     }
146 }
147 
148 /// Environment affecting the translation of a single WebAssembly function.
149 ///
150 /// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cranelift
151 /// IR. The function environment provides information about the WebAssembly module as well as the
152 /// runtime environment.
153 pub trait FuncEnvironment: TargetEnvironment {
154     /// Is the given parameter of the given function a wasm-level parameter, as opposed to a hidden
155     /// parameter added for use by the implementation?
is_wasm_parameter(&self, signature: &ir::Signature, index: usize) -> bool156     fn is_wasm_parameter(&self, signature: &ir::Signature, index: usize) -> bool {
157         signature.params[index].purpose == ir::ArgumentPurpose::Normal
158     }
159 
160     /// Is the given return of the given function a wasm-level parameter, as
161     /// opposed to a hidden parameter added for use by the implementation?
is_wasm_return(&self, signature: &ir::Signature, index: usize) -> bool162     fn is_wasm_return(&self, signature: &ir::Signature, index: usize) -> bool {
163         signature.returns[index].purpose == ir::ArgumentPurpose::Normal
164     }
165 
166     /// Should the code be structured to use a single `fallthrough_return` instruction at the end
167     /// of the function body, rather than `return` instructions as needed? This is used by VMs
168     /// to append custom epilogues.
return_mode(&self) -> ReturnMode169     fn return_mode(&self) -> ReturnMode {
170         ReturnMode::NormalReturns
171     }
172 
173     /// Set up the necessary preamble definitions in `func` to access the global variable
174     /// identified by `index`.
175     ///
176     /// The index space covers both imported globals and globals defined by the module.
177     ///
178     /// Return the global variable reference that should be used to access the global and the
179     /// WebAssembly type of the global.
make_global( &mut self, func: &mut ir::Function, index: GlobalIndex, ) -> WasmResult<GlobalVariable>180     fn make_global(
181         &mut self,
182         func: &mut ir::Function,
183         index: GlobalIndex,
184     ) -> WasmResult<GlobalVariable>;
185 
186     /// Set up the necessary preamble definitions in `func` to access the linear memory identified
187     /// by `index`.
188     ///
189     /// The index space covers both imported and locally declared memories.
make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> WasmResult<ir::Heap>190     fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> WasmResult<ir::Heap>;
191 
192     /// Set up the necessary preamble definitions in `func` to access the table identified
193     /// by `index`.
194     ///
195     /// The index space covers both imported and locally declared tables.
make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table>196     fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table>;
197 
198     /// Set up a signature definition in the preamble of `func` that can be used for an indirect
199     /// call with signature `index`.
200     ///
201     /// The signature may contain additional arguments needed for an indirect call, but the
202     /// arguments marked as `ArgumentPurpose::Normal` must correspond to the WebAssembly signature
203     /// arguments.
204     ///
205     /// The signature will only be used for indirect calls, even if the module has direct function
206     /// calls with the same WebAssembly type.
make_indirect_sig( &mut self, func: &mut ir::Function, index: SignatureIndex, ) -> WasmResult<ir::SigRef>207     fn make_indirect_sig(
208         &mut self,
209         func: &mut ir::Function,
210         index: SignatureIndex,
211     ) -> WasmResult<ir::SigRef>;
212 
213     /// Set up an external function definition in the preamble of `func` that can be used to
214     /// directly call the function `index`.
215     ///
216     /// The index space covers both imported functions and functions defined in the current module.
217     ///
218     /// The function's signature may contain additional arguments needed for a direct call, but the
219     /// arguments marked as `ArgumentPurpose::Normal` must correspond to the WebAssembly signature
220     /// arguments.
221     ///
222     /// The function's signature will only be used for direct calls, even if the module has
223     /// indirect calls with the same WebAssembly type.
make_direct_func( &mut self, func: &mut ir::Function, index: FuncIndex, ) -> WasmResult<ir::FuncRef>224     fn make_direct_func(
225         &mut self,
226         func: &mut ir::Function,
227         index: FuncIndex,
228     ) -> WasmResult<ir::FuncRef>;
229 
230     /// Translate a `call_indirect` WebAssembly instruction at `pos`.
231     ///
232     /// Insert instructions at `pos` for an indirect call to the function `callee` in the table
233     /// `table_index` with WebAssembly signature `sig_index`. The `callee` value will have type
234     /// `i32`.
235     ///
236     /// The signature `sig_ref` was previously created by `make_indirect_sig()`.
237     ///
238     /// Return the call instruction whose results are the WebAssembly return values.
239     #[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
translate_call_indirect( &mut self, pos: FuncCursor, table_index: TableIndex, table: ir::Table, sig_index: SignatureIndex, sig_ref: ir::SigRef, callee: ir::Value, call_args: &[ir::Value], ) -> WasmResult<ir::Inst>240     fn translate_call_indirect(
241         &mut self,
242         pos: FuncCursor,
243         table_index: TableIndex,
244         table: ir::Table,
245         sig_index: SignatureIndex,
246         sig_ref: ir::SigRef,
247         callee: ir::Value,
248         call_args: &[ir::Value],
249     ) -> WasmResult<ir::Inst>;
250 
251     /// Translate a `call` WebAssembly instruction at `pos`.
252     ///
253     /// Insert instructions at `pos` for a direct call to the function `callee_index`.
254     ///
255     /// The function reference `callee` was previously created by `make_direct_func()`.
256     ///
257     /// Return the call instruction whose results are the WebAssembly return values.
translate_call( &mut self, mut pos: FuncCursor, _callee_index: FuncIndex, callee: ir::FuncRef, call_args: &[ir::Value], ) -> WasmResult<ir::Inst>258     fn translate_call(
259         &mut self,
260         mut pos: FuncCursor,
261         _callee_index: FuncIndex,
262         callee: ir::FuncRef,
263         call_args: &[ir::Value],
264     ) -> WasmResult<ir::Inst> {
265         Ok(pos.ins().call(callee, call_args))
266     }
267 
268     /// Translate a `memory.grow` WebAssembly instruction.
269     ///
270     /// The `index` provided identifies the linear memory to grow, and `heap` is the heap reference
271     /// returned by `make_heap` for the same index.
272     ///
273     /// The `val` value is the requested memory size in pages.
274     ///
275     /// Returns the old size (in pages) of the memory.
translate_memory_grow( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, val: ir::Value, ) -> WasmResult<ir::Value>276     fn translate_memory_grow(
277         &mut self,
278         pos: FuncCursor,
279         index: MemoryIndex,
280         heap: ir::Heap,
281         val: ir::Value,
282     ) -> WasmResult<ir::Value>;
283 
284     /// Translates a `memory.size` WebAssembly instruction.
285     ///
286     /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
287     /// returned by `make_heap` for the same index.
288     ///
289     /// Returns the size in pages of the memory.
translate_memory_size( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, ) -> WasmResult<ir::Value>290     fn translate_memory_size(
291         &mut self,
292         pos: FuncCursor,
293         index: MemoryIndex,
294         heap: ir::Heap,
295     ) -> WasmResult<ir::Value>;
296 
297     /// Translate a `memory.copy` WebAssembly instruction.
298     ///
299     /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
300     /// returned by `make_heap` for the same index.
translate_memory_copy( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, dst: ir::Value, src: ir::Value, len: ir::Value, ) -> WasmResult<()>301     fn translate_memory_copy(
302         &mut self,
303         pos: FuncCursor,
304         index: MemoryIndex,
305         heap: ir::Heap,
306         dst: ir::Value,
307         src: ir::Value,
308         len: ir::Value,
309     ) -> WasmResult<()>;
310 
311     /// Translate a `memory.fill` WebAssembly instruction.
312     ///
313     /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
314     /// returned by `make_heap` for the same index.
translate_memory_fill( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, dst: ir::Value, val: ir::Value, len: ir::Value, ) -> WasmResult<()>315     fn translate_memory_fill(
316         &mut self,
317         pos: FuncCursor,
318         index: MemoryIndex,
319         heap: ir::Heap,
320         dst: ir::Value,
321         val: ir::Value,
322         len: ir::Value,
323     ) -> WasmResult<()>;
324 
325     /// Translate a `memory.init` WebAssembly instruction.
326     ///
327     /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference
328     /// returned by `make_heap` for the same index. `seg_index` is the index of the segment to copy
329     /// from.
330     #[allow(clippy::too_many_arguments)]
translate_memory_init( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, seg_index: u32, dst: ir::Value, src: ir::Value, len: ir::Value, ) -> WasmResult<()>331     fn translate_memory_init(
332         &mut self,
333         pos: FuncCursor,
334         index: MemoryIndex,
335         heap: ir::Heap,
336         seg_index: u32,
337         dst: ir::Value,
338         src: ir::Value,
339         len: ir::Value,
340     ) -> WasmResult<()>;
341 
342     /// Translate a `data.drop` WebAssembly instruction.
translate_data_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>343     fn translate_data_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
344 
345     /// Translate a `table.size` WebAssembly instruction.
translate_table_size( &mut self, pos: FuncCursor, index: TableIndex, table: ir::Table, ) -> WasmResult<ir::Value>346     fn translate_table_size(
347         &mut self,
348         pos: FuncCursor,
349         index: TableIndex,
350         table: ir::Table,
351     ) -> WasmResult<ir::Value>;
352 
353     /// Translate a `table.grow` WebAssembly instruction.
translate_table_grow( &mut self, pos: FuncCursor, table_index: TableIndex, delta: ir::Value, init_value: ir::Value, ) -> WasmResult<ir::Value>354     fn translate_table_grow(
355         &mut self,
356         pos: FuncCursor,
357         table_index: TableIndex,
358         delta: ir::Value,
359         init_value: ir::Value,
360     ) -> WasmResult<ir::Value>;
361 
362     /// Translate a `table.get` WebAssembly instruction.
translate_table_get( &mut self, pos: FuncCursor, table_index: TableIndex, index: ir::Value, ) -> WasmResult<ir::Value>363     fn translate_table_get(
364         &mut self,
365         pos: FuncCursor,
366         table_index: TableIndex,
367         index: ir::Value,
368     ) -> WasmResult<ir::Value>;
369 
370     /// Translate a `table.set` WebAssembly instruction.
translate_table_set( &mut self, pos: FuncCursor, table_index: TableIndex, value: ir::Value, index: ir::Value, ) -> WasmResult<()>371     fn translate_table_set(
372         &mut self,
373         pos: FuncCursor,
374         table_index: TableIndex,
375         value: ir::Value,
376         index: ir::Value,
377     ) -> WasmResult<()>;
378 
379     /// Translate a `table.copy` WebAssembly instruction.
380     #[allow(clippy::too_many_arguments)]
translate_table_copy( &mut self, pos: FuncCursor, dst_table_index: TableIndex, dst_table: ir::Table, src_table_index: TableIndex, src_table: ir::Table, dst: ir::Value, src: ir::Value, len: ir::Value, ) -> WasmResult<()>381     fn translate_table_copy(
382         &mut self,
383         pos: FuncCursor,
384         dst_table_index: TableIndex,
385         dst_table: ir::Table,
386         src_table_index: TableIndex,
387         src_table: ir::Table,
388         dst: ir::Value,
389         src: ir::Value,
390         len: ir::Value,
391     ) -> WasmResult<()>;
392 
393     /// Translate a `table.fill` WebAssembly instruction.
translate_table_fill( &mut self, pos: FuncCursor, table_index: TableIndex, dst: ir::Value, val: ir::Value, len: ir::Value, ) -> WasmResult<()>394     fn translate_table_fill(
395         &mut self,
396         pos: FuncCursor,
397         table_index: TableIndex,
398         dst: ir::Value,
399         val: ir::Value,
400         len: ir::Value,
401     ) -> WasmResult<()>;
402 
403     /// Translate a `table.init` WebAssembly instruction.
404     #[allow(clippy::too_many_arguments)]
translate_table_init( &mut self, pos: FuncCursor, seg_index: u32, table_index: TableIndex, table: ir::Table, dst: ir::Value, src: ir::Value, len: ir::Value, ) -> WasmResult<()>405     fn translate_table_init(
406         &mut self,
407         pos: FuncCursor,
408         seg_index: u32,
409         table_index: TableIndex,
410         table: ir::Table,
411         dst: ir::Value,
412         src: ir::Value,
413         len: ir::Value,
414     ) -> WasmResult<()>;
415 
416     /// Translate a `elem.drop` WebAssembly instruction.
translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>417     fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
418 
419     /// Translate a `ref.func` WebAssembly instruction.
translate_ref_func(&mut self, pos: FuncCursor, func_index: u32) -> WasmResult<ir::Value>420     fn translate_ref_func(&mut self, pos: FuncCursor, func_index: u32) -> WasmResult<ir::Value>;
421 
422     /// Translate a `global.get` WebAssembly instruction at `pos` for a global
423     /// that is custom.
translate_custom_global_get( &mut self, pos: FuncCursor, global_index: GlobalIndex, ) -> WasmResult<ir::Value>424     fn translate_custom_global_get(
425         &mut self,
426         pos: FuncCursor,
427         global_index: GlobalIndex,
428     ) -> WasmResult<ir::Value>;
429 
430     /// Translate a `global.set` WebAssembly instruction at `pos` for a global
431     /// that is custom.
translate_custom_global_set( &mut self, pos: FuncCursor, global_index: GlobalIndex, val: ir::Value, ) -> WasmResult<()>432     fn translate_custom_global_set(
433         &mut self,
434         pos: FuncCursor,
435         global_index: GlobalIndex,
436         val: ir::Value,
437     ) -> WasmResult<()>;
438 
439     /// Emit code at the beginning of every wasm loop.
440     ///
441     /// This can be used to insert explicit interrupt or safepoint checking at
442     /// the beginnings of loops.
translate_loop_header(&mut self, _pos: FuncCursor) -> WasmResult<()>443     fn translate_loop_header(&mut self, _pos: FuncCursor) -> WasmResult<()> {
444         // By default, don't emit anything.
445         Ok(())
446     }
447 
448     /// Optional callback for the `FunctionEnvironment` performing this translation to maintain
449     /// internal state or prepare custom state for the operator to translate
before_translate_operator( &mut self, _op: &Operator, _builder: &mut FunctionBuilder, _state: &FuncTranslationState, ) -> WasmResult<()>450     fn before_translate_operator(
451         &mut self,
452         _op: &Operator,
453         _builder: &mut FunctionBuilder,
454         _state: &FuncTranslationState,
455     ) -> WasmResult<()> {
456         Ok(())
457     }
458 
459     /// Optional callback for the `FunctionEnvironment` performing this translation to maintain
460     /// internal state or finalize custom state for the operator that was translated
after_translate_operator( &mut self, _op: &Operator, _builder: &mut FunctionBuilder, _state: &FuncTranslationState, ) -> WasmResult<()>461     fn after_translate_operator(
462         &mut self,
463         _op: &Operator,
464         _builder: &mut FunctionBuilder,
465         _state: &FuncTranslationState,
466     ) -> WasmResult<()> {
467         Ok(())
468     }
469 }
470 
471 /// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the
472 /// [`translate_module`](fn.translate_module.html) function. These methods should not be called
473 /// by the user, they are only for `cranelift-wasm` internal use.
474 pub trait ModuleEnvironment<'data>: TargetEnvironment {
475     /// Provides the number of signatures up front. By default this does nothing, but
476     /// implementations can use this to preallocate memory if desired.
reserve_signatures(&mut self, _num: u32) -> WasmResult<()>477     fn reserve_signatures(&mut self, _num: u32) -> WasmResult<()> {
478         Ok(())
479     }
480 
481     /// Declares a function signature to the environment.
declare_signature( &mut self, wasm_func_type: &WasmFuncType, sig: ir::Signature, ) -> WasmResult<()>482     fn declare_signature(
483         &mut self,
484         wasm_func_type: &WasmFuncType,
485         sig: ir::Signature,
486     ) -> WasmResult<()>;
487 
488     /// Provides the number of imports up front. By default this does nothing, but
489     /// implementations can use this to preallocate memory if desired.
reserve_imports(&mut self, _num: u32) -> WasmResult<()>490     fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
491         Ok(())
492     }
493 
494     /// Declares a function import to the environment.
declare_func_import( &mut self, sig_index: SignatureIndex, module: &'data str, field: &'data str, ) -> WasmResult<()>495     fn declare_func_import(
496         &mut self,
497         sig_index: SignatureIndex,
498         module: &'data str,
499         field: &'data str,
500     ) -> WasmResult<()>;
501 
502     /// Declares a table import to the environment.
declare_table_import( &mut self, table: Table, module: &'data str, field: &'data str, ) -> WasmResult<()>503     fn declare_table_import(
504         &mut self,
505         table: Table,
506         module: &'data str,
507         field: &'data str,
508     ) -> WasmResult<()>;
509 
510     /// Declares a memory import to the environment.
declare_memory_import( &mut self, memory: Memory, module: &'data str, field: &'data str, ) -> WasmResult<()>511     fn declare_memory_import(
512         &mut self,
513         memory: Memory,
514         module: &'data str,
515         field: &'data str,
516     ) -> WasmResult<()>;
517 
518     /// Declares a global import to the environment.
declare_global_import( &mut self, global: Global, module: &'data str, field: &'data str, ) -> WasmResult<()>519     fn declare_global_import(
520         &mut self,
521         global: Global,
522         module: &'data str,
523         field: &'data str,
524     ) -> WasmResult<()>;
525 
526     /// Notifies the implementation that all imports have been declared.
finish_imports(&mut self) -> WasmResult<()>527     fn finish_imports(&mut self) -> WasmResult<()> {
528         Ok(())
529     }
530 
531     /// Provides the number of defined functions up front. By default this does nothing, but
532     /// implementations can use this to preallocate memory if desired.
reserve_func_types(&mut self, _num: u32) -> WasmResult<()>533     fn reserve_func_types(&mut self, _num: u32) -> WasmResult<()> {
534         Ok(())
535     }
536 
537     /// Declares the type (signature) of a local function in the module.
declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()>538     fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()>;
539 
540     /// Provides the number of defined tables up front. By default this does nothing, but
541     /// implementations can use this to preallocate memory if desired.
reserve_tables(&mut self, _num: u32) -> WasmResult<()>542     fn reserve_tables(&mut self, _num: u32) -> WasmResult<()> {
543         Ok(())
544     }
545 
546     /// Declares a table to the environment.
declare_table(&mut self, table: Table) -> WasmResult<()>547     fn declare_table(&mut self, table: Table) -> WasmResult<()>;
548 
549     /// Provides the number of defined memories up front. By default this does nothing, but
550     /// implementations can use this to preallocate memory if desired.
reserve_memories(&mut self, _num: u32) -> WasmResult<()>551     fn reserve_memories(&mut self, _num: u32) -> WasmResult<()> {
552         Ok(())
553     }
554 
555     /// Declares a memory to the environment
declare_memory(&mut self, memory: Memory) -> WasmResult<()>556     fn declare_memory(&mut self, memory: Memory) -> WasmResult<()>;
557 
558     /// Provides the number of defined globals up front. By default this does nothing, but
559     /// implementations can use this to preallocate memory if desired.
reserve_globals(&mut self, _num: u32) -> WasmResult<()>560     fn reserve_globals(&mut self, _num: u32) -> WasmResult<()> {
561         Ok(())
562     }
563 
564     /// Declares a global to the environment.
declare_global(&mut self, global: Global) -> WasmResult<()>565     fn declare_global(&mut self, global: Global) -> WasmResult<()>;
566 
567     /// Provides the number of exports up front. By default this does nothing, but
568     /// implementations can use this to preallocate memory if desired.
reserve_exports(&mut self, _num: u32) -> WasmResult<()>569     fn reserve_exports(&mut self, _num: u32) -> WasmResult<()> {
570         Ok(())
571     }
572 
573     /// Declares a function export to the environment.
declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>574     fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>;
575 
576     /// Declares a table export to the environment.
declare_table_export(&mut self, table_index: TableIndex, name: &'data str) -> WasmResult<()>577     fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str)
578         -> WasmResult<()>;
579 
580     /// Declares a memory export to the environment.
declare_memory_export( &mut self, memory_index: MemoryIndex, name: &'data str, ) -> WasmResult<()>581     fn declare_memory_export(
582         &mut self,
583         memory_index: MemoryIndex,
584         name: &'data str,
585     ) -> WasmResult<()>;
586 
587     /// Declares a global export to the environment.
declare_global_export( &mut self, global_index: GlobalIndex, name: &'data str, ) -> WasmResult<()>588     fn declare_global_export(
589         &mut self,
590         global_index: GlobalIndex,
591         name: &'data str,
592     ) -> WasmResult<()>;
593 
594     /// Notifies the implementation that all exports have been declared.
finish_exports(&mut self) -> WasmResult<()>595     fn finish_exports(&mut self) -> WasmResult<()> {
596         Ok(())
597     }
598 
599     /// Declares the optional start function.
declare_start_func(&mut self, index: FuncIndex) -> WasmResult<()>600     fn declare_start_func(&mut self, index: FuncIndex) -> WasmResult<()>;
601 
602     /// Provides the number of element initializers up front. By default this does nothing, but
603     /// implementations can use this to preallocate memory if desired.
reserve_table_elements(&mut self, _num: u32) -> WasmResult<()>604     fn reserve_table_elements(&mut self, _num: u32) -> WasmResult<()> {
605         Ok(())
606     }
607 
608     /// Fills a declared table with references to functions in the module.
declare_table_elements( &mut self, table_index: TableIndex, base: Option<GlobalIndex>, offset: usize, elements: Box<[FuncIndex]>, ) -> WasmResult<()>609     fn declare_table_elements(
610         &mut self,
611         table_index: TableIndex,
612         base: Option<GlobalIndex>,
613         offset: usize,
614         elements: Box<[FuncIndex]>,
615     ) -> WasmResult<()>;
616 
617     /// Declare a passive element segment.
declare_passive_element( &mut self, index: ElemIndex, elements: Box<[FuncIndex]>, ) -> WasmResult<()>618     fn declare_passive_element(
619         &mut self,
620         index: ElemIndex,
621         elements: Box<[FuncIndex]>,
622     ) -> WasmResult<()>;
623 
624     /// Provides the number of passive data segments up front.
625     ///
626     /// By default this does nothing, but implementations may use this to
627     /// pre-allocate memory if desired.
reserve_passive_data(&mut self, count: u32) -> WasmResult<()>628     fn reserve_passive_data(&mut self, count: u32) -> WasmResult<()> {
629         let _ = count;
630         Ok(())
631     }
632 
633     /// Declare a passive data segment.
declare_passive_data(&mut self, data_index: DataIndex, data: &'data [u8]) -> WasmResult<()>634     fn declare_passive_data(&mut self, data_index: DataIndex, data: &'data [u8]) -> WasmResult<()>;
635 
636     /// Provides the contents of a function body.
637     ///
638     /// Note there's no `reserve_function_bodies` function because the number of
639     /// functions is already provided by `reserve_func_types`.
define_function_body( &mut self, module_translation_state: &ModuleTranslationState, body_bytes: &'data [u8], body_offset: usize, ) -> WasmResult<()>640     fn define_function_body(
641         &mut self,
642         module_translation_state: &ModuleTranslationState,
643         body_bytes: &'data [u8],
644         body_offset: usize,
645     ) -> WasmResult<()>;
646 
647     /// Provides the number of data initializers up front. By default this does nothing, but
648     /// implementations can use this to preallocate memory if desired.
reserve_data_initializers(&mut self, _num: u32) -> WasmResult<()>649     fn reserve_data_initializers(&mut self, _num: u32) -> WasmResult<()> {
650         Ok(())
651     }
652 
653     /// Fills a declared memory with bytes at module instantiation.
declare_data_initialization( &mut self, memory_index: MemoryIndex, base: Option<GlobalIndex>, offset: usize, data: &'data [u8], ) -> WasmResult<()>654     fn declare_data_initialization(
655         &mut self,
656         memory_index: MemoryIndex,
657         base: Option<GlobalIndex>,
658         offset: usize,
659         data: &'data [u8],
660     ) -> WasmResult<()>;
661 
662     /// Declares the name of a module to the environment.
663     ///
664     /// By default this does nothing, but implementations can use this to read
665     /// the module name subsection of the custom name section if desired.
declare_module_name(&mut self, _name: &'data str) -> WasmResult<()>666     fn declare_module_name(&mut self, _name: &'data str) -> WasmResult<()> {
667         Ok(())
668     }
669 
670     /// Declares the name of a function to the environment.
671     ///
672     /// By default this does nothing, but implementations can use this to read
673     /// the function name subsection of the custom name section if desired.
declare_func_name(&mut self, _func_index: FuncIndex, _name: &'data str) -> WasmResult<()>674     fn declare_func_name(&mut self, _func_index: FuncIndex, _name: &'data str) -> WasmResult<()> {
675         Ok(())
676     }
677 
678     /// Indicates that a custom section has been found in the wasm file
custom_section(&mut self, _name: &'data str, _data: &'data [u8]) -> WasmResult<()>679     fn custom_section(&mut self, _name: &'data str, _data: &'data [u8]) -> WasmResult<()> {
680         Ok(())
681     }
682 }
683