QBEの探索: LLVMに代わる軽量な選択肢

コンパイラを構築することは、システムプログラミングにおいて最も困難なタスクの一つと見なされることがよくあります。長年、業界はLLVMに大きく依存してきました。LLVMは、膨大な最適化と幅広いアーキテクチャサポートを提供する強力な基盤となっています。しかし、多くの開発者にとって、LLVMの複雑さとコンパイル時のオーバーヘッドは過剰すぎる場合があります。そこで登場するのがQBEです。QBEは、より軽量な代替手段として設計された、小さく、予測可能で、効果的なコンパイラバックエンドです。

QBEとは?

QBEは、特定の中間表現(IR)を受け取り、さまざまなアーキテクチャ向けのマシンコードを生成するコンパイラバックエンドです。膨大な最適化スイートと、明示的なphiノードを持つ複雑なStatic Single Assignment (SSA) 形式を採用しているLLVMとは異なり、QBEはシンプルさを目指しています。これにより、言語実装者が、すべてのアーキテクチャに対して独自のアセンブリジェネレータを記述することなく、マシンコードをターゲットにすることが可能になります。

エコシステム: cprocからBlaiseまで

QBEの最も魅力的な側面の一つは、その上に構築された、小さくも熱心なツールや言語のエコシステムが台頭していることです。QBEは非常に軽量であるため、実験的またはミニマリストなコンパイラの優れたターゲットとなります。

cproc

cprocは、QBEの上に実装されたCコンパイラです。ユーザーからは、QBEと組み合わせることで、cprocgcc -O2のパフォーマンスの約70%を達成しつつ、コードサイズはごくわずかな量に抑えられることが指摘されています。これは、GCCやLLVMの巨大なコードベースよりも、「プレーンでシンプルなCで書かれたコンパイラ」を好む人々にとって、魅力的な選択肢となります。

Blaise

C以外にも、QBEは新しい言語の基盤として使用されています。モダンなObject Pascalの実装であるBlaiseは、QBEをバックエンドとして利用しており、プロジェクトの汎用性が異なるプログラミングパラダイムにわたって示されています。

技術的なトレードオフと制限事項

QBEのミニマリズムは最大の強みですが、それには固有の技術的なトレードオフが伴います。シニア開発者やコンパイラエンジニアは、LLVMのようなより堅牢なシステムよりもQBEを選択する際に考慮すべきいくつかの主要な制限事項を挙げています。

  • ABIと構造体の扱い: QBEは、レジスタを介した構造体の受け渡しや返却のためのABIを扱いますが、スタックへの不要なコピーが頻繁に発生することがあり、これが軽微なパフォーマンスのオーバーヘッドを引き起こす可能性があります。

  • デバッグ情報: データのデバッグ情報を生成することは、現在課題となっています。これは、包括的なアセンブラサポートの欠如、あるいはDWARF形式の極端な複雑さが原因である可能性があります。

  • インライン化と行番号: 行番号のデバッグ情報ディレクティブは、現在ドキュメント化されておらず、インライン化された関数をサポートしていません。そのため、最適化されたコードの深いデバッグはより困難になります。

  • メモリ管理: IRは、GC (Garbage Collection) のルートを特定することをネイティブにサポートしていません。つまり、QBEをターゲットとする言語は、保守的なGCを実装するか、スタックを明示的に管理する必要があります。

シンプルさの魅力

これらの制限事項にもかかわらず、コミュニティはQBEの「smol」な性質を非常に魅力的に感じています。あるユーザーは、拡張が驚くほど簡単であると言及しました。例えば、AIプロンプト(Claude)を介してMIPSサポートを追加することは、カスタム言語をNintendo 64向けにコンパイルすることに成功するほど十分な成果が得られたと報告されています。

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

現代のコンパイラインフラストラクチャの複雑さに疲れた開発者にとって、QBEは、予測可能で使いやすく、かつ小さなツールセットが、ほとんどの専門的なタスクに対して十分なパワーを提供できることを思い出させてくれる存在です。

Sources