mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-15 12:44:31 +03:00
44c3f8ad2d
This crate provides a transformation to turn exported functions that use a return pointer into exported functions that use multi-value. Consider the following function: ```rust pub extern "C" fn pair(a: u32, b: u32) -> [u32; 2] { [a, b] } ``` LLVM will by default compile this down into the following Wasm: ```wasm (func $pair (param i32 i32 i32) local.get 0 local.get 2 i32.store offset=4 local.get 0 local.get 1 i32.store) ``` What's happening here is that the function is not directly returning the pair at all, but instead the first `i32` parameter is a pointer to some scratch space, and the return value is written into the scratch space. LLVM does this because it doesn't yet have support for multi-value Wasm, and so it only knows how to return a single value at a time. Ideally, with multi-value, what we would like instead is this: ```wasm (func $pair (param i32 i32) (result i32 i32) local.get 0 local.get 1) ``` However, that's not what this transformation does at the moment. This transformation is a little simpler than mutating existing functions to produce a multi-value result, instead it introduces new functions that wrap the original function and translate the return pointer to multi-value results in this wrapper function. With our running example, we end up with this: ```wasm ;; The original function. (func $pair (param i32 i32 i32) local.get 0 local.get 2 i32.store offset=4 local.get 0 local.get 1 i32.store) (func $pairWrapper (param i32 i32) (result i32 i32) ;; Our return pointer that points to the scratch space we are allocating ;; on the shadow stack for calling `$pair`. (local i32) ;; Allocate space on the shadow stack for the result. global.get $shadowStackPointer i32.const 8 i32.sub local.tee 2 global.set $shadowStackPointer ;; Call `$pair` with our allocated shadow stack space for its results. local.get 2 local.get 0 local.get 1 call $pair ;; Copy the return values from the shadow stack to the wasm stack. local.get 2 i32.load local.get 2 offset=4 i32.load ;; Finally, restore the shadow stack pointer. local.get 2 i32.const 8 i32.add global.set $shadowStackPointer) ``` This `$pairWrapper` function is what we actually end up exporting instead of `$pair`.
17 lines
493 B
TOML
17 lines
493 B
TOML
[package]
|
|
name = "wasm-bindgen-multi-value-xform"
|
|
version = "0.2.50"
|
|
authors = ["The wasm-bindgen Developers"]
|
|
license = "MIT/Apache-2.0"
|
|
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/multi-value-xform"
|
|
homepage = "https://rustwasm.github.io/wasm-bindgen/"
|
|
documentation = "https://docs.rs/wasm-bindgen-multi-value-xform"
|
|
description = """
|
|
Internal multi-value transformations for wasm-bindgen
|
|
"""
|
|
edition = "2018"
|
|
|
|
[dependencies]
|
|
failure = "0.1"
|
|
walrus = "0.12.0"
|