【发布时间】:2020-02-16 21:39:42
【问题描述】:
不明白如何正确使用 call_indirect。
在网上搜索,我发现要让函数指针在 web 汇编中工作并不容易。函数的地址存储在 Table 中,基本上是 i32 标识符。 好吧..让我们编码!
在中间表示中定义语义(call-indirect.ll 文件):
define i32 @call_indirect_method(i32 (i32, i32)* %callee, i32 %arg, i32 %arg2) {
%t = call i32 %callee(i32 %arg, i32 %arg2)
ret i32 %t
}
编写程序(program.c文件):
#include <emscripten.h>
int EMSCRIPTEN_KEEPALIVE call_indirect_method();
int EMSCRIPTEN_KEEPALIVE sum(int a, int b)
{
return (a + b);
}
int EMSCRIPTEN_KEEPALIVE calc(int a, int b)
{
return call_indirect_method();
}
一堆js(index.js):
const fs = require("fs");
const raw_source = new Uint8Array(fs.readFileSync(`module.wasm`));
const wasm_module = new WebAssembly.Module(raw_source);
var table = new WebAssembly.Table({initial: 1, element: "anyfunc"});
var memory = new WebAssembly.Memory({initial: 1});
const _exp = new WebAssembly.Instance(wasm_module, {
"env": {
__memory_base: 0,
__table_base: 0,
memoryBase: 0,
tableBase: 0,
memory: memory,
table: table,
nullFunc_X: () => console.info("nullFunc_X()"),
jsCall_X: () => console.info("jsCall_X()"),
abort: err => {
throw new Error('abort ' + err);
},
abortOnCannotGrowMemory: err => {
throw new Error('abortOnCannotGrowMemory ' + err);
},
abortStackOverflow: err => {
throw new Error('abortStackOverflow ' + err); // Wellcome here if compile with -O0 level.
}
}
}).exports;
table.set(0, _exp._sum);
console.log(_exp._calc(1, 2)); // expect to be 3, got 0 instead
我构建 .wasm 的方式:
emcc -O1 -s WASM=1 -s SIDE_MODULE=1 -s ONLY_MY_CODE=1 -s FILESYSTEM=0 -s TOTAL_MEMORY=65536 -s TOTAL_STACK=1024 -s ENVIRONMENT='web' -s ALLOW_MEMORY_GROWTH=0 -s NO_EXIT_RUNTIME=1 -s STACK_OVERFLOW_CHECK=0 call-indirect.ll program.c -o module.wasm
最后,调用:
node index.js
当一切都“组装好”时 - 我在控制台中有 0。但期待 3。
另外(一件小事,但是..)如果您尝试构建没有优化的代码 -O0 它将由于堆栈溢出错误而中止。不知道为什么。任何想法? (是的,我已经在尝试增加内存了)。
那么,也许有人知道我的情况有什么问题?
【问题讨论】:
-
不确定这应该如何工作,program.c 中对
call_indirect_method的调用没有传递 call-indirect.il 中预期的任何参数。我很惊讶这甚至会生成有效的 Wasm 并且不会陷阱。 -
知道如何正确处理 call_indirect 指令吗?或者,也许我误解了这个概念,并且有更简单的方法可以让函数指针工作? :)
标签: javascript c function-pointers webassembly