I am developing the toolchain of a pure, functional programming language that aims on targeting WebAssembly. I am somewhat familiar with type theory, and thus, the type checker for this language is ready. The problem that I'm facing right now is translating this high level language to the lower level of WebAssembly.
After checking types, the compiler is able to take the AST and transform it into a fairly standard supercombinator, lambda-lifted form. Every expression will be either a:
- Function call (name of a top-level function + expressions standing for arguments)
- Reference (name of a top-level function or constant);
- Variable (name of an argument or local);
- Integer (
i32numeric literal); - Double (
f64numeric literal); - Bytestring (
size+ sequence ofsizeUTF-8 bytes); - Thunk (name of a top-level function + an environment of captured values).
Function calls, references, variables, integers, doubles and bytestrings are self-explanatory. Thunks are obtained from partially applied functions or from lambda-lifted closures. The compiler knows when and where thunks become saturated and is capable of automatically inserting force instructions.
Pointers and numeric literals will happily live on the stack, they are small and cheap to copy around. But copying bytestrings, depending on how big they are, can be costly and there's also the chance of an overflow. Manipulating bytestrings on stack memory would also require copies. Functions manipulating recursive data structures may require a copy of the entire thunk at each step.
This means that some heap allocation would be immensely helpful (nigh indispensable), but managing heap memory manually without some tool like malloc/free is a recipe for disaster. Threads like this and posts like this mention allocators for WebAssembly that I thought were only available to C, and I have no idea how it would be possible for me to bring one of them to the runtime of my language. There's also this repository, but I don't know how I would be able to turn this allocator written in Rust into a generic WebAssembly module and use the exported functions.
How would I start integrating an allocator into the runtime of the generated WebAssembly bytecode that comes from the compiler of my language?