LLVM IR -> WebAssembly。 wasm 空模块 |实例
LLVM IR -> WebAssembly. Wasm empty module | instance
我正在尝试生成 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 is not a function
怎么了?
结果如下:
console.log(JSON.stringify(results));
{"module":{},"instance":{}}
版本:
./llc --version
LLVM (http://llvm.org/):
LLVM version 10.0.0
./wasm-ld --version
LLD 10.0.0
原因是您在链接过程中没有导出任何符号。
您可能想查看 the Exports section of wasm-ld docs
了解详细信息,但这是他们对默认值的看法:
When building an executable, only the entry point (_start
) and symbols with the WASM_SYMBOL_EXPORTED
flag are exported by default.
您有两个选择:
- 将
main
重命名为 _start
- 这将确保 _start
被导出并且它的任何依赖项都从环境中正确导入,而不是完全 GCd,就像发生的事情一样现在。
- 使用
--export-all
标志调用 wasm-ld
- 这将导出目标文件中的所有符号。通常不推荐使用此选项,因为您可能会阻止有用的大小优化并暴露您不想暴露的内容,但可能适合原型制作。
- 使用
--export-dynamic
调用 wasm-ld
- 这将导出在 IR 级别标记为可见的所有符号。
- 在调用
wasm-ld
时明确列出符号,例如--export=main
.
除 (1) 之外的所有选项中需要注意的另一个警告是 main
以特殊方式处理,并且使用您当前的代码将导致两个不同的符号:
main
- 一个自动生成的函数包装器,带有两个用于调用函数的 argc
和 argv
参数。
__original_main
- 您实际定义的函数的符号。
为了确保你不 运行 进入这个,要么按照选项 1 并将 main
重命名为 _start
,这是一个特定于 Wasm 的入口点并且不接受任何参数,或将 main
函数的签名更改为正确的签名并接受 argc
和 argv
,就像在 C.
中一样
希望这一切能让你继续前进。
我正在尝试生成 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 is not a function
怎么了?
结果如下:
console.log(JSON.stringify(results));
{"module":{},"instance":{}}
版本:
./llc --version
LLVM (http://llvm.org/):
LLVM version 10.0.0
./wasm-ld --version
LLD 10.0.0
原因是您在链接过程中没有导出任何符号。
您可能想查看 the Exports section of wasm-ld docs
了解详细信息,但这是他们对默认值的看法:
When building an executable, only the entry point (
_start
) and symbols with theWASM_SYMBOL_EXPORTED
flag are exported by default.
您有两个选择:
- 将
main
重命名为_start
- 这将确保_start
被导出并且它的任何依赖项都从环境中正确导入,而不是完全 GCd,就像发生的事情一样现在。 - 使用
--export-all
标志调用wasm-ld
- 这将导出目标文件中的所有符号。通常不推荐使用此选项,因为您可能会阻止有用的大小优化并暴露您不想暴露的内容,但可能适合原型制作。 - 使用
--export-dynamic
调用wasm-ld
- 这将导出在 IR 级别标记为可见的所有符号。 - 在调用
wasm-ld
时明确列出符号,例如--export=main
.
除 (1) 之外的所有选项中需要注意的另一个警告是 main
以特殊方式处理,并且使用您当前的代码将导致两个不同的符号:
main
- 一个自动生成的函数包装器,带有两个用于调用函数的argc
和argv
参数。__original_main
- 您实际定义的函数的符号。
为了确保你不 运行 进入这个,要么按照选项 1 并将 main
重命名为 _start
,这是一个特定于 Wasm 的入口点并且不接受任何参数,或将 main
函数的签名更改为正确的签名并接受 argc
和 argv
,就像在 C.
希望这一切能让你继续前进。