Skip to content

v5.0.0 — Self-hosted toolchain (Linux ELF substrate)

Choose a tag to compare

@zemo-g zemo-g released this 14 May 03:54
· 479 commits to master since this release

Rail produces its own aarch64 Linux ELF binaries. Encoder, assembler, static linker, and ELF writer are pure Rail. For the supported subset of inputs, the build pipeline invokes no external as, ld, or codesign.

What ships

Module Lines Role
jit/arm64.rail +200 23 new encoders for the Linux mnemonic set (ldrb/strb imm/reg-offset/post-index, clz, neg, cmn imm+reg, rev, rev16, fneg, frinta, fcvt s_d / d_s, tbnz, stp/ldp pre/post-index, add/sub imm, asr/lsr/lsl imm). 31/31 byte-verified against as.
stdlib/elf.rail 175 Elf64 writer for static aarch64 binaries (one PT_LOAD for tiny, three for full text+data+bss-via-memsz).
tools/v5/elf_asm.rail 567 Section-aware ARM64 assembler + static linker. Two-pass: pass 1 builds (name, section, offset) label table; layout resolves to vaddrs; pass 2 emits bytes with adrp/:lo12: symbol resolution. Handles .text/.data/.bss/.rodata/.section __DATA,__mod_init_func (skipped), .quad/.byte/.long/.ascii/.asciz/.space/.comm/.p2align/.align, plus writeback stp/ldp variants and the adrp+add :lo12: symbol-load idiom.
tools/v5/compile_elf_full.rail 80 Driver: source .s → 3-pass pipeline → multi-segment ELF. Patches e_entry to _start.

End-to-end verified on aarch64 Linux (Pi Zero 2 W)

Program ELF size Result
exit42_linux.s 132 B exit 42
fib_linux.s 204 B exit(fib(10)) = 55
hello_linux.s 4105 B prints "v5 lives\n", exit 9 (adrp + add :lo12: + write syscall)
bss_test_linux.s 4096 B BSS counter loop, exit 7

Each binary's .text bytes are byte-equivalent to canonical as + ld output. Pipeline invokes neither external assembler nor linker.

compile.rail Linux pipeline fixes (precursor)

Two long-standing bugs in build_linux fixed: duplicate-symbol awk strip ran only on macOS-cross (now runs on Linux too, list broadened to cover the _rail_* runtime helpers that linux_libc.s redefines), and the macOS-only .section __DATA,__mod_init_func block is now stripped. tools/linux_libc.s gains _memcpy and _fmod — the two libSystem references with no Linux-side definition.

Tag-readiness checklist

  • compile.rail's real Linux output traverses the new pipeline → byte-equivalent ELF
  • Linux ELF substrate verified on aarch64 hardware
  • 176 encoders byte-verified against as (89 + 56 + 31)
  • No regression on ./rail_native test (136/140; 4 pre-existing tensor failures)
  • No regression on ./rail_native self byte-identical fixed point
  • CHANGELOG.md v5.0.0 entry
  • Leak guard CI green

Deferred

  • Pi self-host of ./rail_native test via Rail-only build — current GC layout reserves 1.2 GB BSS, exceeding Pi Zero 2 W RAM. Heap-size knob is v5.1 scope.
  • macOS Mach-O end-to-end with dyld stubs — Phase 4b covered the libSystem-free subset; stub-aware Mach-O (LC_LOAD_DYLIB, indirect symbol table, __stubs, __got, bind opcodes) is ~1500 more lines. Tracked as v5.2.

🤖 Generated with Claude Code