Architecture
xcc is a heterogeneous data-parallel compiler. One source, in xc or in C, becomes one executable that holds native code for the CPU and a kernel for every GPU API the target can reach. The program decides at run time, on the machine it runs on, which devices to use.
The parts
Section titled “The parts”- Front ends. xc has a hand-written recursive-descent parser; C is read through clang’s front end as LLVM IR before any LLVM optimisation, and xcc translates it into its own IR. Both lower to the same SSA intermediate representation.
- Data-parallel extraction. Loops whose iterations
are independent become
parblocks, in three phases: acquisition of candidate loops, validation of each one, and run-time device-under-test measurement that picks the devices. - The optimiser. SSA passes over the shared IR: inlining, CSE, LICM, loop vectorisation for NEON, AVX2, AVX-512 and WebAssembly SIMD, guarded devirtualisation, idiom recognition and more.
- GPU kernels. Every
parblock is printed as Metal Shading Language, PTX, SPIR-V and WGSL by xcc itself, and embedded in the executable: zero-dependency GPU inlining, with no GPU toolkit at build time. - Tiles, devices and the network. The runtime cuts a
block into tiles and schedules them across every CPU core, GPUs from different vendors at
once, and GPUs on other machines served by
xcd: transparent, scalable network tiling. - CPU back ends. arm64, x86-64, Windows x64 and WebAssembly, with in-house assemblers, linkers and Mach-O, ELF and PE writers, so a build needs no system toolchain. The same back-end design reaches the Motorola 68000, 32-bit ARM and a banked 6502.
Self-hosting
Section titled “Self-hosting”xcc is written in xc and compiles itself. A release is built three times over, the compiler building the compiler, and the second and third builds must be byte-identical before it ships.