Invokes the underlying wasm function, lowering arguments and lifting the result. The `lower` function and `lift` function provided here are what actually do the lowering and lifting. The `LowerParams` and `LowerReturn` types are what will be allocated on the stack for this function call. They should be appropriately sized for the lowering/lifting operation happening. # Safety The safety of this
(
&self,
mut store: StoreContextMut<'_, T>,
lower: impl FnOnce(
&mut LowerContext<'_, T>,
InterfaceType,
&mut MaybeUninit<LowerParams>,
| 425 | /// for the params/results that are going to be produced. Additionally |
| 426 | /// these types must be representable with a sequence of `ValRaw` values. |
| 427 | unsafe fn call_raw<T, Return, LowerParams, LowerReturn>( |
| 428 | &self, |
| 429 | mut store: StoreContextMut<'_, T>, |
| 430 | lower: impl FnOnce( |
| 431 | &mut LowerContext<'_, T>, |
| 432 | InterfaceType, |
| 433 | &mut MaybeUninit<LowerParams>, |
| 434 | ) -> Result<()>, |
| 435 | lift: impl FnOnce(&mut LiftContext<'_>, InterfaceType, &LowerReturn) -> Result<Return>, |
| 436 | ) -> Result<(Return, ValRaw)> |
| 437 | where |
| 438 | LowerParams: Copy, |
| 439 | LowerReturn: Copy, |
| 440 | { |
| 441 | let export = self.lifted_core_func(store.0); |
| 442 | let (_options, _flags, _ty, raw_options) = self.abi_info(store.0); |
| 443 | let instance = self.instance.runtime_instance(raw_options.instance); |
| 444 | |
| 445 | if !store.0.may_enter(instance)? { |
| 446 | bail!(crate::Trap::CannotEnterComponent); |
| 447 | } |
| 448 | |
| 449 | let async_type = self.abi_async(store.0); |
| 450 | store.0.enter_guest_sync_call(None, async_type, instance)?; |
| 451 | |
| 452 | #[repr(C)] |
| 453 | union Union<Params: Copy, Return: Copy> { |
| 454 | params: Params, |
| 455 | ret: Return, |
| 456 | } |
| 457 | |
| 458 | let space = &mut MaybeUninit::<Union<LowerParams, LowerReturn>>::uninit(); |
| 459 | |
| 460 | // Double-check the size/alignment of `space`, just in case. |
| 461 | // |
| 462 | // Note that this alone is not enough to guarantee the validity of the |
| 463 | // `unsafe` block below, but it's definitely required. In any case LLVM |
| 464 | // should be able to trivially see through these assertions and remove |
| 465 | // them in release mode. |
| 466 | let val_size = mem::size_of::<ValRaw>(); |
| 467 | let val_align = mem::align_of::<ValRaw>(); |
| 468 | assert!(mem::size_of_val(space) % val_size == 0); |
| 469 | assert!(mem::size_of_val(map_maybe_uninit!(space.params)) % val_size == 0); |
| 470 | assert!(mem::size_of_val(map_maybe_uninit!(space.ret)) % val_size == 0); |
| 471 | assert!(mem::align_of_val(space) == val_align); |
| 472 | assert!(mem::align_of_val(map_maybe_uninit!(space.params)) == val_align); |
| 473 | assert!(mem::align_of_val(map_maybe_uninit!(space.ret)) == val_align); |
| 474 | |
| 475 | self.with_lower_context(store.as_context_mut(), |cx, ty| { |
| 476 | lower(cx, ty, map_maybe_uninit!(space.params)) |
| 477 | })?; |
| 478 | |
| 479 | // SAFETY: We are providing the guarantee that all the inputs are valid. |
| 480 | // The various pointers passed in for the function are all valid since |
| 481 | // they're coming from our store, and the `params_and_results` should |
| 482 | // have the correct layout for the core wasm function we're calling. |
| 483 | // Note that this latter point relies on the correctness of this module |
| 484 | // and `ComponentType` implementations, hence `ComponentType` being an |
no test coverage detected