I'm working on developing a WebAssembly module in C and have been attempting to utilize the memory.fill
and memory.copy
instructions defined in the WebAssembly spec.
I know that Clang (v11.1.0) already supports other memory-related wasm intrinsics like __builtin_wasm_memory_size
and __builtin_wasm_memory_grow
, but I've been having a hard time working out if it supports intrinsics for memory.fill
and memory.copy
.
I'm not intimately familiar with the inner workings of Clang/LLVM but references to these instructions seem to be hinted at in a few places [1] [2] (unless I'm misinterpreting something).
I attempted to use __builtin_memcpy
and __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);
}
which piles, but the calls to __builtin_memcpy
and __builtin_memset
are replaced with imported functions in the assembly:
...
(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)
...
At this point I'm a little stuck, it seems like these intrinsics aren’t available yet, but I’m not positive of that.
I'd really appreciate any help I could get!
[Quick note: I'm not currently interested in using emscripten as I'm trying to avoid the large amount of glue code it es with.]
I'm working on developing a WebAssembly module in C and have been attempting to utilize the memory.fill
and memory.copy
instructions defined in the WebAssembly spec.
I know that Clang (v11.1.0) already supports other memory-related wasm intrinsics like __builtin_wasm_memory_size
and __builtin_wasm_memory_grow
, but I've been having a hard time working out if it supports intrinsics for memory.fill
and memory.copy
.
I'm not intimately familiar with the inner workings of Clang/LLVM but references to these instructions seem to be hinted at in a few places [1] [2] (unless I'm misinterpreting something).
I attempted to use __builtin_memcpy
and __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);
}
which piles, but the calls to __builtin_memcpy
and __builtin_memset
are replaced with imported functions in the assembly:
...
(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)
...
At this point I'm a little stuck, it seems like these intrinsics aren’t available yet, but I’m not positive of that.
I'd really appreciate any help I could get!
[Quick note: I'm not currently interested in using emscripten as I'm trying to avoid the large amount of glue code it es with.]
Share Improve this question asked Apr 13, 2021 at 3:05 mecimeci 2092 silver badges7 bronze badges1 Answer
Reset to default 9but the calls to
__builtin_memcpy
and__builtin_memset
are replaced with imported functions in the assembly:
The reason is that those instructions are not part of the core (MVP) WebAssembly instruction set, and were added later in the bulk-memory proposal.
Those later proposals need to be opted in explicitly, since there is a risk that a given WebAssembly engine you might be targeting is not supporting them yet. To be sure, you can check my support table on webassembly.
Finally, if you already checked this, you can opt in to this feature in Clang via -mbulk-memory
flag. For example, with this flag and optimisations enabled
clang temp.c -mbulk-memory -O -c -o temp.wasm
this is what I get for your sample above:
(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)))
which seems to be the expected result.