A clean and expressive IR that compiles to QBE and LLVM, runs interpreted at speed, or fires through an experimental JIT on Apple Silicon.
@fib(%n: int): int { entry: %a0 = const 0 %b0 = const 1 %i0 = const 0 jmp loop_cond loop_cond: %a = phi [entry: %a0, loop_body: %a_next] %b = phi [entry: %b0, loop_body: %b_next] %i = phi [entry: %i0, loop_body: %i_next] %cond = lt %i, %n br_if %cond, loop_body, loop_end loop_body: %tmp = add %a, %b %a_next = %b %b_next = %tmp %i_next = add %i, 1 jmp loop_cond loop_end: ret %a }
@fib(%n: int): int { entry: %cond0 = le %n, 1 br_if %cond0, base_case, recursive_case base_case: ret %n recursive_case: %n1 = sub %n, 1 %n2 = sub %n, 2 %task1 = spawn call fib(%n1) %task2 = spawn call fib(%n2) %r1 = sync %task1 %r2 = sync %task2 %res = add %r1, %r2 ret %res }
@test_arena { %arena = arena_create %a = arena_alloc %arena, 64 %b = arena_alloc %arena, 128 %c = arena_alloc %arena, 32 arena_destroy %arena ret 0 } @test_free { %p = alloc Person %age_ref = get_field_ref %p, age store %age_ref, 42 %val = load %age_ref call puts(%val) free %p ret 0 }
Static single-assignment throughout. Phi nodes, explicit basic blocks, and clean control flow. Optimization passes are straightforward to write and reason about.
Lower to QBE for fast compilation, LLVM for optimized output, or run directly in the interpreter. Same source, different targets.
Direct aarch64 code generation targeting Apple Silicon. No intermediate steps. Further platforms are planned.
First-class spawn and
sync primitives. Express concurrent
workloads directly in the IR.
Built-in arena_create,
arena_alloc, and
arena_destroy alongside manual
alloc / free.
Aggregate types with get_field_ref and
get_index_ref. Load and store structs by
pointer as in any systems IR.
Both forms lower to the same internal representation.
@fib(%n: int): int { entry: %a0 = const 0 %b0 = const 1 %i0 = const 0 jmp loop_cond loop_cond: %a = phi [entry: %a0, loop_body: %a_next] %i = phi [entry: %i0, loop_body: %i_next] %cond = lt %i, %n br_if %cond, loop_body, loop_end loop_body: %tmp = add %a, %b %a_next = %b %i_next = add %i, 1 jmp loop_cond loop_end: ret %a }
@fib(%n: int): int { %a = const 0 %b = const 1 %i = const 0 while (lt %i, %n) { %tmp = add %a, %b %a = %b %b = %tmp %i = add %i, 1 } ret %a } @main(): int { %s = call sum_to(1000000) %i = const 0 while (lt %i, 10000) { %r = call fib(70) %i = add %i, 1 } call puts("Done.") ret 0 }