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