Clang 是否为 WebAssembly 的 memory.fill 和 memory.copy 提供内在函数?
Does Clang provide intrinsics for WebAssembly's memory.fill and memory.copy?
我正在用 C 语言开发 WebAssembly 模块,并一直在尝试使用 WebAssembly spec 和 memory.copy
中定义的指令。
我知道 Clang (v11.1.0) 已经 supports other memory-related wasm intrinsics 像 __builtin_wasm_memory_size
和 __builtin_wasm_memory_grow
,但我一直很难弄清楚它是否支持 memory.fill
和 memory.copy
.
我不太熟悉 Clang/LLVM 的内部工作原理,但在一些地方似乎暗示了对这些说明的引用 [1] [2](除非我误解了某些内容)。
我尝试使用 __builtin_memcpy
和 __builtin_memset
:
__attribute__((export_name("memcpy")))
void memcpy_test(void* mem_dst, void* mem_src) {
__builtin_memcpy(mem_dst, mem_src, 128);
}
__attribute__((export_name("memset")))
void memset_test(void* mem_src) {
__builtin_memset(mem_src, 0, 128);
}
编译,但对 __builtin_memcpy
和 __builtin_memset
的调用在程序集中被替换为导入函数:
...
(import "env" "memcpy" (func $memcpy (type $t0)))
(import "env" "memset" (func $memset (type $t0)))
(func $__wasm_call_ctors (type $t1))
(func $memcpy_test (type $t2) (param $p0 i32) (param $p1 i32)
local.get $p0
local.get $p1
i32.const 128
call $memcpy
drop)
(func $memset_test (type $t3) (param $p0 i32)
local.get $p0
i32.const 0
i32.const 128
call $memset
drop)
...
此时我有点卡住了,这些内在函数似乎还不可用,但我对此并不肯定。
如果能得到任何帮助,我将不胜感激!
[快速说明:我目前对使用 emscripten 不感兴趣,因为我试图避免它附带的大量胶水代码。]
but the calls to __builtin_memcpy
and __builtin_memset
are replaced with imported functions in the assembly:
原因是这些指令不是核心 (MVP) WebAssembly 指令集的一部分,而是稍后添加到 bulk-memory proposal。
需要明确选择后来的提案,因为存在您可能针对的给定 WebAssembly 引擎尚不支持它们的风险。可以肯定的是,您可以检查 my support table on webassembly.org.
最后,如果您已经选中此项,则可以通过 -mbulk-memory
标志在 Clang 中选择启用此功能。例如,启用此标志和优化
clang temp.c -mbulk-memory -O -c -o temp.wasm
这是我从上面的示例中得到的:
(module
(type $t0 (func (param i32 i32)))
(type $t1 (func (param i32)))
(import "env" "__linear_memory" (memory $env.__linear_memory 0))
(import "env" "__indirect_function_table" (table $env.__indirect_function_table 0 funcref))
(func $memcpy_test (type $t0) (param $p0 i32) (param $p1 i32)
(memory.copy
(local.get $p0)
(local.get $p1)
(i32.const 128)))
(func $memset_test (type $t1) (param $p0 i32)
(memory.fill
(local.get $p0)
(i32.const 0)
(i32.const 128)))
(export "memcpy" (func $memcpy_test))
(export "memset" (func $memset_test)))
这似乎是预期的结果。
我正在用 C 语言开发 WebAssembly 模块,并一直在尝试使用 WebAssembly spec 和 memory.copy
中定义的指令。
我知道 Clang (v11.1.0) 已经 supports other memory-related wasm intrinsics 像 __builtin_wasm_memory_size
和 __builtin_wasm_memory_grow
,但我一直很难弄清楚它是否支持 memory.fill
和 memory.copy
.
我不太熟悉 Clang/LLVM 的内部工作原理,但在一些地方似乎暗示了对这些说明的引用 [1] [2](除非我误解了某些内容)。
我尝试使用 __builtin_memcpy
和 __builtin_memset
:
__attribute__((export_name("memcpy")))
void memcpy_test(void* mem_dst, void* mem_src) {
__builtin_memcpy(mem_dst, mem_src, 128);
}
__attribute__((export_name("memset")))
void memset_test(void* mem_src) {
__builtin_memset(mem_src, 0, 128);
}
编译,但对 __builtin_memcpy
和 __builtin_memset
的调用在程序集中被替换为导入函数:
...
(import "env" "memcpy" (func $memcpy (type $t0)))
(import "env" "memset" (func $memset (type $t0)))
(func $__wasm_call_ctors (type $t1))
(func $memcpy_test (type $t2) (param $p0 i32) (param $p1 i32)
local.get $p0
local.get $p1
i32.const 128
call $memcpy
drop)
(func $memset_test (type $t3) (param $p0 i32)
local.get $p0
i32.const 0
i32.const 128
call $memset
drop)
...
此时我有点卡住了,这些内在函数似乎还不可用,但我对此并不肯定。
如果能得到任何帮助,我将不胜感激!
[快速说明:我目前对使用 emscripten 不感兴趣,因为我试图避免它附带的大量胶水代码。]
but the calls to
__builtin_memcpy
and__builtin_memset
are replaced with imported functions in the assembly:
原因是这些指令不是核心 (MVP) WebAssembly 指令集的一部分,而是稍后添加到 bulk-memory proposal。
需要明确选择后来的提案,因为存在您可能针对的给定 WebAssembly 引擎尚不支持它们的风险。可以肯定的是,您可以检查 my support table on webassembly.org.
最后,如果您已经选中此项,则可以通过 -mbulk-memory
标志在 Clang 中选择启用此功能。例如,启用此标志和优化
clang temp.c -mbulk-memory -O -c -o temp.wasm
这是我从上面的示例中得到的:
(module
(type $t0 (func (param i32 i32)))
(type $t1 (func (param i32)))
(import "env" "__linear_memory" (memory $env.__linear_memory 0))
(import "env" "__indirect_function_table" (table $env.__indirect_function_table 0 funcref))
(func $memcpy_test (type $t0) (param $p0 i32) (param $p1 i32)
(memory.copy
(local.get $p0)
(local.get $p1)
(i32.const 128)))
(func $memset_test (type $t1) (param $p0 i32)
(memory.fill
(local.get $p0)
(i32.const 0)
(i32.const 128)))
(export "memcpy" (func $memcpy_test))
(export "memset" (func $memset_test)))
这似乎是预期的结果。