WebAssembly progress

When I downloaded WebAssembly/wabt from GitHub, it built right away using CMake, CMake-GUI, GCC8, and GNU Make, it built right away even in parallel build. There were only a few warnings, mostly related to a missing assert.h file. When I later tried running the 190 unit tests for WABT, they all ran successfully.

Since there is no WASM backend for GCC, I tried repeating the above steps using LLVM-12, LLVM-12libs, Clang-12 and Ninja. I specified clang and clang++ in CMake-GUI as the tools to build WABT but what were warnings about assert.h are outright errors on Clang++.

As a fallback plan I am looking into cross compiling from Clang++ under Linux. Now I only need the headers from Haiku to generate the WASM file.

Stay tuned…

7 Likes

Update: The planned build process for the test.

  1. Use Clang++ on the dev box to convert each source file that generates a bitcode as an object file.

  2. Use llvm-link to merge the object files into one bitcode file.

  3. Pipe the output of llvm-link into llc to convert the bitcode file into WASM32 format.

  4. Send the .WASM file to the user machine.

  5. Use wasm2c to convert the WASM file back to C

  6. Use either Clang or GCC to convert the resultant C file into an object file.

  7. Use Clang++, G++ or ld directly to do the final linkage stage with all the necessary linker files.

  8. Run the executable.

Notes:

The final compile stage on the user box must be in C. The final linkage stage must be for C++. Otherwise the name mangling will get done twice so the linkage will not be able to succeed.

Since the linker libraries are architecture-specific, they must be linked on the user box, not the developer box. That will keep the package sizes smaller but the package manager will have to have some sort of re-link trigger based on either Make or Ninja.

4 Likes

Can you show a trivial example of this working? Can you, for example, create an app that links libbe.so and displays a simple BWindow that has a clickable button that updates a label? Or maybe (simpler) an app that displays “Hello, world” in a BWindow? I think, this is key to adoption. Without being able to link to the BeOS C++ API, it is not really going to be very useful.

Another thought - if you are proposing this as a way to move packaging to AOT on device, how will this handle third party libs? Will this AOT those? Won’t that add in additional issues and performance concerns. Won’t that also make supporting the package on each platform almost impossible, because the developer will not be able to easily debug issues? This sounds like a utopia, but I can’t see how you will address all of the shortfallings.

Can you use llvm bitcode to do this and skip WASM altogether, or does this cause problems with linking (or have some other problem)?

Looking at it, @SamuraiCrow was right in saying the bitcode is architecture specific. So a 64bit target would look different to a 32bit one. But, here’s the thing - having one package for 64bit and one for 32bit seems like a better trade off than making things overengineered. I still don’t see the benefit of using WebAssembly for this. But, I’d like to see the POC UI test apps that work on multiple architectures and processors and how debugging issues goes with those exes, before I make a final conclusion.

Sounds about as easy as sending the source code in a zip file.

Source code tends to produce errors on compiler/headers update. You can see that by trying to compile original Be sample code. Binaries can be more stable.

2 Likes

That’s true if the platform doesn’t move. But the bytecode might still be compromised over time. Also, we are talking about shipping for a release, not taking source and making it work on any version.

The Be example code suffers from mainly using BeIDE projects (as well as targeted a specific version of gcc or mwcc), and as BeIDE is not ported to Haiku, a lot of it causes issues unless you are reasonably up to speed with what has changed in the last 20+ years.

The are some headers incompatibilities, adding additional headers is often needed when compiling BeOS code on Haiku.

1 Like

I think that is more Haiku not being a 100% drop in replacement.

That’s the plan. I started this thread just before it was time to sleep. Hopefully, I’ll have time today to finish the plan.

Technically the compilation will be static from source to bytecode and from bytecode to binary. No need to pause at runtime for AOT compilation.

Third-party libs will likely be separate packages, compiled separately, then linked. When dependencies require it the package will need to relink.

As far as support is concerned, only linker errors are difficult. As long as linker errors are resolved for each dependency, there is no problem.

One of the biggest criticisms of bitccode is that it is extremely hard for a developer to take a crash dump and marry up a crash to their original source. Apple uses Test Flight to bridge the gap, but it is still not without flaws. How do you envision that would work for Haiku? Especially if I create a package from a 32bit Haiku app I have developed and some one using ARM64 or RISC-V reports a crash? I think making it a requirement to be massively cross platform is all well and good when it “just works”, but having come from the era when IA32 devs would recompile their code for PowerPC and it would just fail horribly, because they didn’t respect endianess or something like that, and when we reported the issue they would effectively “de-list” PowerPC from future development… yeah, that is what I see this bringing at the moment. It needs to be seamless and it needs to be easy to debug issues on different architectures.

I hope you appreciate me challenging you. I feel like asking the hard questions now will get you to a better place in the future.

More or less, but the macro-optimization is done at the developer’s machine, thus speeding up the installation process. Besides that, it has most of the same advantages as obfuscated source as a closed-source distribution medium.

You can compile libroot.so stub code to get IL library for linking. You can also use Python utility in the same directory to get stubs for other libraries.

1 Like

Endianness will require a new fork of the WebAssembly bytecode. I asked on somebody else’s issue on GitHub if support would be added to bi-endian architectures running in big-endian mode. One of the lead developers adamantly refused. Also, big-endian bytecodes will need a separate set of packages because there is no way to bypass endian-specific optimizations in LLVM.

As for debugging, WebAssembly offers the option of removing debug information from the bytecode in the wasm2c converter. This conversely suggests that debug builds of the executable are possible without re-downloading the packages. Unfortunately, the linker libs will also need debug builds to trace things down completely.

How future-proof are the stub codes when future releases of Haiku come out with changes?

New Haiku versions should only add new symbols, not remove. Old stubs should work on new Haiku version.

1 Like

That’s kind of ignoring the issue. If I develop an app and have access to a symbolic debugger, if the app crashes and there is a stack trace, I can use that to work out where and why the app crashed. That is pretty essential. If you lose that ability, you are shooting in the dark. Sure, trivial issues are easy, but not multithreaded timing based issues or things that require state changes or other interaction to recreate. I guess, if you cross compile the app, you have the possibility to cache the symbols you generate, but if everyone is a potential compile target, and everyone has a completely random Haiku build (as happens now with Beta and Nightlies) how do you imagine that working?

I do this for a living. I write apps for mobile platforms and deal with about 4 or 5 different target architectures. Not having a way to narrow down where an error is means a LOT more effort on the devs side.

Also - you glossed over the libs - so these are all coming from packages that were compiled to byte code too? So if the issue is 3 layers deep, how do we debug that?

I still believe having packages and symbols for each platform is better. The only use case for this is making old apps that are no longer available run (like running PowerPC BeOS apps on Haiku or maybe 32bit apps on 64bit or something like that.) and then you are looking at a completely different solution, because you’d need to transpile existing exe’s to new native code (or byte code?)

2 Likes

Maybe it is possible to use IL <-> native code address translation table? Or convert machine code <-> source code table. Oberon use similar technology.

2 Likes

As far as I know, address translation tables are the only way to do it.