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