llvm - LLVM IR -> WebAssembly。Wasm 空模块 | 实例
问题描述
我正在尝试生成 WebBrowser (Firefox) 可以正确理解的有效 wasm 文件,但我不确定我在这里做错了什么
这是Main.ll
文件
define i32 @main() {
ret i32 42
}
然后我使用 llc (Linux):
./llc -mtriple=wasm32-unknown-unknown -O3 -filetype=obj main.ll -o main.o
然后我使用 wasm-ld (Linux):
./wasm-ld main.o -o main.wasm --no-entry -allow-undefined
然后我复制main.wasm
到 Windows,然后打开这个本地文件页面:
|-- fille.html
|-- main.wasm
<div id="test">
</div>
<style>
#test
{
border: 3px solid red;
width: 100%;
height: 100%;
}
</style>
<script>
fetch("main.wasm")
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, {}))
.then(results => {
window.alert(results.instance.exports.main());
});
</script>
但
TypeError:results.instance.exports.main 不是函数
怎么了?
结果如下:
console.log(JSON.stringify(results));
{"module":{},"instance":{}}
版本:
./llc --版本
LLVM (http://llvm.org/):
LLVM version 10.0.0
./wasm-ld --version
LLD 10.0.0
解决方案
原因是您在链接期间没有导出任何符号。
您可能想查看the Exports section of wasm-ld docs
详细信息,但这是他们对默认值的看法:
构建可执行文件时,默认情况下仅导出入口点 (
_start
) 和带有标志的符号。WASM_SYMBOL_EXPORTED
你有几个选择:
- 重命名
main
为_start
- 这将确保_start
已导出并且它的任何依赖项都正确地从环境中导入,而不是完全从 GCd 中导入,就像现在发生的那样。 wasm-ld
使用标志调用--export-all
- 这将导出目标文件中的所有符号。通常不建议使用此选项,因为您可能会阻止有用的尺寸优化并暴露您不想暴露的东西,但对于原型设计可能很好。- 调用- 这将导出在 IR 级别标记为可见的所有符号
wasm-ld
。--export-dynamic
wasm-ld
使用 eg调用时显式列出符号--export=main
。
除了 (1) 之外的所有选项中要注意的另一个警告main
是以特殊方式处理的,并且使用您当前的代码,它将导致两个不同的符号:
main
- 一个自动生成的函数包装器,带有两个参数,用于argc
调用argv
你的函数。__original_main
- 您实际定义的函数的符号。
为确保您不会遇到这种情况,请遵循选项 1 并将其重命名main
为_start
特定于 Wasm 的入口点且不接受任何参数,或者将main
函数的签名更改为正确的签名并接受两者argc
并argv
喜欢C。
希望这一切都能让你继续前进。
推荐阅读
- powershell - 仅对机械硬盘进行分区和格式化
- php - 填充对象数组而不每次都创建新对象
- javascript - 有没有办法强制特定的 dataTable 列在移动设备上显示?
- android - FCM 未发送通知
- python - 使用 exchangelib 更改发件人帐户
- pandas - 我想知道如何从两个不同的列中获取具有 2 个特定值的行
- mongodb - 猫鼬增量动态对象
- c# - 用于创建新 blob 容器的 Powershell 脚本不适用于 Azure 存储模拟器
- metadata - 为 MDSPathFilter 选择文件时发生冲突
- c# - 超时无法从传输连接读取数据