-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Toolchain support for multiple memories #45
Comments
Support was recently added to Binaryen, but hasn't been added to LLVM yet. |
I'm curious if there is any example of "high level language being compiled to WebAssembly with multi-memory support"? |
(sorry, misread the above comment)
Is anybody working on LLVM support? LLVM IR has address spaces, that can be used to represent multiple memories. |
No, nobody is currently working on multimemory in LLVM, although Igalia's work adding support for tables is very similar to what would need to happen to support multiple memories as well. |
I don't know of any either, probably because of the current lack of implementations. Hopefully we will soon break the chicken-and-egg problem. Did you have a particular thing you wanted to learn from an example? |
I have come up an technique leveraging the multi-memory support of the WebAssembly and now need some test cases. And such high-level coding method is what I wanted to learn. |
What does this work look like? LLVM has |
One of the more compelling use cases I've stumbled on is virtualizing interfaces that use memory. E.g. implementing a Wasm module that has an imported memory from the "user", which it may read and/or write, and then a private memory that is used to store additional internal state and possibly communicate with other modules. AFAICT It would be possible to write such a module in C with address space annotations. |
yes, that’s what I want to learn.
|
With Clang and C/C++ it is Example: int incr_from_mem3(__attribute__((address_space(3))) int * ptr) {
return (*ptr) + 1;
} (Edit) Even though this would lead to |
I see, thanks for explanation. |
Since address spaces need to be statically allocated by the LLVM backend for WebAssembly, it would not be scalable to try to use them to support multiple memories directly. Tables are modeled in LLVM IR as global arrays in a special address space so that an arbitrary number of them may be created. The Wasm object file format used with LLVM was also extended with additional relocation types for tables. The same patterns would work well for modeling multi-memory as well. |
I actually find that take somewhat surprising; given that address spaces also need to be statically allocated in the wasm module, requiring the same static allocation at the LLVM IR level seems like it should scale exactly as well in LLVM as it would in wasm itself? Tables are different in the sense that there's not really any obvious analog in the IR already (not just for tables, but also for the references they contain). |
I am going to second what @dschuff said, aren't memories statically declared, why would they need to get the same dynamic treatments tables get? |
By "statically allocated in the backend," I mean statically allocated when LLVM is compiled, not when the user program is compiled. So if you had a 1:1 mapping between address spaces and memories, then when you compile LLVM, you would have to determine what the maximum number of memories an LLVM IR module could reference at that point. In contrast, the scheme used for tables allows user programs to use an arbitrary number of tables. |
Is this discussion is just about the LLVM internal representation? At the C or C++ level these would still be address space annotations on pointer types? |
There is a hard limit on number of memories, memory index is one byte, I think. |
At the C or C++ level these would most likely be new annotations like
No, just like all other indices in Wasm, memory indices are LEB128 values. |
Oh, so you mean they would be globally-declared (non-address taken) arrays into which the program would index with integers? |
Yes, exactly. |
"not address-taken" sounds like a very severe restriction for memory |
It's definitely a severe restriction compared to what you can do with other constructs in C/C++, but that's ok because a program would only need to use this feature to do something very specific to WebAssembly, and in that case having the source language construct match the underlying construct as closely as possible is a good thing. |
where did your assumption "a program would only need to use this feature to do something very specific to WebAssembly" come from? |
But that’s not something you can do in portable C/C++, so it only makes sense to expect to be able to do that if you’re targeting WebAssembly (or some other specific platform that could provide similar functionality). |
right. |
To turn this around, what would it even mean to take the address of something that lowers to a WebAssembly memory? How do you envision the address would be represented and how do you envision it could be used?
In this case you can just compile the library normally to use a single memory, then use something like wasm-merge to merge it into the rest of the application, which would have a different memory. If you need to copy data from one memory to the other on the boundary, you could use the |
i don't pretend to have a clear vision! although i'm not an llvm expert, address spaces seems like the closest construct llvm currently has.
maybe. |
👋 Is the work on supporting the toolchain still in progress? It appears to be non-functional at the moment. https://github.com/search?q=repo%3Allvm%2Fllvm-project+multimemory&type=code |
I don't think anyone is working on it right now. |
We have a requirement for an embedded product that needs support for multiple memories. This product has two types of memory: a general memory and an on-chip memory. The code, which will be compiled into WASM from C, should be able to access variables in both types of memories. __attribute__((address_space(4))) int blank_array[1024];
void fill_array(__attribute__((address_space(4))) int* x, int n, int v) {
for(int i = 0; i < n; i++) {
x[i] = v;
}
}
If go deeper, variables in different memories __attribute__((address_space(4))) f32_t gvInA[LENGTH];
__attribute__((address_space(4))) f32_t gvInB[LENGTH];
f32_t gvInC[LENGTH];
f32_t gvInD[LENGTH];
gvInA[0] = 0.3;
gvInB[0] = 0.4;
gvInC[1] = 0.1;
gvInD[2] = 0.2; will be marked with
Eventually, variant sections. .globl gvInA
.size gvInA, 8192
.type gvInA,@object
.globl gvInB
.size gvInB, 8192
.type gvInB,@object
.size .Lstr, 11
.type .Lstr,@object
.size .L.str, 19
.type .L.str,@object
.size .L.str.1, 21
.type .L.str.1,@object
.globl gvInC
.size gvInC, 8192
.type gvInC,@object
.globl gvInD
.size gvInD, 8192
.type gvInD,@object
.section .vecmem_data,"aw",@progbits
.align 4
gvInA: ; @0x0
.skip 8192
.align 4
gvInB: ; @0x2000
.skip 8192
.section .rodata_in_data,"aw",@progbits
.align 4
.Lstr: ; @0x0
.asciz "Test ended"
.align 4
.L.str: ; @0xc
.asciz "Sample Length: %d\n"
.align 4
.L.str.1: ; @0x20
.asciz "Measured SNR: %f dB\n"
.section .bss,"aw",@nobits
.align 4
gvInC: ; @0x0
.skip 8192
.align 4
gvInD: ; @0x2000
.skip 8192
mov_s %r19,gvInA ; @0x1c6
asl %r16,%r16,10 ; @0x1cc
mov_s %r15,%r19 ; @0x1d0
mov_s %r0,gvInD+8 ; @0x1d2
mov_s %r1,gvInC+4 ; @0x1d8
mov %r13,1024 ; @0x1de
mov_s %r17,0x3e100000@u32 ; @0x1e2
st 0x3e99999a@u32,[%r19,0] ; @0x1e8
st 0x3e4ccccd@u32,[%r0,0] ; @0x1f0
st 0x3dcccccd@u32,[%r1,0] ; @0x1f8 |
I thought about this a little more.
|
Does anyone know the current status of multi-memory support in toolchains, e.g. LLVM? After a cursory search of LLVM commits, I didn't turn up anything.
The text was updated successfully, but these errors were encountered: