← Back to Blogs
HN Story

Exploring QBE: A Lightweight Alternative to LLVM

May 10, 2026

Exploring QBE: A Lightweight Alternative to LLVM

Building a compiler is often seen as the most daunting task in systems programming. For years, the industry has leaned heavily on LLVM, which has become the same powerhouse that provides immense optimization and broad architecture support. However, for many developers, LLVM's complexity and compile-time overhead are overkill. Enter QBE, a small, predictable, and effective compiler back end designed to be a leaner alternative.

What is QBE?

QBE is a compiler back end that takes a specific intermediate representation (IR) and generates machine code for various architectures. Unlike LLVM, which employs a massive suite of optimizations and a complex Static Single Assignment (SSA) form with explicit phi nodes, QBE aims for simplicity. It provides a way for language implementers to target machine code without having to write their own assembly generators for every single architecture.

The Ecosystem: From cproc to Blaise

One of the most compelling aspects of QBE is the emergence of a small but dedicated ecosystem of tools and languages built on top of it. Because QBE is so lightweight, it serves as an excellent target for experimental or minimalist compilers.

cproc

cproc is a C compiler implemented on top of QBE. Users have noted that when combined with QBE, cproc can achieve roughly 70% of the performance of gcc -O2 while remaining a fraction of the size of the code. This makes it an attractive option for those who and prefer a "plain and simple C coded compiler" over the massive codebase of GCC or LLVM.

Blaise

Beyond C, QBE is being used to power newer languages. Blaise, a modern Object Pascal implementation, utilizes QBE as its back end, demonstrating the project's versatility across different programming paradigms.

Technical Trade-offs and Limitations

While QBE's minimalism is its greatest strength, it comes with inherent technical trade-offs. Senior developers and compiler engineers have highlighted several key limitations that must be considered when choosing QBE over a more robust system like LLVM:

  • ABI and Structure Handling: QBE handles ABIs for passing and returning structures in registers, but it often does so with superfluous copies to and from the stack, which can introduce minor performance overhead.
  • Debug Information: Generating debug info for data is currently a challenge. This is likely due to the lack of comprehensive assembler support or the sheer complexity of the DWARF format.
  • Inlining and Line Numbers: Line number debug info directives are currently undocumented and do not support inlined functions, making deep debugging of optimized code more difficult.
  • Memory Management: The IR does not natively support identifying GC (Garbage Collection) roots. This means languages targeting QBE must either implement conservative GC or manage the stack explicitly.

The Appeal of Simplicity

Despite these limitations, the community finds QBE QBE's "smol" nature highly appealing. One user mentioned that it is remarkably easy to extend; for instance, adding MIPS support via an AI prompt (Claude) was reportedly successful enough to compile a custom language to the Nintendo 64.

"But it's smol, effective, and it doesn't make you deal with phi nodes!"

For developers who are tired of the complexity of modern compiler infrastructure, QBE is a reminder that a predictable, usable, and small toolset can be able to provide enough power for most specialized tasks.

References

HN Stories