← Back to Blog

The C99 Backend

November 1, 2024 compilerc99

The C99 backend transpiles Lateralus to portable C, enabling embedded and OS development. It's the secret weapon that lets Lateralus run on everything from microcontrollers to mainframes.

◉ Why C99?

C compilers exist for every platform ever built. From 8-bit AVR chips to z/Architecture mainframes, if silicon runs code, a C compiler targets it. By transpiling to C99, Lateralus inherits decades of optimization work for free.

C99 specifically because:

◉ Freestanding Mode

lateralus build --target c99 --freestanding kernel.ltl

No libc, no runtime, no OS dependencies. Just your code, compiled to raw C that can run on bare metal.

Freestanding mode disables:

What you get is pure, position-independent code that can run at any address. Perfect for bootloaders and kernels.

◉ The Translation

Lateralus maps surprisingly well to C. Here's what the compiler generates:

// Lateralus
fn factorial(n: int) -> int {
    if n <= 1 { return 1 }
    return n * factorial(n - 1)
}

// Generated C99
static int64_t ltl_factorial(int64_t n) {
    if (n <= 1) { return 1; }
    return n * ltl_factorial(n - 1);
}

Functions become static C functions. Structs become C structs. Pipelines get transformed into nested calls:

// Lateralus
data |> transform |> filter |> output

// Generated C99
ltl_output(ltl_filter(ltl_transform(data)))

◉ Memory Management

The C backend supports three memory modes:

1. GC (default): Conservative garbage collector, like Boehm GC

lateralus build --target c99 --gc=conservative

2. Arena: Region-based allocation, freed in bulk

lateralus build --target c99 --gc=arena

3. Manual: Explicit alloc/free, for OS kernels

lateralus build --target c99 --gc=manual --freestanding

◉ The Preamble

Every generated C file includes a standard preamble with type definitions:

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

typedef struct ltl_string { char* data; size_t len; } ltl_string;
typedef struct ltl_list { void* data; size_t len; size_t cap; } ltl_list;
typedef struct ltl_map { void* buckets; size_t size; } ltl_map;

In freestanding mode, even these headers are replaced with minimal definitions that assume nothing about the environment.

◉ Real-World Use: LateralusOS

The C backend powers LateralusOS — a complete operating system written in Lateralus:

// kernel/main.ltl
@foreign("c")
fn kernel_main() {
    serial_init()
    serial_puts("LateralusOS booting...")

    memory_init()
    interrupts_init()
    scheduler_init()

    // Pipeline for boot sequence
    drivers
        |> filter(fn(d) { d.available() })
        |> each(fn(d) { d.init() })

    serial_puts("Boot complete. Entering shell.")
    shell_run()
}

This compiles to ~500 lines of C, which then compiles to a 12KB kernel binary.

◉ Performance

The generated C is clean enough that GCC and Clang optimize it well. Benchmarks on a recursive Fibonacci:

Target fib(40)
Python backend45.2s
Bytecode VM2.1s
C99 backend (-O2)0.38s
Native C0.35s

We're within 10% of hand-written C. Not bad for a high-level language.

◉ Try It

Generate C from your Lateralus code:

lateralus c myprogram.ltl -o output.c
gcc -O2 output.c -o myprogram
./myprogram

Or for embedded targets:

lateralus c --freestanding firmware.ltl -o firmware.c
arm-none-eabi-gcc -mcpu=cortex-m4 -ffreestanding firmware.c -o firmware.elf

The C99 backend turns Lateralus into a practical systems language. Write elegant pipelines, deploy anywhere C runs.