mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-07-30 19:41:56 +00:00
Introduce the multi-value-xform
crate
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`.
This commit is contained in:
@@ -21,6 +21,7 @@ tempfile = "3.0"
|
||||
walrus = "0.12.0"
|
||||
wasm-bindgen-anyref-xform = { path = '../anyref-xform', version = '=0.2.50' }
|
||||
wasm-bindgen-shared = { path = "../shared", version = '=0.2.50' }
|
||||
wasm-bindgen-multi-value-xform = { path = '../multi-value-xform', version = '=0.2.50' }
|
||||
wasm-bindgen-threads-xform = { path = '../threads-xform', version = '=0.2.50' }
|
||||
wasm-bindgen-wasm-interpreter = { path = "../wasm-interpreter", version = '=0.2.50' }
|
||||
wasm-webidl-bindings = "0.5.0"
|
||||
|
Reference in New Issue
Block a user