gpt4 book ai didi

c - WASM : does anyone support multi-value WASM?

转载 作者:行者123 更新时间:2023-12-05 04:27:20 27 4
gpt4 key购买 nike

将多个值从 WebAssembly 传递到 Javascript 可能比需要的更难。通常,我发现我必须:

  1. 设置 Javascript 和 WebAssembly 之间共享的内存。
  2. 执行 WASM 工作以产生值(value)。
  3. 将值存储在共享内存中的某处。
  4. 输出一个指向 Javascript 的内存指针。
  5. 让 Javascript 从共享内存中检索值。

多值是 WASM 的一个特性,旨在使这更容易,多个值可以直接从 WASM 传递到 Javascript,无需处理指针。步骤变为:

  1. 执行 WASM 工作以产生值(value)。
  2. 将值输出到 Javascript。

例如:

(module
(func $multResult (export "multResult")
(result f64 f64)
f64.const 1
f64.const 2
)
)

我们直接输出1和2。

我可以使用 Rick Battagline's helpful functions从 WAT 编译 WASM(使用 slight fix 以正确支持多值标志):

node ./bin/watwasm bugrepro.wat -o newoutput.wasm -O3 --multi-value

将生成的 WASM 编译回 WAT,我们得到:

(module
(type $none_=>_f64_f64 (func (result f64 f64)))
(export "multResult" (func $0))
(func $0 (result f64 f64)
(tuple.make
(f64.const 1)
(f64.const 2)
)
)
)

tuple.make 命令是使函数可直接在 Javascript 中使用的秘诀。如果我写这个 Javascript:

const fs = require('fs');

const wasmBytes = fs.readFileSync('./newoutput.wasm');

WebAssembly.instantiate(wasmBytes)
.then(obj => obj.instance.exports)
.then(exported => exported.multResult())
.then(res => console.log(res));

我可以看到 [1,2] 是由 WASM 函数返回的。太棒了。

我希望能够使用比 WAT 更高级的语言来做到这一点。是否有任何高级语言产生多值 WASM?

最佳答案

有一个:C。

TinyGo does not ; Rust does not ; AssemblyScript does not .我不知道 Grain 是否这样做;无论哪种方式,我都找不到文档。

您必须以特殊方式使用 Emscripten 编译器。 (这显然只在 this Twitter entry 的任何地方提到过。)

首先,在 C 中构建函数。例如:

typedef struct _nums
{
int x;
int y;
} nums;

nums echo(int x, int y)
{
nums result = {x,y};
return result;
}

这定义了一个包含两个 int 的 C struct,然后定义了一个函数来回显发送给它的任何内容。

可以用Emscripten编译如下:

emcc -mmultivalue -Xclang -target-abi -Xclang experimental-mv -Oz -s STANDALONE_WASM -s EXPORTED_FUNCTIONS="['_echo']" -Wl,--no-entry hello.world.c -o bob.wasm

标志的快速分解:

  1. -mmultivalue:告诉 Clang 启用多值支持
  2. -Xclang -target-abi:告诉 Clang 以应用程序二进制接口(interface)为目标
  3. -Xclang experimental-mv:启用更多多值内容?
  4. -Oz:告诉 Clang 生成针对大小积极优化的代码
  5. -s STANDALONE_WASM:告诉 Emscripten 不要生成它通常生成的 Javascript 胶水代码
  6. -s EXPORTED_FUNCTIONS="['_echo']":告诉 Emscripten 如果找不到对它的引用,不要优化掉 'echo' 函数。这允许您将代码从 WebAssembly 导出到 Javascript。
  7. -Wl,--no-entry:告诉 Emscripten 不要尝试在 WebAssembly 中创建默认条目
  8. hello.world.c:输入的C文件
  9. -o bob.wasm: 输出名为'bob.wasm'的文件

这导致了这段代码:

(module
(type $none_=>_i32 (func (result i32)))
(type $i32_=>_none (func (param i32)))
(type $i32_=>_i32 (func (param i32) (result i32)))
(type $i32_i32_=>_i32_i32 (func (param i32 i32) (result i32 i32)))
(memory $0 256 256)
(table $0 1 1 funcref)
(global $global$0 (mut i32) (i32.const 5243920))
(export "memory" (memory $0))
(export "echo" (func $0))
(export "__indirect_function_table" (table $0))
(export "__errno_location" (func $4))
(export "stackSave" (func $1))
(export "stackRestore" (func $2))
(export "stackAlloc" (func $3))
(func $0 (param $0 i32) (param $1 i32) (result i32 i32)
(tuple.make
(local.get $0)
(local.get $1)
)
)
(func $1 (result i32)
(global.get $global$0)
)
(func $2 (param $0 i32)
(global.set $global$0
(local.get $0)
)
)
(func $3 (param $0 i32) (result i32)
(global.set $global$0
(local.tee $0
(i32.and
(i32.sub
(global.get $global$0)
(local.get $0)
)
(i32.const -16)
)
)
)
(local.get $0)
)
(func $4 (result i32)
(i32.const 1024)
)
)

这会产生大量样板文件。重要的部分:

...
(export "echo" (func $0))
...
(func $0 (param $0 i32) (param $1 i32) (result i32 i32)
(tuple.make
(local.get $0)
(local.get $1)
)
)

C 是唯一能够生成多值代码的语言的情况可能很快就会改变。 Rust 似乎偶尔会修复一个问题。

关于c - WASM : does anyone support multi-value WASM?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72835008/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com