- C 53.9%
- Scheme 42.8%
- M4 1.9%
- Makefile 0.9%
- Python 0.4%
Wastrel, a research WebAssembly-to-C compiler
Wastrel is an implementation of WebAssembly. It compiles Wasm modules to C, and thence to native code.
Wastrel is a whole-program ahead-of-time compiler, designed to compile one Wasm module into one executable. It currently compiles in a straightforward way, emitting C that looks like the Wasm source, and relies on the C compiler to do appropriate optimizations. It has two virtues:
-
It's fairly easy to use: it's like Wasmtime's command-line interface, except that it takes longer in the compile phase.
-
The resulting code is quite fast! Compiling via GCC or Clang is slow but the output binaries have best-in-class performance.
-
Security is OK? The wastrel compiler itself is written in a memory-safe language, the output code uses C's type system as well as we can to avoid signedness, type confusion, and pointer construction bugs, and the output uses Linux's memory protection and filesystem namespace isolation facilities to prevent bugs by construction.
-
Wastrel aims to support experimental extensions: GC, stack switching, all that hot mess.
-
Wastrel aims to serve as a test bed for Whippet, a garbage collection library.
If a module needs some bespoke imports, Wastrel can accomodate that by including C runtime support files. If an import would be better provided by another Wasm module, then those modules should be linked in a Wasm-to-Wasm pass before compiling with Wastrel.
Wastrel implements WASI
0.1.
If a module imports interfaces from the wasi_snapshot_preview1 module,
Wastrel will provide implementations. Additionally, if the module
exports a nullary procedure named _start, or otherwise exports any
nullary procedure, that procedure will be called as part of the compiled
main function.
There are newer versions of WASI, notably version 1.0 that is coming out sometime early in 2026. Newer versions of WASI specify mechanisms to compose components into a whole, which involves some amount of run-time linking support. Wastrel should be able to be a part of that world somehow, but hopefully in the same way it implements WASI 0.1: by requiring that some other tool link components together and lower from component-model types to a conventional ABI, and Wastrel just provides the WASI standard library.
That said, one goal of Wastrel is to experiment with garbage collection as a compositional paradigm. Culturally speaking, WASI's thesis is that shared-nothing architectures allow one to robustly build larger systems from smaller pieces. This is at the same time obviously true but also limiting: for the size of system that can stay within an address space, we can avoid copies if we can pass immutable data by reference. This might not simply be more efficient, as it may result in systems with a completely different flavor, relative to the shared-nothing discipline. We should find out!
Wastrel is not currently intended to allow Wasm modules to be instantiated multiple times in a process, or to be included as a library in a larger program. Would you like this? We should talk!
Building
The only dependencies of Wastrel are Guile 3.0.x for the Wasm-to-C translation, a Linux system on which to run, and a C compiler. Wastrel is mainly tested on GCC.
Checking out the git repo
git clone https://codeberg.org/andywingo/wastrel
cd wastrel
Building on Guix
On Guix:
guix shell
./bootstrap.sh && ./configure && make -j
Building on Debian/Ubuntu
Something like this should work to install dependencies:
sudo apt install guile-3.0 guile-3.0-dev pkg-config gcc automake autoconf make
Building on some other Linux distro
You need Guile! And a C compiler of course. And pkg-config and automake and autoconf and make so that the build works. Godspeed!
Building on MacOS or Windows
Firstly, what are you doing with your life? I cannot imagine developing software on a platform controlled by one company. What a drag. You do you, though!
But here's the thing. Compiling plain Wasm files to C should work fine
on these targets, but a plain Wasm file can't do much. Mostly you will
be compiling Wasm binaries that use WASI interfaces because that's what
gives you, like, the ability to print to the console and access files.
But you don't want to let the binaries access any file, and indeed
WASI provides for some sandboxing. But despite the
capabilities-oriented security veneer, in practice many WASI
implementations effectively implement the sandbox via a permissions
layer: for example the WASI implementation has capabilities to access
the parents of preopened directories via .., but has to actively
prevent this capability from leaking to the compiled module via run-time
checks.
Wastrel takes a different approach, which is to use Linux's filesystem namespaces to build a tree in which only the exposed files are accessible. No run-time checks are necessary; the system is secure by construction. I do not want to implement file sandboxing any other way.
So is there a nice way to do this on MacOS? Well let's talk, surely it isn't too much code. But if not, we're back to my first point: what are you doing with your life?
Usage
$ ./pre-inst-env bin/wastrel test.wasm
Hello, world from ./test.wasm.YkJpch!
Neat, right? Just running wastrel my-wasm-file.wasm is short for
running wastrel run my-wasm-file.wasm. You can instead stop with
creating a binary with wastrel compile:
$ ./pre-inst-env bin/wastrel compile -o test test.wasm
$ ./test
Hello, world from ./test!
Or at creating a C file:
$ ./pre-inst-env bin/wastrel compile -S -o test-out.c test.wasm
$ gcc -O2 -o test -lm -Wall -Wno-unused-label -Wno-unused-variable test-out.c
$ ./test
Hello, world from ./test!
Performance
Well, comparisons are fraught. I have looked at the Coremark benchmark and Wastrel's speed is the same as native (slightly faster actually?), a tiny bit faster than w2c2, and some 40% faster than Wasmtime. A proper evaluation will take more time.
Other Wasm implementations have virtues that Wastrel will probably never have. Like, use something else if you need to run on Windows, right? Our goal is to be a test bed for experimentation. Having state of the art performance is necessary; portability to HaikuOS is not.
Acknowledgements
Wastrel uses the WebAssembly support libraries from Spritely's Hoot Scheme-to-WebAssembly compiler. Thanks especially to David Thompson for his work on these libraries.
Wastrel is Free Software, and can be run, distributed, and modified in accordance with the Apache License, version 2.0. See LICENSE.txt, for full details.