-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Compiled code and handmade WASM interop #24157
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
Comments
If you want to link you wasm assmembly code into an emscripten project then the simplest way to do this would be write in using the LLVM assembly format and including it your project as a
Alternatively, if the project in question has C/C++ fallbacks for the x86 assembly then that would likely be simpler than trying to write hand written wasm assembly. |
Thanks @sbc100. Actually the code is written in WAST already which is much easier to code. I don't think writing llvm asm is an option here. About the fallbacks, yes it does have it but I wanted to optimize it with v128 SIMD ops. Checking emscripten sources there seems to be some internal logic to pass the heap to the wasm module, like emscripten/src/runtime_shared.js Line 64 in 41a730a
Disassembling the generated emscripten wasm code, it is not crystal clear how the memory is accessed, but on the .js code seems that's the way to do it. Am I on the correct path? |
Are you sure? Can you share the wast file so we can check it out together? I would hope it would be relatively easy to convert from one to the other is most cases.
Another alternative then would be write using the wasm simd C intrinsics, but it sounds like you already write the raw wast so that I likely not attractive to you either.
It sounds like you are proposing some kind of dynamic linking of two wasm modules, one produced by you direclty and one produced by emscripten. While this may be feasible its certainly not easy and not the simplest way to solve this kind of problem. By far the simplest way to solve this (which will also lead to better performance) is to build your code as an object file and have emscripten link it into your program statically (i.e. at static link time). However, to produce an object file you really want to write your assembly in the llvm format. As well as being simple this will likely be the most performant option since it will allow wasm-opt to optimize the whole program as one. |
Sure, it is not ready yet. Once it is, I will
Isn't an option either. To give you more context, I'm porting https://gitlab.freedesktop.org/gstreamer/orc/ to WASM by providing a WASM target. Orc is basically a loop optimizer using different SIMD instructions (mmx, sse, avx, avx512, neon, etc) and it does so by either generating assembly code to link statically with, or generating the actual machine code for doing JIT execution. Currently, I'm on the assembly approach, which is easier to code, doing WAT. Later, once it works, I'll need to do the actual WASM bytecode. The two approaches provide different challenges. I'm currently trying to understand emscripten/llvm internals to be able to glue Orc there. At the end, on the static approach, I'll need to link to my new WASM (by doing a wat2wasm) and provide a way to pass C variables to it. Maybe from your comments, It will be more feasible to do the JIT directly and provide the glue myself, still the same questions remain as I don't know how to access the heap/pointers and provide them to the WASM module.
Yes, it seems so.
I see, I understand now. I thought that the dynamic linking was against the wasm itself, not the intermediate object. |
I'm afraid I don't quite understand the question. Can you elaborate? |
I apologize, yes. You were referring to the "llvm asm" option as the easiest one, but given that it is not possible, I'm wondering what more complex ways to achieve this are, if any. |
The more complex way that it sounds like you are proposing would be to somehow to try to dynamically link wasm module that was not build by emscripten with and emscripten-built module. To do this I think you have two main choices:
|
I see, thanks for the information. I'll check https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md as it seems it describes the current ABI to load wasm modules. Thanks! |
Answering myself after some findings
Check https://emscripten.org/docs/compiling/Dynamic-Linking.html#load-time-dynamic-linking simply do a
As long as it is defined in the side module (library) it should be found I'm having issues with the relocatable feature, doing a wat2wasm with dynamic linking annotations as explained here https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md and calling
It seems wat2wasm is not honoring the annotation. Maybe a bug?
Compiling the main module with the side module gives me this output
If I do an
Which is different to what wat2wasm is doing. I'm a bit confused, maybe some version compatibility problem? Compiling the new .wasm side module (the one generated with emcc itself) does work. |
I don't know of any way to build and emscripten an dynamic library other than using emscirpten itself (or perhaps using wasm-ld directly). Even if you did find a way to make a dynamic library from your wat file remember that dynamic linking comes at a cost, especially with wasm/emscripten. There is code size cost and a runtime cost when compared to static linking. Unless you really really need to the code to be loaded dynamically I would not recommend this approach. |
And is it possible to feed emcc with an object file (.wasm file) that is generated from
which seems to be exported from the custom "linking" section Seems that my situation is similar to WebAssembly/wabt#1658 |
It should work, but it would not be surprising to me if |
To be honest, I don't know where to start. Is it some emscripten wrong behavior with the "linking" custom section, or wat2wasm not following https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md ... |
Can you share the object produced by As we go down the rabbit hole though I would once again advice you to write your code in llvm assembly format to avoid this issue. |
In addition to being easily convertible to a valid object file, the LLVM assembly format also has some added advantages over wat such as support the C pre-processor and supporting symbolic names for your static data. |
I think I've found the issue but can't explain if it is a correct behavior or not. Basically, For a code like
wat2wasm -r generates the following "linking" table
But for the following code (without export)
The generated object file has
The difference is on the binding and vis by just using the export statement. With the second form, it links correctly with Emscripten.
Yes, and I appreciate your patience and help with this topic. As my particular requires building a "compiler" myself, I'd like to understand further the alternatives and how things work |
Hello all,
After successfully compiling a project, I'd like to optimize it. The program has some x86 asm code which I have ported to wasm by writing the corresponding wast file. So far, so good.
My question is how to interop the compiled project with the handmade .wasm file:
void func(uint8* src, uint*8 dst, int n)
On the .wasm side, src and dst arei32
offsets of the imported memory?(import 'foo' 'bar' (memory 1 SIZE shared))
? What are 'foo and 'bar' here to properly reference the heap?Thanks for helping me understand how emscripten/llvm work at this level.
The text was updated successfully, but these errors were encountered: