WebAssembly progress

If you recompile it, then sure.

Maybe PowerPC compiler can be opened?

I spoke to someone at Metrowerks a long time ago (I forget his name, but he was the developer advocate and he was quite infamous int he Metrowerks community.) He told me he would look in to it. I never heard much back.

AFAIK, Be Inc had the IDE source, but the compiler was binary only and came from Metrowerks. The same compiler was used to compile PEF on all platforms (Classic MacOS, MacOS X, Windows and BeOS), so there are later versions of it kicking around. I guess any of the versions being opensourced would be handy.

I tried to find out who owns the Metrowerks IP, but it is unclear.

Afair MW was bought by Freescale, and its compiler business was bought by NXP. But i can be wrong.

They have absolutely no email address on their webpage (because fck do not disturb us mortal human), so i had to make extra miles.

You can try to contact them, maybe you will have more luck.

Re:Double Mangle condition

Looking at the source, wasm2c has a mechanism to prevent the double mangle so I may be able to simplify the test script.

UPDATE:

The source code to Haiku is full of preprocessor magic. Of course this defines the architecture long before the bytecode can be generated so every instance of

#ifdef __IM_A_PREPROCESSOR_FLAG
  do this;
#endif

needs to be replaced with

if (__IM_A_BOOLEAN_CONST) {
  do this;
}

so that

#define __IM_A_PREPROCESSOR_FLAG 1

can be repaced with

extern const bool __IM_A_BOOLEAN_CONST;

thus allowing the value of __IM_A_BOOLEAN_CONST to be linked in on the destination machine and the if statement to be constant folded by the link-time optimization pass.

It’ll be monotonous work but more importantly, will touch almost every part of the source code of the operating system. Expensive as a time sink even though the work is easy. I’m guessing that this may not make it to Beta 4, to say the least. Even worse, the GCC2 ABI requirement won’t be met without an alternative compiler that supports link-time optimization.

I will welcome any critique of the situation but the amount of work that will be needed to merge all the packages into one bytecode may have to wait until the “glass elevator” arrives on the first floor. (Meaning that it may have to wait until after release 1.)

Edit: If everybody was willing to pitch in and replace all the preprocessor macros in the config directory with constants, we collectively could make it beta 4!

6 Likes

CodeWarrior (the MacOS equivalent to BeIDE) is now owned by NXP but the current versions seem to be based on the Eclipse IDE and the GCC compiler: CodeWarrior® Embedded Software Development Tools | NXP Semiconductors

I don’t know if they still have backup of the older versions…

We can send them the x86 one.

On to plan B. I’m going to try to update the ApplicationKit headers so they don’t need to include the config.h macros as preprocessor definitions. Once I see what breaks I’ll report back.

Update

The extent of what I can accomplish for architecture neutrality using static compilation is limited by address bit width and endianness. This means 68k and Sparc32 can share a bytecode, as can PPC32 and ARMEB, but not x86 because it is little-endian. Little-endian 32-bit processors like ARM and x86 will be able to share a different bytecode. Futhermore, AMD64 and RISC-V64 will be able to share a bytecode because they are both little-endian and 64-bit. Finally, the fourth bytecode will be big-endian 64-bit.

Running a smaller address width or endian-swapped architecture (or both) will only be possible using a JIT. The speed penalty can be minimized by using a fast JIT like Cranelift but it will still have a speed penalty due to the compilations being concurrent or at load-time using AOT compilation.

Future Opportunities

I intend to fork bytecodes from the WebAssembly standard to support features that it presently does not support. 64-bit WebAssembly is going to be supported soon by the W3C so no need to fork for that. Two other features not supported or planned to be are big-endian platform support and macro injection.

Big-endian support will only require adding multi-byte loads and stores. I would not recommend using the same bytecode values for a big-endian load and store in case bi-endianness is supported as PPC and AArch64 both do endian swapping with a fair degree of transparency.

The final nail in fixed architecture is code injection. Normally associated with JIT compilation, code injection allows library code to contain macros in such a way that code from a performance limited libraries such as graphics drivers can actually put driver code in the executable of the application. This removes calling overhead from what might be implemented as a subroutine on one architecture, but a few opcodes on another. While often performed in JIT and AOT compilation strategies, it can also be implemented in static code by invoking a dependency check at startup.

More to come…

1 Like

More Updating

I’ve gotten Clang to compile my graphical “Hello world” class executable from Clang after having modelled it after the beginning example from the beginners’ tutorial. The command lines to build are much different. The significance of this is that GCC doesn’t have a WebAssembly backend to generate bytecode with.

The GCC build line is as follows:

g++ App.cpp -Os -lbe

The Clang 12 build line is this:

clang++ App.cpp -I/boot/system/develop/sources/haiku/headers/build/gcc-2.95.3 -fPIC -Os -lbe

The extra included directory contains the headers to the LibStdC++ runtimes. Apparently activating Position Independent Code is not optional either but must be specified. The resultant code is a couple hundred bytes smaller with Clang 12 than with GCC8, but that’s not a fair comparison considering that Clang 12 is on par with GCC 10 or 11 as far as generations go.

Here’s the C++ source listing of the program:

#include "App.h"

#include <StringView.h>
#include <Window.h>

App::App(void)
	:	BApplication("application/x-vnd.dw-TestApp")
{
	BRect frame(100,100,500,400);
	BWindow *myWindow = new BWindow(frame, "My First App", B_TITLED_WINDOW,
		B_QUIT_ON_WINDOW_CLOSE);
	frame.Set(10,10,11,11);
	BStringView *label = new BStringView(frame, "myLabel", "Haiku Rocks!");
	label->ResizeToPreferred();
	myWindow->AddChild(label);
	myWindow->Show();
}


int
main(void)
{
	App *app = new App();
	app->Run();
	delete app;
	return 0;
}

The App.h file is this:

#define APP_H

#include <Application.h>

class App : public BApplication
{
public:
	App(void);
};

#endif

Now to get Clang to generate bytecode like I’ve already done on Linux.

Stay tuned…

2 Likes

But then

Now which ABI is targeted here? GCC2 or GCC4? If GCC4 then why the GCC2 include folder? If GCC2 then why “couple hundred bytes smaller with Clang 12 than with GCC8” ?

And if GCC2, let me ask: wouldn’t it easier to support only one ABI? One don’t really need to compile the whole os into webassembly, and most of the user-programs can be built with GCC4 ABI, then why to mess with the GCC2 ABI at all?

(Maybe I overlooked something here.)

And that include path doesn’t look to be shipped in default to me.

Tell me where the ABI v4 headers are to direct toward. I’ll try it. When I did a search for “new.h” that was the only one that showed up.

GCC2 is not compatible with Clang. GCC 4+ headers should be used.

1 Like

-I/boot/system/develop/tools/x86/lib/gcc/i586-pc-haiku/8.3.0/include/c++ -I/boot/system/develop/tools/x86/lib/gcc/i586-pc-haiku/8.3.0/include/c++/i586-pc-haiku

/x86 need to be removed for 64 bit system.

3 Likes

I agree. Where is the ABI v4 header for new.h? This was just the first attempt to make a graphical application work on Clang 12.

Edit: Thanks for the correct path.

“new” don’t need “.h” at end. “new.h” is obsolete GCC 2 header, it should be not used.

3 Likes

With the correct headers, the executable came out identical to the one with the wrong headers, but at least I’ll be future-proof. Now for the bytecode attempt.

I tried using the Python utility to create stubs for all shared objects but it wasn’t robust enough. I’ll have to rework the algorithm in my own stubify.py script.

1 Like

Toolchain

I’m now starting to look into a WebAssembly based toolchain for Haiku.

Binaryen

Binaryen is cross-architecture but deviates from WebAssermbly on several points: The structure of Binaryen’s bytecode is tree-based rather than a stack machine. Due to stack machines being more easily considered position-independent than a tree definition, implementing macros of all system-specific features in a device driver can be encapsulated into a bytecode driver template whose binary code can be rebuilt by an install trigger in the package manager every time the macro definitions change. This could also be used to make applications calling these drivers to incorporate driver code in performance intensive loops by macro-inlining and registering a trigger to also rebuild any time the macro package needs updating. Binaryen translates to raw WebAssembly in the end anyway.

Haiku-specific Headers

This will probably be the type of toolchain I end up using. Packager friendly by being a stable ABI unlike other operating systems that shall remain unnamed except that the first inital of the kernel is the first letter of Linux. (Yes Linux. The famous unstable ABI that broke the closed-source nVidia drivers on my main development machine during a routine kernel update. GRRRRRR! :angry: )

If we can pioneer enough into a macro-intensive device driver architecture, maybe we can push our changes upstream to the main WebAssembly standard at some point. I’m fairly sure the graphics card makers will appreciate the flexibility.

8 Likes