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; 10 use crate::translation_utils::{ 11 DataIndex, ElemIndex, EntityIndex, EntityType, Event, EventIndex, FuncIndex, Global, 12 GlobalIndex, InstanceIndex, InstanceTypeIndex, Memory, MemoryIndex, ModuleIndex, 13 ModuleTypeIndex, SignatureIndex, Table, TableIndex, TypeIndex, 14 }; 15 use core::convert::From; 16 use core::convert::TryFrom; 17 use cranelift_codegen::cursor::FuncCursor; 18 use cranelift_codegen::ir::immediates::Offset32; 19 use cranelift_codegen::ir::{self, InstBuilder}; 20 use cranelift_codegen::isa::TargetFrontendConfig; 21 use cranelift_frontend::FunctionBuilder; 22 #[cfg(feature = "enable-serde")] 23 use serde::{Deserialize, Serialize}; 24 use std::boxed::Box; 25 use std::string::ToString; 26 use std::vec::Vec; 27 use thiserror::Error; 28 use wasmparser::ValidatorResources; 29 use wasmparser::{BinaryReaderError, FuncValidator, FunctionBody, Operator, WasmFeatures}; 30 31 /// WebAssembly value type -- equivalent of `wasmparser`'s Type. 32 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 33 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 34 pub enum WasmType { 35 /// I32 type 36 I32, 37 /// I64 type 38 I64, 39 /// F32 type 40 F32, 41 /// F64 type 42 F64, 43 /// V128 type 44 V128, 45 /// FuncRef type 46 FuncRef, 47 /// ExternRef type 48 ExternRef, 49 /// ExnRef type 50 ExnRef, 51 } 52 53 impl TryFrom<wasmparser::Type> for WasmType { 54 type Error = WasmError; try_from(ty: wasmparser::Type) -> Result<Self, Self::Error>55 fn try_from(ty: wasmparser::Type) -> Result<Self, Self::Error> { 56 use wasmparser::Type::*; 57 match ty { 58 I32 => Ok(WasmType::I32), 59 I64 => Ok(WasmType::I64), 60 F32 => Ok(WasmType::F32), 61 F64 => Ok(WasmType::F64), 62 V128 => Ok(WasmType::V128), 63 FuncRef => Ok(WasmType::FuncRef), 64 ExternRef => Ok(WasmType::ExternRef), 65 ExnRef => Ok(WasmType::ExnRef), 66 EmptyBlockType | Func => Err(WasmError::InvalidWebAssembly { 67 message: "unexpected value type".to_string(), 68 offset: 0, 69 }), 70 } 71 } 72 } 73 74 impl From<WasmType> for wasmparser::Type { from(ty: WasmType) -> wasmparser::Type75 fn from(ty: WasmType) -> wasmparser::Type { 76 match ty { 77 WasmType::I32 => wasmparser::Type::I32, 78 WasmType::I64 => wasmparser::Type::I64, 79 WasmType::F32 => wasmparser::Type::F32, 80 WasmType::F64 => wasmparser::Type::F64, 81 WasmType::V128 => wasmparser::Type::V128, 82 WasmType::FuncRef => wasmparser::Type::FuncRef, 83 WasmType::ExternRef => wasmparser::Type::ExternRef, 84 WasmType::ExnRef => wasmparser::Type::ExnRef, 85 } 86 } 87 } 88 89 /// WebAssembly function type -- equivalent of `wasmparser`'s FuncType. 90 #[derive(Debug, Clone, Eq, PartialEq, Hash)] 91 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 92 pub struct WasmFuncType { 93 /// Function params types. 94 pub params: Box<[WasmType]>, 95 /// Returns params types. 96 pub returns: Box<[WasmType]>, 97 } 98 99 impl TryFrom<wasmparser::FuncType> for WasmFuncType { 100 type Error = WasmError; try_from(ty: wasmparser::FuncType) -> Result<Self, Self::Error>101 fn try_from(ty: wasmparser::FuncType) -> Result<Self, Self::Error> { 102 Ok(Self { 103 params: ty 104 .params 105 .into_vec() 106 .into_iter() 107 .map(WasmType::try_from) 108 .collect::<Result<_, Self::Error>>()?, 109 returns: ty 110 .returns 111 .into_vec() 112 .into_iter() 113 .map(WasmType::try_from) 114 .collect::<Result<_, Self::Error>>()?, 115 }) 116 } 117 } 118 119 /// The value of a WebAssembly global variable. 120 #[derive(Clone, Copy)] 121 pub enum GlobalVariable { 122 /// This is a constant global with a value known at compile time. 123 Const(ir::Value), 124 125 /// This is a variable in memory that should be referenced through a `GlobalValue`. 126 Memory { 127 /// The address of the global variable storage. 128 gv: ir::GlobalValue, 129 /// An offset to add to the address. 130 offset: Offset32, 131 /// The global variable's type. 132 ty: ir::Type, 133 }, 134 135 /// This is a global variable that needs to be handled by the environment. 136 Custom, 137 } 138 139 /// A WebAssembly translation error. 140 /// 141 /// When a WebAssembly function can't be translated, one of these error codes will be returned 142 /// to describe the failure. 143 #[derive(Error, Debug)] 144 pub enum WasmError { 145 /// The input WebAssembly code is invalid. 146 /// 147 /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly 148 /// code. This should never happen for validated WebAssembly code. 149 #[error("Invalid input WebAssembly code at offset {offset}: {message}")] 150 InvalidWebAssembly { 151 /// A string describing the validation error. 152 message: std::string::String, 153 /// The bytecode offset where the error occurred. 154 offset: usize, 155 }, 156 157 /// A feature used by the WebAssembly code is not supported by the embedding environment. 158 /// 159 /// Embedding environments may have their own limitations and feature restrictions. 160 #[error("Unsupported feature: {0}")] 161 Unsupported(std::string::String), 162 163 /// An implementation limit was exceeded. 164 /// 165 /// Cranelift can compile very large and complicated functions, but the [implementation has 166 /// limits][limits] that cause compilation to fail when they are exceeded. 167 /// 168 /// [limits]: https://github.com/bytecodealliance/wasmtime/blob/main/cranelift/docs/ir.md#implementation-limits 169 #[error("Implementation limit exceeded")] 170 ImplLimitExceeded, 171 172 /// Any user-defined error. 173 #[error("User error: {0}")] 174 User(std::string::String), 175 } 176 177 /// Return an `Err(WasmError::Unsupported(msg))` where `msg` the string built by calling `format!` 178 /// on the arguments to this macro. 179 #[macro_export] 180 macro_rules! wasm_unsupported { 181 ($($arg:tt)*) => { $crate::environ::WasmError::Unsupported(format!($($arg)*)) } 182 } 183 184 impl From<BinaryReaderError> for WasmError { 185 /// Convert from a `BinaryReaderError` to a `WasmError`. from(e: BinaryReaderError) -> Self186 fn from(e: BinaryReaderError) -> Self { 187 Self::InvalidWebAssembly { 188 message: e.message().into(), 189 offset: e.offset(), 190 } 191 } 192 } 193 194 /// A convenient alias for a `Result` that uses `WasmError` as the error type. 195 pub type WasmResult<T> = Result<T, WasmError>; 196 197 /// How to return from functions. 198 #[derive(Copy, Clone, PartialEq, Eq, Debug)] 199 pub enum ReturnMode { 200 /// Use normal return instructions as needed. 201 NormalReturns, 202 /// Use a single fallthrough return at the end of the function. 203 FallthroughReturn, 204 } 205 206 /// An entry in the alias section of a wasm module (from the module linking 207 /// proposal) 208 pub enum Alias<'a> { 209 /// An outer module's module is being aliased into our own index space. 210 OuterModule { 211 /// The number of modules above us that we're referencing. 212 relative_depth: u32, 213 /// The module index in the outer module's index space we're referencing. 214 index: ModuleIndex, 215 }, 216 217 /// An outer module's type is being aliased into our own index space 218 /// 219 /// Note that the index here is in the outer module's index space, not our 220 /// own. 221 OuterType { 222 /// The number of modules above us that we're referencing. 223 relative_depth: u32, 224 /// The type index in the outer module's index space we're referencing. 225 index: TypeIndex, 226 }, 227 228 /// A previously created instance is having one of its exports aliased into 229 /// our index space. 230 InstanceExport { 231 /// The index we're aliasing. 232 instance: InstanceIndex, 233 /// The nth export that we're inserting into our own index space 234 /// locally. 235 export: &'a str, 236 }, 237 } 238 239 /// Environment affecting the translation of a WebAssembly. 240 pub trait TargetEnvironment { 241 /// Get the information needed to produce Cranelift IR for the given target. target_config(&self) -> TargetFrontendConfig242 fn target_config(&self) -> TargetFrontendConfig; 243 244 /// Get the Cranelift integer type to use for native pointers. 245 /// 246 /// This returns `I64` for 64-bit architectures and `I32` for 32-bit architectures. pointer_type(&self) -> ir::Type247 fn pointer_type(&self) -> ir::Type { 248 ir::Type::int(u16::from(self.target_config().pointer_bits())).unwrap() 249 } 250 251 /// Get the size of a native pointer, in bytes. pointer_bytes(&self) -> u8252 fn pointer_bytes(&self) -> u8 { 253 self.target_config().pointer_bytes() 254 } 255 256 /// Get the Cranelift reference type to use for the given Wasm reference 257 /// type. 258 /// 259 /// By default, this returns `R64` for 64-bit architectures and `R32` for 260 /// 32-bit architectures. If you override this, then you should also 261 /// override `FuncEnvironment::{translate_ref_null, translate_ref_is_null}` 262 /// as well. reference_type(&self, ty: WasmType) -> ir::Type263 fn reference_type(&self, ty: WasmType) -> ir::Type { 264 let _ = ty; 265 match self.pointer_type() { 266 ir::types::I32 => ir::types::R32, 267 ir::types::I64 => ir::types::R64, 268 _ => panic!("unsupported pointer type"), 269 } 270 } 271 } 272 273 /// Environment affecting the translation of a single WebAssembly function. 274 /// 275 /// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cranelift 276 /// IR. The function environment provides information about the WebAssembly module as well as the 277 /// runtime environment. 278 pub trait FuncEnvironment: TargetEnvironment { 279 /// Is the given parameter of the given function a wasm-level parameter, as opposed to a hidden 280 /// parameter added for use by the implementation? is_wasm_parameter(&self, signature: &ir::Signature, index: usize) -> bool281 fn is_wasm_parameter(&self, signature: &ir::Signature, index: usize) -> bool { 282 signature.params[index].purpose == ir::ArgumentPurpose::Normal 283 } 284 285 /// Is the given return of the given function a wasm-level parameter, as 286 /// opposed to a hidden parameter added for use by the implementation? is_wasm_return(&self, signature: &ir::Signature, index: usize) -> bool287 fn is_wasm_return(&self, signature: &ir::Signature, index: usize) -> bool { 288 signature.returns[index].purpose == ir::ArgumentPurpose::Normal 289 } 290 291 /// Should the code be structured to use a single `fallthrough_return` instruction at the end 292 /// of the function body, rather than `return` instructions as needed? This is used by VMs 293 /// to append custom epilogues. return_mode(&self) -> ReturnMode294 fn return_mode(&self) -> ReturnMode { 295 ReturnMode::NormalReturns 296 } 297 298 /// Called after the locals for a function have been parsed, and the number 299 /// of variables defined by this function is provided. after_locals(&mut self, num_locals_defined: usize)300 fn after_locals(&mut self, num_locals_defined: usize) { 301 drop(num_locals_defined); 302 } 303 304 /// Set up the necessary preamble definitions in `func` to access the global variable 305 /// identified by `index`. 306 /// 307 /// The index space covers both imported globals and globals defined by the module. 308 /// 309 /// Return the global variable reference that should be used to access the global and the 310 /// WebAssembly type of the global. make_global( &mut self, func: &mut ir::Function, index: GlobalIndex, ) -> WasmResult<GlobalVariable>311 fn make_global( 312 &mut self, 313 func: &mut ir::Function, 314 index: GlobalIndex, 315 ) -> WasmResult<GlobalVariable>; 316 317 /// Set up the necessary preamble definitions in `func` to access the linear memory identified 318 /// by `index`. 319 /// 320 /// The index space covers both imported and locally declared memories. make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> WasmResult<ir::Heap>321 fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> WasmResult<ir::Heap>; 322 323 /// Set up the necessary preamble definitions in `func` to access the table identified 324 /// by `index`. 325 /// 326 /// The index space covers both imported and locally declared tables. make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table>327 fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table>; 328 329 /// Set up a signature definition in the preamble of `func` that can be used for an indirect 330 /// call with signature `index`. 331 /// 332 /// The signature may contain additional arguments needed for an indirect call, but the 333 /// arguments marked as `ArgumentPurpose::Normal` must correspond to the WebAssembly signature 334 /// arguments. 335 /// 336 /// The signature will only be used for indirect calls, even if the module has direct function 337 /// calls with the same WebAssembly type. make_indirect_sig( &mut self, func: &mut ir::Function, index: TypeIndex, ) -> WasmResult<ir::SigRef>338 fn make_indirect_sig( 339 &mut self, 340 func: &mut ir::Function, 341 index: TypeIndex, 342 ) -> WasmResult<ir::SigRef>; 343 344 /// Set up an external function definition in the preamble of `func` that can be used to 345 /// directly call the function `index`. 346 /// 347 /// The index space covers both imported functions and functions defined in the current module. 348 /// 349 /// The function's signature may contain additional arguments needed for a direct call, but the 350 /// arguments marked as `ArgumentPurpose::Normal` must correspond to the WebAssembly signature 351 /// arguments. 352 /// 353 /// The function's signature will only be used for direct calls, even if the module has 354 /// indirect calls with the same WebAssembly type. make_direct_func( &mut self, func: &mut ir::Function, index: FuncIndex, ) -> WasmResult<ir::FuncRef>355 fn make_direct_func( 356 &mut self, 357 func: &mut ir::Function, 358 index: FuncIndex, 359 ) -> WasmResult<ir::FuncRef>; 360 361 /// Translate a `call_indirect` WebAssembly instruction at `pos`. 362 /// 363 /// Insert instructions at `pos` for an indirect call to the function `callee` in the table 364 /// `table_index` with WebAssembly signature `sig_index`. The `callee` value will have type 365 /// `i32`. 366 /// 367 /// The signature `sig_ref` was previously created by `make_indirect_sig()`. 368 /// 369 /// Return the call instruction whose results are the WebAssembly return values. 370 #[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: TypeIndex, sig_ref: ir::SigRef, callee: ir::Value, call_args: &[ir::Value], ) -> WasmResult<ir::Inst>371 fn translate_call_indirect( 372 &mut self, 373 pos: FuncCursor, 374 table_index: TableIndex, 375 table: ir::Table, 376 sig_index: TypeIndex, 377 sig_ref: ir::SigRef, 378 callee: ir::Value, 379 call_args: &[ir::Value], 380 ) -> WasmResult<ir::Inst>; 381 382 /// Translate a `call` WebAssembly instruction at `pos`. 383 /// 384 /// Insert instructions at `pos` for a direct call to the function `callee_index`. 385 /// 386 /// The function reference `callee` was previously created by `make_direct_func()`. 387 /// 388 /// 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>389 fn translate_call( 390 &mut self, 391 mut pos: FuncCursor, 392 _callee_index: FuncIndex, 393 callee: ir::FuncRef, 394 call_args: &[ir::Value], 395 ) -> WasmResult<ir::Inst> { 396 Ok(pos.ins().call(callee, call_args)) 397 } 398 399 /// Translate a `memory.grow` WebAssembly instruction. 400 /// 401 /// The `index` provided identifies the linear memory to grow, and `heap` is the heap reference 402 /// returned by `make_heap` for the same index. 403 /// 404 /// The `val` value is the requested memory size in pages. 405 /// 406 /// 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>407 fn translate_memory_grow( 408 &mut self, 409 pos: FuncCursor, 410 index: MemoryIndex, 411 heap: ir::Heap, 412 val: ir::Value, 413 ) -> WasmResult<ir::Value>; 414 415 /// Translates a `memory.size` WebAssembly instruction. 416 /// 417 /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference 418 /// returned by `make_heap` for the same index. 419 /// 420 /// Returns the size in pages of the memory. translate_memory_size( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, ) -> WasmResult<ir::Value>421 fn translate_memory_size( 422 &mut self, 423 pos: FuncCursor, 424 index: MemoryIndex, 425 heap: ir::Heap, 426 ) -> WasmResult<ir::Value>; 427 428 /// Translate a `memory.copy` WebAssembly instruction. 429 /// 430 /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference 431 /// returned by `make_heap` for the same index. translate_memory_copy( &mut self, pos: FuncCursor, src_index: MemoryIndex, src_heap: ir::Heap, dst_index: MemoryIndex, dst_heap: ir::Heap, dst: ir::Value, src: ir::Value, len: ir::Value, ) -> WasmResult<()>432 fn translate_memory_copy( 433 &mut self, 434 pos: FuncCursor, 435 src_index: MemoryIndex, 436 src_heap: ir::Heap, 437 dst_index: MemoryIndex, 438 dst_heap: ir::Heap, 439 dst: ir::Value, 440 src: ir::Value, 441 len: ir::Value, 442 ) -> WasmResult<()>; 443 444 /// Translate a `memory.fill` WebAssembly instruction. 445 /// 446 /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference 447 /// 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<()>448 fn translate_memory_fill( 449 &mut self, 450 pos: FuncCursor, 451 index: MemoryIndex, 452 heap: ir::Heap, 453 dst: ir::Value, 454 val: ir::Value, 455 len: ir::Value, 456 ) -> WasmResult<()>; 457 458 /// Translate a `memory.init` WebAssembly instruction. 459 /// 460 /// The `index` provided identifies the linear memory to query, and `heap` is the heap reference 461 /// returned by `make_heap` for the same index. `seg_index` is the index of the segment to copy 462 /// from. 463 #[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<()>464 fn translate_memory_init( 465 &mut self, 466 pos: FuncCursor, 467 index: MemoryIndex, 468 heap: ir::Heap, 469 seg_index: u32, 470 dst: ir::Value, 471 src: ir::Value, 472 len: ir::Value, 473 ) -> WasmResult<()>; 474 475 /// Translate a `data.drop` WebAssembly instruction. translate_data_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>476 fn translate_data_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>; 477 478 /// Translate a `table.size` WebAssembly instruction. translate_table_size( &mut self, pos: FuncCursor, index: TableIndex, table: ir::Table, ) -> WasmResult<ir::Value>479 fn translate_table_size( 480 &mut self, 481 pos: FuncCursor, 482 index: TableIndex, 483 table: ir::Table, 484 ) -> WasmResult<ir::Value>; 485 486 /// Translate a `table.grow` WebAssembly instruction. translate_table_grow( &mut self, pos: FuncCursor, table_index: TableIndex, table: ir::Table, delta: ir::Value, init_value: ir::Value, ) -> WasmResult<ir::Value>487 fn translate_table_grow( 488 &mut self, 489 pos: FuncCursor, 490 table_index: TableIndex, 491 table: ir::Table, 492 delta: ir::Value, 493 init_value: ir::Value, 494 ) -> WasmResult<ir::Value>; 495 496 /// Translate a `table.get` WebAssembly instruction. translate_table_get( &mut self, builder: &mut FunctionBuilder, table_index: TableIndex, table: ir::Table, index: ir::Value, ) -> WasmResult<ir::Value>497 fn translate_table_get( 498 &mut self, 499 builder: &mut FunctionBuilder, 500 table_index: TableIndex, 501 table: ir::Table, 502 index: ir::Value, 503 ) -> WasmResult<ir::Value>; 504 505 /// Translate a `table.set` WebAssembly instruction. translate_table_set( &mut self, builder: &mut FunctionBuilder, table_index: TableIndex, table: ir::Table, value: ir::Value, index: ir::Value, ) -> WasmResult<()>506 fn translate_table_set( 507 &mut self, 508 builder: &mut FunctionBuilder, 509 table_index: TableIndex, 510 table: ir::Table, 511 value: ir::Value, 512 index: ir::Value, 513 ) -> WasmResult<()>; 514 515 /// Translate a `table.copy` WebAssembly instruction. 516 #[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<()>517 fn translate_table_copy( 518 &mut self, 519 pos: FuncCursor, 520 dst_table_index: TableIndex, 521 dst_table: ir::Table, 522 src_table_index: TableIndex, 523 src_table: ir::Table, 524 dst: ir::Value, 525 src: ir::Value, 526 len: ir::Value, 527 ) -> WasmResult<()>; 528 529 /// 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<()>530 fn translate_table_fill( 531 &mut self, 532 pos: FuncCursor, 533 table_index: TableIndex, 534 dst: ir::Value, 535 val: ir::Value, 536 len: ir::Value, 537 ) -> WasmResult<()>; 538 539 /// Translate a `table.init` WebAssembly instruction. 540 #[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<()>541 fn translate_table_init( 542 &mut self, 543 pos: FuncCursor, 544 seg_index: u32, 545 table_index: TableIndex, 546 table: ir::Table, 547 dst: ir::Value, 548 src: ir::Value, 549 len: ir::Value, 550 ) -> WasmResult<()>; 551 552 /// Translate a `elem.drop` WebAssembly instruction. translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>553 fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>; 554 555 /// Translate a `ref.null T` WebAssembly instruction. 556 /// 557 /// By default, translates into a null reference type. 558 /// 559 /// Override this if you don't use Cranelift reference types for all Wasm 560 /// reference types (e.g. you use a raw pointer for `funcref`s) or if the 561 /// null sentinel is not a null reference type pointer for your type. If you 562 /// override this method, then you should also override 563 /// `translate_ref_is_null` as well. translate_ref_null(&mut self, mut pos: FuncCursor, ty: WasmType) -> WasmResult<ir::Value>564 fn translate_ref_null(&mut self, mut pos: FuncCursor, ty: WasmType) -> WasmResult<ir::Value> { 565 let _ = ty; 566 Ok(pos.ins().null(self.reference_type(ty))) 567 } 568 569 /// Translate a `ref.is_null` WebAssembly instruction. 570 /// 571 /// By default, assumes that `value` is a Cranelift reference type, and that 572 /// a null Cranelift reference type is the null value for all Wasm reference 573 /// types. 574 /// 575 /// If you override this method, you probably also want to override 576 /// `translate_ref_null` as well. translate_ref_is_null( &mut self, mut pos: FuncCursor, value: ir::Value, ) -> WasmResult<ir::Value>577 fn translate_ref_is_null( 578 &mut self, 579 mut pos: FuncCursor, 580 value: ir::Value, 581 ) -> WasmResult<ir::Value> { 582 let is_null = pos.ins().is_null(value); 583 Ok(pos.ins().bint(ir::types::I32, is_null)) 584 } 585 586 /// Translate a `ref.func` WebAssembly instruction. translate_ref_func( &mut self, pos: FuncCursor, func_index: FuncIndex, ) -> WasmResult<ir::Value>587 fn translate_ref_func( 588 &mut self, 589 pos: FuncCursor, 590 func_index: FuncIndex, 591 ) -> WasmResult<ir::Value>; 592 593 /// Translate a `global.get` WebAssembly instruction at `pos` for a global 594 /// that is custom. translate_custom_global_get( &mut self, pos: FuncCursor, global_index: GlobalIndex, ) -> WasmResult<ir::Value>595 fn translate_custom_global_get( 596 &mut self, 597 pos: FuncCursor, 598 global_index: GlobalIndex, 599 ) -> WasmResult<ir::Value>; 600 601 /// Translate a `global.set` WebAssembly instruction at `pos` for a global 602 /// that is custom. translate_custom_global_set( &mut self, pos: FuncCursor, global_index: GlobalIndex, val: ir::Value, ) -> WasmResult<()>603 fn translate_custom_global_set( 604 &mut self, 605 pos: FuncCursor, 606 global_index: GlobalIndex, 607 val: ir::Value, 608 ) -> WasmResult<()>; 609 610 /// Translate an `i32.atomic.wait` or `i64.atomic.wait` WebAssembly instruction. 611 /// The `index` provided identifies the linear memory containing the value 612 /// to wait on, and `heap` is the heap reference returned by `make_heap` 613 /// for the same index. Whether the waited-on value is 32- or 64-bit can be 614 /// determined by examining the type of `expected`, which must be only I32 or I64. 615 /// 616 /// Returns an i32, which is negative if the helper call failed. translate_atomic_wait( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, addr: ir::Value, expected: ir::Value, timeout: ir::Value, ) -> WasmResult<ir::Value>617 fn translate_atomic_wait( 618 &mut self, 619 pos: FuncCursor, 620 index: MemoryIndex, 621 heap: ir::Heap, 622 addr: ir::Value, 623 expected: ir::Value, 624 timeout: ir::Value, 625 ) -> WasmResult<ir::Value>; 626 627 /// Translate an `atomic.notify` WebAssembly instruction. 628 /// The `index` provided identifies the linear memory containing the value 629 /// to wait on, and `heap` is the heap reference returned by `make_heap` 630 /// for the same index. 631 /// 632 /// Returns an i64, which is negative if the helper call failed. translate_atomic_notify( &mut self, pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, addr: ir::Value, count: ir::Value, ) -> WasmResult<ir::Value>633 fn translate_atomic_notify( 634 &mut self, 635 pos: FuncCursor, 636 index: MemoryIndex, 637 heap: ir::Heap, 638 addr: ir::Value, 639 count: ir::Value, 640 ) -> WasmResult<ir::Value>; 641 642 /// Emit code at the beginning of every wasm loop. 643 /// 644 /// This can be used to insert explicit interrupt or safepoint checking at 645 /// the beginnings of loops. translate_loop_header(&mut self, _builder: &mut FunctionBuilder) -> WasmResult<()>646 fn translate_loop_header(&mut self, _builder: &mut FunctionBuilder) -> WasmResult<()> { 647 // By default, don't emit anything. 648 Ok(()) 649 } 650 651 /// Optional callback for the `FunctionEnvironment` performing this translation to maintain 652 /// internal state or prepare custom state for the operator to translate before_translate_operator( &mut self, _op: &Operator, _builder: &mut FunctionBuilder, _state: &FuncTranslationState, ) -> WasmResult<()>653 fn before_translate_operator( 654 &mut self, 655 _op: &Operator, 656 _builder: &mut FunctionBuilder, 657 _state: &FuncTranslationState, 658 ) -> WasmResult<()> { 659 Ok(()) 660 } 661 662 /// Optional callback for the `FunctionEnvironment` performing this translation to maintain 663 /// 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<()>664 fn after_translate_operator( 665 &mut self, 666 _op: &Operator, 667 _builder: &mut FunctionBuilder, 668 _state: &FuncTranslationState, 669 ) -> WasmResult<()> { 670 Ok(()) 671 } 672 673 /// Optional callback for the `FunctionEnvironment` performing this translation to perform work 674 /// before the function body is translated. before_translate_function( &mut self, _builder: &mut FunctionBuilder, _state: &FuncTranslationState, ) -> WasmResult<()>675 fn before_translate_function( 676 &mut self, 677 _builder: &mut FunctionBuilder, 678 _state: &FuncTranslationState, 679 ) -> WasmResult<()> { 680 Ok(()) 681 } 682 683 /// Optional callback for the `FunctionEnvironment` performing this translation to perform work 684 /// after the function body is translated. after_translate_function( &mut self, _builder: &mut FunctionBuilder, _state: &FuncTranslationState, ) -> WasmResult<()>685 fn after_translate_function( 686 &mut self, 687 _builder: &mut FunctionBuilder, 688 _state: &FuncTranslationState, 689 ) -> WasmResult<()> { 690 Ok(()) 691 } 692 } 693 694 /// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the 695 /// [`translate_module`](fn.translate_module.html) function. These methods should not be called 696 /// by the user, they are only for `cranelift-wasm` internal use. 697 pub trait ModuleEnvironment<'data>: TargetEnvironment { 698 /// Provides the number of types up front. By default this does nothing, but 699 /// implementations can use this to preallocate memory if desired. reserve_types(&mut self, _num: u32) -> WasmResult<()>700 fn reserve_types(&mut self, _num: u32) -> WasmResult<()> { 701 Ok(()) 702 } 703 704 /// Declares a function signature to the environment. declare_type_func(&mut self, wasm_func_type: WasmFuncType) -> WasmResult<()>705 fn declare_type_func(&mut self, wasm_func_type: WasmFuncType) -> WasmResult<()>; 706 707 /// Declares a module type signature to the environment. declare_type_module( &mut self, imports: &[(&'data str, Option<&'data str>, EntityType)], exports: &[(&'data str, EntityType)], ) -> WasmResult<()>708 fn declare_type_module( 709 &mut self, 710 imports: &[(&'data str, Option<&'data str>, EntityType)], 711 exports: &[(&'data str, EntityType)], 712 ) -> WasmResult<()> { 713 drop((imports, exports)); 714 Err(WasmError::Unsupported("module linking".to_string())) 715 } 716 717 /// Declares an instance type signature to the environment. declare_type_instance(&mut self, exports: &[(&'data str, EntityType)]) -> WasmResult<()>718 fn declare_type_instance(&mut self, exports: &[(&'data str, EntityType)]) -> WasmResult<()> { 719 drop(exports); 720 Err(WasmError::Unsupported("module linking".to_string())) 721 } 722 723 /// Translates a type index to its signature index, only called for type 724 /// indices which point to functions. type_to_signature(&self, index: TypeIndex) -> WasmResult<SignatureIndex>725 fn type_to_signature(&self, index: TypeIndex) -> WasmResult<SignatureIndex> { 726 drop(index); 727 Err(WasmError::Unsupported("module linking".to_string())) 728 } 729 730 /// Translates a type index to its module type index, only called for type 731 /// indices which point to modules. type_to_module_type(&self, index: TypeIndex) -> WasmResult<ModuleTypeIndex>732 fn type_to_module_type(&self, index: TypeIndex) -> WasmResult<ModuleTypeIndex> { 733 drop(index); 734 Err(WasmError::Unsupported("module linking".to_string())) 735 } 736 737 /// Translates a type index to its instance type index, only called for type 738 /// indices which point to instances. type_to_instance_type(&self, index: TypeIndex) -> WasmResult<InstanceTypeIndex>739 fn type_to_instance_type(&self, index: TypeIndex) -> WasmResult<InstanceTypeIndex> { 740 drop(index); 741 Err(WasmError::Unsupported("module linking".to_string())) 742 } 743 744 /// Provides the number of imports up front. By default this does nothing, but 745 /// implementations can use this to preallocate memory if desired. reserve_imports(&mut self, _num: u32) -> WasmResult<()>746 fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> { 747 Ok(()) 748 } 749 750 /// Declares a function import to the environment. declare_func_import( &mut self, index: TypeIndex, module: &'data str, field: Option<&'data str>, ) -> WasmResult<()>751 fn declare_func_import( 752 &mut self, 753 index: TypeIndex, 754 module: &'data str, 755 field: Option<&'data str>, 756 ) -> WasmResult<()>; 757 758 /// Declares a table import to the environment. declare_table_import( &mut self, table: Table, module: &'data str, field: Option<&'data str>, ) -> WasmResult<()>759 fn declare_table_import( 760 &mut self, 761 table: Table, 762 module: &'data str, 763 field: Option<&'data str>, 764 ) -> WasmResult<()>; 765 766 /// Declares a memory import to the environment. declare_memory_import( &mut self, memory: Memory, module: &'data str, field: Option<&'data str>, ) -> WasmResult<()>767 fn declare_memory_import( 768 &mut self, 769 memory: Memory, 770 module: &'data str, 771 field: Option<&'data str>, 772 ) -> WasmResult<()>; 773 774 /// Declares an event import to the environment. declare_event_import( &mut self, event: Event, module: &'data str, field: Option<&'data str>, ) -> WasmResult<()>775 fn declare_event_import( 776 &mut self, 777 event: Event, 778 module: &'data str, 779 field: Option<&'data str>, 780 ) -> WasmResult<()> { 781 drop((event, module, field)); 782 Err(WasmError::Unsupported("wasm events".to_string())) 783 } 784 785 /// Declares a global import to the environment. declare_global_import( &mut self, global: Global, module: &'data str, field: Option<&'data str>, ) -> WasmResult<()>786 fn declare_global_import( 787 &mut self, 788 global: Global, 789 module: &'data str, 790 field: Option<&'data str>, 791 ) -> WasmResult<()>; 792 793 /// Declares a module import to the environment. declare_module_import( &mut self, ty_index: TypeIndex, module: &'data str, field: Option<&'data str>, ) -> WasmResult<()>794 fn declare_module_import( 795 &mut self, 796 ty_index: TypeIndex, 797 module: &'data str, 798 field: Option<&'data str>, 799 ) -> WasmResult<()> { 800 drop((ty_index, module, field)); 801 Err(WasmError::Unsupported("module linking".to_string())) 802 } 803 804 /// Declares an instance import to the environment. declare_instance_import( &mut self, ty_index: TypeIndex, module: &'data str, field: Option<&'data str>, ) -> WasmResult<()>805 fn declare_instance_import( 806 &mut self, 807 ty_index: TypeIndex, 808 module: &'data str, 809 field: Option<&'data str>, 810 ) -> WasmResult<()> { 811 drop((ty_index, module, field)); 812 Err(WasmError::Unsupported("module linking".to_string())) 813 } 814 815 /// Notifies the implementation that all imports have been declared. finish_imports(&mut self) -> WasmResult<()>816 fn finish_imports(&mut self) -> WasmResult<()> { 817 Ok(()) 818 } 819 820 /// Provides the number of defined functions up front. By default this does nothing, but 821 /// implementations can use this to preallocate memory if desired. reserve_func_types(&mut self, _num: u32) -> WasmResult<()>822 fn reserve_func_types(&mut self, _num: u32) -> WasmResult<()> { 823 Ok(()) 824 } 825 826 /// Declares the type (signature) of a local function in the module. declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()>827 fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()>; 828 829 /// Provides the number of defined tables up front. By default this does nothing, but 830 /// implementations can use this to preallocate memory if desired. reserve_tables(&mut self, _num: u32) -> WasmResult<()>831 fn reserve_tables(&mut self, _num: u32) -> WasmResult<()> { 832 Ok(()) 833 } 834 835 /// Declares a table to the environment. declare_table(&mut self, table: Table) -> WasmResult<()>836 fn declare_table(&mut self, table: Table) -> WasmResult<()>; 837 838 /// Provides the number of defined memories up front. By default this does nothing, but 839 /// implementations can use this to preallocate memory if desired. reserve_memories(&mut self, _num: u32) -> WasmResult<()>840 fn reserve_memories(&mut self, _num: u32) -> WasmResult<()> { 841 Ok(()) 842 } 843 844 /// Declares a memory to the environment declare_memory(&mut self, memory: Memory) -> WasmResult<()>845 fn declare_memory(&mut self, memory: Memory) -> WasmResult<()>; 846 847 /// Provides the number of defined events up front. By default this does nothing, but 848 /// implementations can use this to preallocate memory if desired. reserve_events(&mut self, _num: u32) -> WasmResult<()>849 fn reserve_events(&mut self, _num: u32) -> WasmResult<()> { 850 Ok(()) 851 } 852 853 /// Declares an event to the environment declare_event(&mut self, event: Event) -> WasmResult<()>854 fn declare_event(&mut self, event: Event) -> WasmResult<()> { 855 drop(event); 856 Err(WasmError::Unsupported("wasm events".to_string())) 857 } 858 859 /// Provides the number of defined globals up front. By default this does nothing, but 860 /// implementations can use this to preallocate memory if desired. reserve_globals(&mut self, _num: u32) -> WasmResult<()>861 fn reserve_globals(&mut self, _num: u32) -> WasmResult<()> { 862 Ok(()) 863 } 864 865 /// Declares a global to the environment. declare_global(&mut self, global: Global) -> WasmResult<()>866 fn declare_global(&mut self, global: Global) -> WasmResult<()>; 867 868 /// Provides the number of exports up front. By default this does nothing, but 869 /// implementations can use this to preallocate memory if desired. reserve_exports(&mut self, _num: u32) -> WasmResult<()>870 fn reserve_exports(&mut self, _num: u32) -> WasmResult<()> { 871 Ok(()) 872 } 873 874 /// Declares a function export to the environment. declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>875 fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>; 876 877 /// Declares a table export to the environment. declare_table_export(&mut self, table_index: TableIndex, name: &'data str) -> WasmResult<()>878 fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str) 879 -> WasmResult<()>; 880 881 /// Declares a memory export to the environment. declare_memory_export( &mut self, memory_index: MemoryIndex, name: &'data str, ) -> WasmResult<()>882 fn declare_memory_export( 883 &mut self, 884 memory_index: MemoryIndex, 885 name: &'data str, 886 ) -> WasmResult<()>; 887 888 /// Declares an event export to the environment. declare_event_export( &mut self, event_index: EventIndex, name: &'data str, ) -> WasmResult<()>889 fn declare_event_export( 890 &mut self, 891 event_index: EventIndex, 892 name: &'data str, 893 ) -> WasmResult<()> { 894 drop((event_index, name)); 895 Err(WasmError::Unsupported("wasm events".to_string())) 896 } 897 898 /// Declares a global export to the environment. declare_global_export( &mut self, global_index: GlobalIndex, name: &'data str, ) -> WasmResult<()>899 fn declare_global_export( 900 &mut self, 901 global_index: GlobalIndex, 902 name: &'data str, 903 ) -> WasmResult<()>; 904 905 /// Declares an instance export to the environment. declare_instance_export( &mut self, index: InstanceIndex, name: &'data str, ) -> WasmResult<()>906 fn declare_instance_export( 907 &mut self, 908 index: InstanceIndex, 909 name: &'data str, 910 ) -> WasmResult<()> { 911 drop((index, name)); 912 Err(WasmError::Unsupported("module linking".to_string())) 913 } 914 915 /// Declares an instance export to the environment. declare_module_export(&mut self, index: ModuleIndex, name: &'data str) -> WasmResult<()>916 fn declare_module_export(&mut self, index: ModuleIndex, name: &'data str) -> WasmResult<()> { 917 drop((index, name)); 918 Err(WasmError::Unsupported("module linking".to_string())) 919 } 920 921 /// Notifies the implementation that all exports have been declared. finish_exports(&mut self) -> WasmResult<()>922 fn finish_exports(&mut self) -> WasmResult<()> { 923 Ok(()) 924 } 925 926 /// Declares the optional start function. declare_start_func(&mut self, index: FuncIndex) -> WasmResult<()>927 fn declare_start_func(&mut self, index: FuncIndex) -> WasmResult<()>; 928 929 /// Provides the number of element initializers up front. By default this does nothing, but 930 /// implementations can use this to preallocate memory if desired. reserve_table_elements(&mut self, _num: u32) -> WasmResult<()>931 fn reserve_table_elements(&mut self, _num: u32) -> WasmResult<()> { 932 Ok(()) 933 } 934 935 /// Fills a declared table with references to functions in the module. declare_table_elements( &mut self, table_index: TableIndex, base: Option<GlobalIndex>, offset: u32, elements: Box<[FuncIndex]>, ) -> WasmResult<()>936 fn declare_table_elements( 937 &mut self, 938 table_index: TableIndex, 939 base: Option<GlobalIndex>, 940 offset: u32, 941 elements: Box<[FuncIndex]>, 942 ) -> WasmResult<()>; 943 944 /// Declare a passive element segment. declare_passive_element( &mut self, index: ElemIndex, elements: Box<[FuncIndex]>, ) -> WasmResult<()>945 fn declare_passive_element( 946 &mut self, 947 index: ElemIndex, 948 elements: Box<[FuncIndex]>, 949 ) -> WasmResult<()>; 950 951 /// Indicates that a declarative element segment was seen in the wasm 952 /// module. declare_elements(&mut self, elements: Box<[FuncIndex]>) -> WasmResult<()>953 fn declare_elements(&mut self, elements: Box<[FuncIndex]>) -> WasmResult<()> { 954 drop(elements); 955 Ok(()) 956 } 957 958 /// Provides the number of passive data segments up front. 959 /// 960 /// By default this does nothing, but implementations may use this to 961 /// pre-allocate memory if desired. reserve_passive_data(&mut self, count: u32) -> WasmResult<()>962 fn reserve_passive_data(&mut self, count: u32) -> WasmResult<()> { 963 let _ = count; 964 Ok(()) 965 } 966 967 /// Declare a passive data segment. declare_passive_data(&mut self, data_index: DataIndex, data: &'data [u8]) -> WasmResult<()>968 fn declare_passive_data(&mut self, data_index: DataIndex, data: &'data [u8]) -> WasmResult<()>; 969 970 /// Indicates how many functions the code section reports and the byte 971 /// offset of where the code sections starts. reserve_function_bodies(&mut self, bodies: u32, code_section_offset: u64)972 fn reserve_function_bodies(&mut self, bodies: u32, code_section_offset: u64) { 973 drop((bodies, code_section_offset)); 974 } 975 976 /// Provides the contents of a function body. define_function_body( &mut self, validator: FuncValidator<ValidatorResources>, body: FunctionBody<'data>, ) -> WasmResult<()>977 fn define_function_body( 978 &mut self, 979 validator: FuncValidator<ValidatorResources>, 980 body: FunctionBody<'data>, 981 ) -> WasmResult<()>; 982 983 /// Provides the number of data initializers up front. By default this does nothing, but 984 /// implementations can use this to preallocate memory if desired. reserve_data_initializers(&mut self, _num: u32) -> WasmResult<()>985 fn reserve_data_initializers(&mut self, _num: u32) -> WasmResult<()> { 986 Ok(()) 987 } 988 989 /// Fills a declared memory with bytes at module instantiation. declare_data_initialization( &mut self, memory_index: MemoryIndex, base: Option<GlobalIndex>, offset: u32, data: &'data [u8], ) -> WasmResult<()>990 fn declare_data_initialization( 991 &mut self, 992 memory_index: MemoryIndex, 993 base: Option<GlobalIndex>, 994 offset: u32, 995 data: &'data [u8], 996 ) -> WasmResult<()>; 997 998 /// Declares the name of a module to the environment. 999 /// 1000 /// By default this does nothing, but implementations can use this to read 1001 /// the module name subsection of the custom name section if desired. declare_module_name(&mut self, _name: &'data str)1002 fn declare_module_name(&mut self, _name: &'data str) {} 1003 1004 /// Declares the name of a function to the environment. 1005 /// 1006 /// By default this does nothing, but implementations can use this to read 1007 /// the function name subsection of the custom name section if desired. declare_func_name(&mut self, _func_index: FuncIndex, _name: &'data str)1008 fn declare_func_name(&mut self, _func_index: FuncIndex, _name: &'data str) {} 1009 1010 /// Declares the name of a function's local to the environment. 1011 /// 1012 /// By default this does nothing, but implementations can use this to read 1013 /// the local name subsection of the custom name section if desired. declare_local_name(&mut self, _func_index: FuncIndex, _local_index: u32, _name: &'data str)1014 fn declare_local_name(&mut self, _func_index: FuncIndex, _local_index: u32, _name: &'data str) { 1015 } 1016 1017 /// Indicates that a custom section has been found in the wasm file custom_section(&mut self, _name: &'data str, _data: &'data [u8]) -> WasmResult<()>1018 fn custom_section(&mut self, _name: &'data str, _data: &'data [u8]) -> WasmResult<()> { 1019 Ok(()) 1020 } 1021 1022 /// Returns the list of enabled wasm features this translation will be using. wasm_features(&self) -> WasmFeatures1023 fn wasm_features(&self) -> WasmFeatures { 1024 WasmFeatures::default() 1025 } 1026 1027 /// Indicates that this module will have `amount` submodules. 1028 /// 1029 /// Note that this is just child modules of this module, and each child 1030 /// module may have yet more submodules. reserve_modules(&mut self, amount: u32)1031 fn reserve_modules(&mut self, amount: u32) { 1032 drop(amount); 1033 } 1034 1035 /// Called at the beginning of translating a module. 1036 /// 1037 /// Note that for nested modules this may be called multiple times. module_start(&mut self)1038 fn module_start(&mut self) {} 1039 1040 /// Called at the end of translating a module. 1041 /// 1042 /// Note that for nested modules this may be called multiple times. module_end(&mut self)1043 fn module_end(&mut self) {} 1044 1045 /// Indicates that this module will have `amount` instances. reserve_instances(&mut self, amount: u32)1046 fn reserve_instances(&mut self, amount: u32) { 1047 drop(amount); 1048 } 1049 1050 /// Declares a new instance which this module will instantiate before it's 1051 /// instantiated. declare_instance( &mut self, module: ModuleIndex, args: Vec<(&'data str, EntityIndex)>, ) -> WasmResult<()>1052 fn declare_instance( 1053 &mut self, 1054 module: ModuleIndex, 1055 args: Vec<(&'data str, EntityIndex)>, 1056 ) -> WasmResult<()> { 1057 drop((module, args)); 1058 Err(WasmError::Unsupported("wasm instance".to_string())) 1059 } 1060 1061 /// Declares a new alias being added to this module. 1062 /// 1063 /// The alias comes from the `instance` specified (or the parent if `None` 1064 /// is supplied) and the index is either in the module's own index spaces 1065 /// for the parent or an index into the exports for nested instances. declare_alias(&mut self, alias: Alias<'data>) -> WasmResult<()>1066 fn declare_alias(&mut self, alias: Alias<'data>) -> WasmResult<()> { 1067 drop(alias); 1068 Err(WasmError::Unsupported("wasm alias".to_string())) 1069 } 1070 } 1071