So last year I started writing a series on compiling a functional language to LLVM, and I have to confess, I came utterly unstuck.
Until recent versions, LLVM tried to be helpful by making you specify types for all pointers you pass around. This is really helpful in simple cases as you get basic typechecking at compile time. However, once you start implementing things like sum types (ie, reserve a slab of memory, and stuff it with one of several sets of data), it becomes super annoying.
For example, compiling an Either<Int, Bool>
type requires you to constantly cast between “arbitrary array type we’ve chosen
that takes up the right amount of memory”, “this thing if it turns out
to be Left<Int>
” and “this thing if it turns out to be Right<Bool>
.
This has been solved though! More recent versions of LLVM have the concept of an Opaque pointer, which allows us to pass pointers around without caring what type they are, and then think about the types when it comes to actually interacting with the underlying data. This is ideal!
However, it’s only available in LLVM 14 onwards, and getting a working
version-matched set
of LLVM Haskell libraries turns out to be precarious at best. I got reasonably
close using
the LLVM-15 branch of llvm-hs-pure
, but could not find an equivalent for llvm-hs-pretty.
Basically, it was all getting a bit fiddly and stupid, and writing a tutorial that is either a) already out of date or b) relies on a set of arbitrary commits from a bunch of forks doesn’t feel like it will be particularly useful, so I have decided to change tack.
The good news?
I decided to port the project to compile to WebAssembly instead! Development of the thing itself has been going really well, see for yourself here: wasm-calc
The language is fully featured enough that we can create a very simple wasm-4 game with it.
Some thoughts so far:
The wasm package for Haskell is lovely!
Not being able to cheat by including a bunch of C in a runtime has forced me to learn how allocators work
There’s a bunch of useful resources, like watlings and Mozilla’s docs.
What’s next?
As well as serving as a big excuse, this blog is supposed to be a forcing
function to write the tutorials to go with all the wasm-calc
versions. I’ll
start by porting the llvm-calc
blogs, and then move onto the new features
we’ve got.
Make sense? If not, get in touch!
Further reading: