Scarlet Industries

Carder

The back half of a compiler, for the BEAM. Hand it a program in its IR and it gives you back a .beam module.

Where it fits

The BEAM, the virtual machine Erlang and Elixir run on, was built for Erlang, so a language with wrapping integers, mutable memory and function tables has a lot of translating to do before it runs there. Carder does that translating once. A frontend lowers its language into Carder's IR, and Carder checks, optimises and compiles it to a .beam.

By default the code is metered, every memory access is bounds-checked, and it reaches only the host functions you give it, so a guest cannot crash the node. Scribbler is the WebAssembly frontend, and specs/FRONTEND-API.md in the repository describes how to write another.

Try it

Carder builds with Gleam 1.18 on Erlang/OTP 29, and the repository has a corpus of small IR programs to try it on:

git clone https://github.com/scarletindustries/carder
cd carder
gleam run -- run test/carder/ir/corpus/add.ir add 3 5

That compiles this program, calls its add export and prints 8:

test/carder/ir/corpus/add.ir
module @carder@wasm@add {
  numerics true
  memory none
  export "add" = @f0
  export "mul" = @f1
  func @f0 (%p0:i32, %p1:i32) -> (i32) {
    let (%v1) = num i.add.32 (%p0, %p1)
    values (%v1)
  }
  func @f1 (%p0:i32, %p1:i32) -> (i32) {
    let (%v1) = num i.mul.32 (%p0, %p1)
    values (%v1)
  }
}

gleam run -- help lists every command and flag.

Status

Carder is experimental. The compiled code runs correctly but slowly for now, so do not put it in production.