bfjit is a Brainfuck JIT compiler written in Zig. It reads a Brainfuck file, folds runs of simple commands together, emits x86-64 machine code, and runs that code in the same process.
The code is small enough to study without much compiler background. The machine-code emitter is handwritten, so there is no LLVM or other compiler framework involved.
Build the executable:
zig buildRun the included Hello World program:
zig build run -- hello_world.bfYou can also run the installed binary directly:
./zig-out/bin/bfjit hello_world.bfbfjit expects one source file. If the program uses ,, it reads raw bytes from standard input. For example, save ,. in a file named echo.bf, then run:
printf 'A' | zig build run -- echo.bfThe program prints A.
All eight Brainfuck commands work:
| Commands | What they do |
|---|---|
+ / - |
Increment or decrement the current cell |
> / < |
Move the tape pointer right or left |
. |
Write the current byte to standard output |
, |
Read one byte from standard input into the current cell |
[ / ] |
Loop while the current cell is nonzero |
The tape has 30,000 u8 cells, all initialized to zero. Cell arithmetic wraps at 0 and 255. Reading at EOF stores zero in the current cell. The parser ignores non-command bytes, so comments and whitespace are fine.
The parser reports unmatched brackets with their byte offset. Moving outside the 30,000-cell tape stops the program with an error. Source files may be up to 1 MiB.
Brainfuck source
-> compact IR
-> x86-64 machine bytes
-> executable memory
-> native function call
The parser combines adjacent cell changes and pointer moves. For example, +++++-- becomes one add 3 operation. The x86-64 backend turns those operations into machine-code bytes and turns loops into conditional jumps.
Input and output go through C ABI callbacks into Zig. This keeps Zig's buffered standard streams out of the generated code. The generated memory starts out writable so the compiler can fill it, then changes to read-execute before the function call.
Note
This version only supports the Linux x86-64 System V ABI. It has no interpreter mode or advanced optimization passes.