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:
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).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!