RISC-V Toolchain Internals: How GCC and LLVM Turn an ISA String Into a Binary
1. Introduction
Every article in this series so far has stayed on one side of a boundary: the kernel. Watchdogs, mempool_t, the scheduler’s task-switch path, CXL’s HDM-DB coherency model — all of it lives in vmlinux, running in supervisor mode, indifferent to whatever produced the instructions it executes. This one crosses that boundary in the other direction. Before any of that kernel code runs, something had to turn .c files into RISC-V machine code, decide which of the dozens of optional RISC-V extensions to target, and encode that decision into the binary in a form the linker and the loader can both act on. That something is the toolchain, and on RISC-V it behaves differently — and is less mature — than the x86 or AArch64 toolchains most engineers take for granted.
This matters for a concrete, current reason. RISC-V is the first mainstream ISA where the extension surface is genuinely open-ended: a vendor can ship a chip with the base integer set, the compressed instruction extension, bit-manipulation extensions, vector extensions, and any number of custom extensions, in almost any combination. GCC and LLVM cannot assume a fixed feature set the way they can for x86-64-v3 or armv8.2-a. They have to parse an arbitrary, underscore-delimited ISA string, validate it against a versioned extension database, and thread that decision through every stage of compilation, assembly, and linking. Getting this wrong doesn’t just mean a missed optimization — it means emitting an instruction the target CPU will trap on.
Everything in this article was built and executed for real: cross-compiled with riscv64-linux-gnu-gcc 13.3.0 and clang 18.1.3 targeting riscv64-linux-gnu, and run under qemu-riscv64 user-mode emulation, which — confirmed during development — correctly implements the riscv_hwprobe(2) syscall used by the demo. Every command output, every disassembly fragment, and every error message quoted below is a real result, not a reconstruction.


