Write Web Assembly With LLVM

If you didn’t know. There’s a secret in the compiler community. LLVM can compile to web assembly. LLVM is a tool used by languages like Clang and Rust as a universial intermediate representation(IR) that can be compiled down to machine code output. Web assembly is one of those outputs.

Today I am going to show how simple it is to compile LLVM into web assembly. Let’s start with writing the IR for the function

define i32 @main() {
ret i32 42
}

Simple yes? A function that returns 42. A classic.

Now here’s the magic:

llc-7 -mtriple=wasm32-unknown-unknown -O3 -filetype=obj main.ll -o main.o
wasm-ld-7 main.o -o main.wasm --no-entry -allow-undefined

These lines are doing two things:

  1. lcc is compiling our IR into a machine language representation of a specific architecture. In our case: its a binary format targeted toward web assembly (an object file).
  2. wasm-ld is linking this object file into web assembly module that browsers can use

That’s it! Now you can take your web assembly module and load it in a browser.

fetch("main.wasm")
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, {}))
.then(results => {
window.alert(results.instance.exports.main());
});

See it working here

I have a complete project here to experiment with. Some of you may be thinking, “that’s all?” Well, I hope I inspired you all to perhaps take a look at LLVM a bit more (which is quite a rabbit hole) and encouraged some of you that a compiler you can bring to the web isn’t too far out of reach as one might think. One simply needs to compile a language to LLVM IR. Have fun out there!