KernRift

A self-hosted systems language compiler with an SSA IR backend. Self-compiles on all 8 targets — Linux, macOS, Windows, Android on x86_64 and ARM64. No Rust, no C, no LLVM. Fat binaries by default.

KernRift is a programming language created by Pantelis Christou.

$ krc hello.kr -o hello.krbo
$ kr hello.krbo
Hello, World!

KernRift is a self-hosting systems language compiler written entirely in KernRift — ~226K tokens of source across 18 files, plus an 18-module standard library. The compiler ships with an SSA-based IR backend: AST lowers to a target-independent intermediate representation, liveness analysis runs, a graph-coloring register allocator assigns physical registers, an optimizer does constant folding / DCE / CSE / LICM and an AST-level function inliner, and dedicated emitters produce native x86_64 and AArch64 machine code. No Rust, no C, no LLVM, no external assembler — the compiler emits raw machine bytes directly. By default, krc produces BCJ+LZ-Rift-compressed fat binaries containing 8 platform slices — Linux, Windows, macOS, and Android, each with x86_64 and/or AArch64 native code. The compiler self-hosts on all 8 targets; CI verifies bootstrap fixed point and runs 448 tests on every push. Recent work: v2.8.23 fixed three IR-emitter memory leaks that dropped peak self-compile RSS by 96–99 % (single-arch 806 MB → 33 MB; fat 6.3 GB → 87 MB), making fat self-compile feasible on a 4 GB Pi 400. The latest landings add an AST-level function inliner that folds pure single-expression callees at every call site (with DCE preserving original definitions for --emit=obj/--emit=asm/--emit=ir) and copy-coalescing scaffolding behind a runtime gate. Kernel-first primitives include device blocks for typed MMIO, load/store/vload/vstore pointer builtins, slice parameters [T] name with .len, static and struct arrays, inline assembly, signed comparisons, atomic operations, bitfield operations, and --freestanding mode.

Self-Hosting Compiler

KernRift compiles itself. The compiler is ~226K tokens of KernRift across 18 source files, plus 18 stdlib modules. It achieves a bootstrap fixed point — compiling itself twice produces bit-identical binaries, verified on all 8 platform targets (Linux x86_64/ARM64, macOS ARM64/x86_64, Windows x86_64/ARM64, Android ARM64/x86_64) with 448 tests passing on every CI run. No LLVM, no Rust, no C, no external assembler — just KernRift all the way down.

Stage Input Output Verified
krc → krc2 ~45,000 lines (.kr) ~1.14 MB native ELF (IR, default) / ~1.19 MB (legacy)
krc2 → krc3 ~45,000 lines (.kr) identical output to krc2
krc3 → krc4 ~45,000 lines (.kr) identical output to krc3 krc3 == krc4 ✓
Self-compile time ~45,000 lines ~180ms (legacy) / ~1.05s (IR + optimizer, default) ~8.2s fat binary (8 slices, 3.81 MB) ✓
Cross-compile x86_64 host ARM64 + Windows PE + macOS Mach-O Tested on all platforms ✓
Fat binary any .kr file .krbo (8 slices, BCJ+LZ-Rift) Default output ✓

Benchmarks vs. C and Rust

KernRift produces the smallest binaries and compiles 20-90× faster than gcc/rustc. Runtime is competitive with unoptimized C. All measurements on AMD Ryzen 9 7900X, Linux 6.17, gcc 13.3, rustc 1.93.

Compile Time

Benchmark krc gcc -O0 gcc -O2 rustc rustc -O2
Fibonacci (recursive, fib(40)) 1ms 68ms 44ms 158ms 79ms
Sort (bubble 10K ints) 2ms 32ms 32ms 115ms 94ms
Sieve (primes to 10⁶) 2ms 27ms 30ms 77ms 89ms
Matrix Multiply (200×200 int) 2ms 32ms 31ms 71ms 85ms
Self-compile krc (legacy / IR default) ~180ms / ~1.05s N/A

Binary Size

Benchmark krc gcc -O0 gcc -O2 rustc rustc -O2
Fibonacci 383 B 15.8 KB 15.8 KB 3.9 MB 3.9 MB
Sort (quicksort) 772 B 16.0 KB 16.0 KB 3.9 MB 3.9 MB
Sieve 719 B 16.0 KB 16.0 KB 3.9 MB 3.9 MB
Matrix Multiply 1.9 KB 16.0 KB 16.0 KB 3.9 MB 3.9 MB
Self-compiled compiler (x86_64 IR default / legacy) ~1.14 MB / ~1.19 MB N/A
Self-compiled fat binary (all 8 platforms) ~3.81 MB BCJ + LZ-Rift compressed

Runtime (median of 3)

Benchmark krc gcc -O0 gcc -O2 rustc rustc -O2
Fibonacci fib(40) 409ms 383ms 78ms 386ms 162ms
Sort (bubble 10K) 108ms 150ms 270ms 2,637ms 45ms
Sieve (primes to 10⁶) 3ms 4ms 2ms 20ms 2ms
Matrix 200×200 33ms 16ms 4ms 125ms 3ms

krc's SSA IR backend uses a graph-coloring register allocator (6 colors on x86_64, 10 on AArch64, partial used-callee-save prologue, cross-register spill-reload peephole) plus constant folding / DCE / CSE / LICM and an AST-level function inliner. No auto-vectorization. Compile time and binary size are where krc excels; runtime is competitive with unoptimized C. Measurements on AMD Ryzen 9 7900X, gcc 13.3, rustc 1.93.

Self-Compilation Across Platforms

Self-compile = krc rebuilding its own ~226K-token source. Single-arch produces a native binary for the host architecture; fat binary bundles all 8 platform slices into one BCJ+LZ-Rift-compressed .krbo. v2.8.23 fixed three per-function memory leaks in the IR emitter and made the liveness scratch buffer reusable across basic blocks, dropping peak RSS ~96-99% vs v2.8.22 and making fat self-compile feasible on a 4 GB Raspberry Pi 400 (was OOM-bound). Peak RSS is the high-water mark of the compiler process; the resident set never grows beyond it during the run.

Platform / Device CPU / RAM Single Arch (time / peak RSS) Fat Binary (time / peak RSS)
Linux x86_64 (desktop) AMD Ryzen 9 7900X (12c/24t, 32 GB) 1.06 s / 33 MB 8.4 s / 87 MB
Windows 11 x86_64 (laptop) Intel Core Ultra 9 275HX (24c, 64 GB) 2.04 s / 38 MB 15.2 s / 91 MB
Linux ARM64 (Raspberry Pi 400) Cortex-A72 @ 1.8 GHz (4c, 4 GB) 23.8 s / 33 MB 3 min 11 s / 87 MB
Android ARM64 (Redmi Note 8 Pro) MediaTek Helio G90T (2× A76 + 6× A55, 6 GB) 19.5 s / 33 MB 2 min 35 s / 80 MB
Android ARM64 (Galaxy Z Fold 5) Snapdragon 8 Gen 2 (1×X3 + 4×A715/A710 + 3×A510, 12 GB) 6.84 s / 33 MB 52.9 s / 80 MB

How Other Compilers Compare (Self-Build)

Compiler Self-Build Time Binary Size Source
KernRift krc (IR + optimizer, default) 1.05s ~1.14 MB measured (Ryzen 9 7900X)
KernRift krc (legacy, --legacy flag) 180ms ~1.19 MB measured (Ryzen 9 7900X)
TCC <1s (est.) ~100 KB bellard.org/tcc
Go toolchain ~1-3 min ~50 MB go.dev/rebuild
LLVM + Clang ~4-5 min ~50 MB OpenBenchmarking (Ryzen 9 7950X)
rustc (stage 2) ~6-8 min ~80 MB dtolnay/buck2-rustc-bootstrap
GCC (3-stage) ~20-90 min ~30 MB (cc1) OpenBenchmarking (220+ runs avg)

krc is not directly comparable to production compilers — it has an SSA IR with constant-folding / DCE / CSE / LICM and an AST inliner, a graph-coloring register allocator, but no auto-vectorizer and no external linker in the loop. The comparison shows where a short, self-contained compiler sits on the build-time spectrum. TCC is the closest analog. External data is from public benchmarks on comparable hardware; see linked sources.

~45,000 lines, ~1.14 MB self-compiled binary. 448 tests. Bootstrap fixed point verified on all 8 targets (Linux, macOS, Windows, Android × x86_64, ARM64). Fat binary: 8 slices, BCJ+LZ-Rift compressed.

Self-Hosting

The compiler is written in KernRift and compiles itself. After a one-time bootstrap from the Rust bootstrap compiler, krc is fully self-sustaining. No external toolchain needed.

Universal Fat Binaries

By default, krc bundles 8 platform slices (Linux, Windows, macOS, Android × x86_64 + ARM64) into a single BCJ+LZ-Rift-compressed .krbo file. LZ-Rift compression uses 24-bit offsets, 65K hash tables, and lazy matching for arch-pair blobs. Use --arch=x86_64 or --arch=arm64 for a single-architecture native binary.

Device Blocks for MMIO

device UART0 at 0x3F201000 { Data at 0x00 : u32 } declares a hardware register set. Reads and writes to UART0.Data compile directly to volatile loads and stores with the right width, plus the appropriate memory barrier — mfence on x86_64, DSB SY on ARM64.

Clean Pointer Builtins

load8/16/32/64(addr) and store8/16/32/64(addr, val) replace the verbose unsafe { *(addr as uint32) = val } form. Volatile variants vload*/vstore* add memory barriers for MMIO. Same codegen, much cleaner to read.

Slice Parameters

fn foo([u8] data) takes a fat pointer (ptr, len). Inside the function, data.len reads the length and data is a plain pointer for indexing. Callers pass two arguments. Classic C (ptr, len) idiom with a nicer symbolic name.

Static & Struct Arrays

static u8[4096] page gives you a zero-initialized data-section buffer. Point[10] pts gives you a fixed array of struct instances with full pts[i].field syntax. Both work locally and at module scope.

Zero Dependencies

The compiler is a single static binary. It produces native ELF, PE, and Mach-O executables without cc, ld, ar, or any external tool. Each output binary is fully static — no libc, no dynamic linking, no runtime.

Cross-Platform Output

8 platform targets from any host: ELF (Linux + Android), PE/COFF (Windows), and Mach-O (macOS), each for x86_64 and AArch64. On Windows, install.ps1 sets up the toolchain and kr.exe runs fat binaries natively. KrboFat containers, AR archives, and KRBO portable objects.

Standard Library

18 modules (~4,100 lines) covering strings, I/O, math, formatting, memory management (bump-allocated arenas with guard pages, fixed-size pools with double-free detection — std/alloc.kr), dynamic arrays, hash maps, colors, fixed-point arithmetic, fast memory operations, framebuffer graphics, font rendering, UI widgets, time/clock access, structured logging, floating-point math, and raw socket networking. Import with import "std/string.kr" — the compiler resolves stdlib paths automatically via ~/.local/share/kernrift/.

VS Code LSP

First-class editor support via the KernRift VS Code extension (v0.2.3). Includes syntax highlighting, diagnostics from krc check, completions, hover documentation, and go-to-definition. Available on the VS Code Marketplace.

Import System

import "file.kr" brings in declarations from other source files with recursive dependency resolution and stdlib search paths. No more concatenation — the compiler resolves the dependency graph automatically.

Match Statements

match expr { val => { body } ... } for clean multi-way branching. Combined with enums, match provides exhaustive pattern handling for state machines and dispatch logic.

Methods & Short Aliases

fn Point.sum(Point self) attaches a method to a struct; call it with p.sum(). Short type aliases u8/u16/u32/u64 and i8..i64 are synonyms for the long forms. Nested struct access (a.b.c) works naturally.

Inline Assembly

asm("cli") or asm { "cli"; "sti" } emits raw machine instructions. Supports x86_64 privileged instructions (cr0/cr3, lgdt, lidt, wrmsr, cpuid, in/out) and ARM64 system instructions (msr, mrs, svc, wfi, dsb, dmb). Raw hex bytes for anything else.

Kernel Annotations

@naked functions skip prologue/epilogue — pure assembly bodies for ISR entry points. @noreturn marks diverging functions. @packed structs for hardware register layouts. @section(".text.init") for linker section placement.

Bitfield & Signed Ops

bit_get, bit_set, bit_clear, bit_range, bit_insert for hardware register manipulation. signed_lt/gt/le/ge for signed comparisons (the default <, >, <=, >= operators are unsigned). Stack size warnings at compile time.

Freestanding Mode

krc --freestanding disables the startup trampoline, auto-exit insertion, and OS-specific syscall wrappers — producing bare-metal code ready for kernel entry points, bootloaders, and embedded firmware.

Atomic Operations

Lock-free primitives for concurrent data structures: atomic_load, atomic_store, atomic_cas (compare-and-swap), atomic_add, atomic_sub, atomic_and, atomic_or, and atomic_xor. Compiled to native LOCK-prefixed instructions on x86_64 and LDXR/STXR exclusive pairs on ARM64.

Floating-Point & Multi-Return

f32 and f64 types with full arithmetic, comparisons, conversions, and a math library (sin, cos, exp, log, pow, sqrt, fmt_f64). f16 for storage. Hardware sqrt, software trig/exp/log. Multi-return with return (a, b) and 2-tuple destructuring (u64 q, u64 r) = divmod(17, 5). Inline asm I/O constraints: asm { "rdtsc" } out(rax -> lo, rdx -> hi).

Framebuffer & UI

Stdlib modules for bare-metal graphics: std/fb.kr for framebuffer pixel, line, and rectangle drawing; std/font.kr for bitmap font rendering; std/widget.kr for panels, labels, buttons, progress bars, and text fields.

Quickstart

No dependencies required. The compiler is a single static binary. No Rust, no C compiler, no linker needed.

Install
# Linux / macOS (installs krc, kr, and stdlib to ~/.local/)
curl -sSf https://raw.githubusercontent.com/Pantelis23/KernRift/main/install.sh | sh

# Windows PowerShell (installs krc.exe, kr.exe, and stdlib to %LOCALAPPDATA%\KernRift\)
irm https://raw.githubusercontent.com/Pantelis23/KernRift/main/install.ps1 | iex

# Homebrew (macOS / Linux)
brew install kernrift

# Scoop (Windows)
scoop bucket add kernrift https://github.com/Pantelis23/KernRift
scoop install kernrift

# Winget (Windows)
winget install Pantelis23.KernRift

# AUR (Arch Linux)
yay -S kernrift

# Or download directly (x86_64 / ARM64)
curl -L -o krc https://github.com/Pantelis23/KernRift/releases/latest/download/krc-linux-x86_64
curl -L -o kr  https://github.com/Pantelis23/KernRift/releases/latest/download/kr
chmod +x krc kr && sudo mv krc kr /usr/local/bin/
fibonacci.kr — Recursive Functions
fn fib(uint64 n) -> uint64 {
    if n <= 1 { return n }
    return fib(n - 1) + fib(n - 2)
}

struct Point {
    uint64 x
    uint64 y
}

static uint64 counter = 0

fn main() {
    Point p
    p.x = fib(10)     // 55
    p.y = 42
    uint64 msg = "KernRift!\n"
    write(1, msg, 10)
    exit(p.x + p.y)   // 97
}
memory.kr — Unsafe Pointer Operations
// Direct memory access for kernel development
fn main() {
    uint64 buf = alloc(4096)

    // Write a uint32 to memory
    unsafe { *(buf as uint32) = 0xDEADBEEF }

    // Read it back
    uint32 val = 0
    unsafe { *(buf as uint32) -> val }

    // Array operations
    uint8[256] table
    uint64 i = 0
    while i < 256 {
        table[i] = i
        i += 1
    }
    exit(table[42])  // 42
}
kernel.kr — Inline Assembly & Kernel Features
// Naked ISR entry — no compiler-generated prologue
@naked fn isr_timer() {
    asm { "cli"; "nop"; "sti"; "iretq" }
}

// Hardware register manipulation with bitfields
fn enable_paging(uint64 cr0_val) -> uint64 {
    uint64 pg = bit_set(cr0_val, 31)   // set PG bit
    uint64 pe = bit_set(pg, 0)          // set PE bit
    return pe
}

// Signed comparisons for kernel math
fn clamp_signed(uint64 val, uint64 lo, uint64 hi) -> uint64 {
    if signed_lt(val, lo) { return lo }
    if signed_gt(val, hi) { return hi }
    return val
}
Compile & Run
# Compile to fat binary (8 platform slices, BCJ+LZ-Rift-compressed)
$ krc program.kr -o program.krbo

# Run on any platform
$ kr program.krbo

# Or compile for a single architecture and run directly
$ krc --arch=x86_64 program.kr -o program
$ ./program

# Safety analysis
$ krc check module.kr

# Living compiler — patterns + fitness score
$ krc lc program.kr
=== KernRift Living Compiler Report ===
Functions: 12
Calls: 45
Unsafe ops: 3
Patterns found: 2
Fitness score: 85/100

# The compiler compiles itself
$ krc --arch=x86_64 krc-source.kr -o krc

Bug Reports & Discussions