No. 83 / project of 147 on the ladder

TCC RV32 on chip

introduces — TinyCC RV32 fork; real guest-side C compiler; static RV32 ELF output; compiler performance follow-up

harden statelast run2026-05-05
signoff
  • DRCNOT RUN
  • LVSNOT RUN
  • antennaNOT RUN

P82 used chipcc, our toy compiler, to prove that Linux on the chip could execute a generated file. P83 replaces that toy with a real TinyCC-derived compiler: the sellicott/tcc-riscv32 fork.

The initramfs now includes /bin/tcc. BusyBox ash runs:

tcc -static -nostdlib -o /tmp/p83_tcc_hello /usr/share/p83/tcc_hello.c
chmod +x /tmp/p83_tcc_hello
/tmp/p83_tcc_hello

The generated program printed:

P83-TCC-COMPILED-ON-CHIP

What Worked

The pinned TCC fork built into a static RV32 Linux executable. In the passing run /bin/tcc was 422,904 bytes. Running that compiler inside the guest produced a 584-byte static RV32 executable in /tmp.

The source is intentionally minimal. It defines _start, uses inline RISC-V assembly to make SYS_write and SYS_exit, and avoids libc startup, headers, floating point, and normal main.

What Bit Us

GCC-style register variables were not enough for this TCC fork. The first generated program stored the desired syscall register values on the stack, reached ecall with stale registers, and spun forever. The working source loads a0, a1, a2, and a7 directly in inline assembly.

Verification

tty-smoke produced these markers:

P83-BUSYBOX-SMOKE
P83-UNAME-OK
P83-TOOLS-OK
P83-BACKSPACE-OK
P83-TCC-OK
P83-TCC-COMPILED-ON-CHIP
P83-COMPILE-OK
P83-FILE-OK

The final marker arrived after 209,262,630 post-load cycles with all 357 host input bytes delivered.

Honest Status

checkstatus
Static RV32 /bin/tcc from pinned forkPASS
TCC runs inside the guestPASS
TCC emits /tmp/p83_tcc_hello on the chipPASS
Generated RV32 executable runs on the chipPASS
Normal main + libc + headersNOT RUN
Upstream TinyCC RV32 supportNOT RUN
LibreLane hardeningNOT RUN

Profiling Next

This path is now real enough to profile. The next project should turn the existing PC samples, state counters, and milestone cycles into a flamegraph-style notebook page: where time is spent, what is Linux, what is shell/TCC/userspace, and which RTL/runtime features would buy the most speed.