Running WebAssembly on ARM

Syrus Akbary
Wasmer
Published in
4 min readNov 22, 2019

--

We started Wasmer with the mission of making programs universally available by leveraging on WebAssembly (Wasm). By enabling the use cases of Wasm outside of the browser we aim to unleash its full power: becoming the lingua franca for running software safely and at native speeds.

Linux and macOS were the first platforms we started supporting for executing Wasm server-side (since Unix support was the easiest to start with), to then add support for Windows just a few months after the initial launch.

Similarly, we focused first on running Wasmer in x86_64 chipset machines, as it was the most popular chipset among developers (desktop computers, laptops, servers).

One of the main powers of WebAssembly is not just to run logic safely and natively in any platform but also in any chipset

Today we are very happy to announce Wasmer 0.11.0 with full support for running Wasm modules on ARM chipsets (Aarch64) 🎉

Here’s why we believe this is going to be game-changing for the industry and what we did to make it possible …including a cool demo of Wasmer running in a Raspberry Pi!

Why Running WebAssembly on ARM is important?

ARM is the chipset that probably runs in your phone. It’s optimized for low power consumption among other great properties.

As such, ARM is making a come-back for computing in server-side (low power consumption, cheaper boards) and becoming a key element for Edge-Computing. To date, ARM chipsets are present almost everywhere:

  • Phones: ARM is the typical chip that runs in your phone (95% of Android devices and all iPhones).
  • Internet of Things (IoT): ARM is a strong contender for mid-to-high-end IoT devices.

What we did to support ARM?

Wasmer ships with three different backends: Singlepass, Clif and LLVM.

Singlepass requires much less memory and resources than full IR compilers (Clif or LLVM) which are key properties when running Wasm on such devices.
The decision was clear: Singlepass will be the first backend supporting ARM compilation.

Here’s what we did to make it possible:

1. Make it compile!

To compile Wasmer in ARM, we rented a bare metal ARM server in Packet. This enabled us to fix all Rust compilation errors in the ARM server easily.

Most of the compilation issues were related to assumptions we made about pointer sizes. While pointer sizes are 8 bits in x86_64 chipsets, they can actually differ for other architectures.

2. ARM Code Generation

Once we got Wasmer compiling on ARM, we needed to implement the code emitter for ARM. For the Singlepass backend we use the dynasm! crate to emit machine instructions at runtime.

When we started planning supporting ARM compilation, dynasm only had support for emitting x86 instructions

We contacted Maurits (author of the dynasm crate) and offered an open-source sponsorship to add support for Aarch64 instructions in Dynasm. Maurits laid out a plan with the time required to implement them and the effort required for each of the steps… he did a terrific job in both planning and implementing the instructions in record time!

Once dynasm added support for ARM, we were good to go! We started implementing the easiest Wasm instructions (integer operations) and got very simple programs running in our ARM Packet server.

Once the simple programs run, we jumped on running spectests: starting with all disabled and enabling them as we added support for more operations.

3. CI Integration

Once big chunk of Wasm spectests were passing on our ARM server, it was time to add integration into our CI, so each time we pushed a change to the pull request… tests can be run!
That way we can assure no regressions on ARM for the foreseeable future.

However, Azure Pipelines (our repo CI server) was not able to run on ARM servers …what else could we use?
Fortunately, we were lucky enough that Travis announced support for Multi-CPU architecture just after a few days looking for alternatives! 🚀

After 3 months of hard work, 120 commits and more than 17,000 spectests passing we just landed the PR in master and published a new version of Wasmer!

Heyang Zhou has been driving this tremendous effort and deserve huge props for the work he has done on making Wasmer available on ARM.

In summary…

Now, you can create programs that run in any platform (Linux, macOS and Windows) and in any chipset (x86, Aarch64) without any requirement to have a ARM chipset to test things on, all thanks to WebAssembly… isn’t that awesome?! 🚀✨

That way, developers that have x86 machines should be able to create programs that will run on Aarch64 (ARM) devices without any code modification.
Same way, ARM developers could create programs that target x86 machines (or more chipsets in the future!) very easily.

To reinforce that argument, all the programs that Wasmer was able to run before, now should run seamlessly even in more chipsets, and you can expect this expansion to continue happening in the future.
This is great for both the standalone programs and for any of the WebAssembly language embeddings that we support (Python, Rust, Go, PHP, Ruby, C#, R), as their universe just got a little-bit bigger.

Bonus: the programs available in WAPM should run natively in your ARM device with no extra steps required!

Wasmer running on a Raspberry Pi!

Here’s a simple demo running rustpython in a Raspberry Pi 4 with Wasmer:

And you can run it too! Install Wasmer in your ARM (or x86!) device with:

curl https://get.wasmer.io -sSfL | sh

Hope you enjoyed this article! 🎉

--

--