探索 QBE:輕量級的 LLVM 替代方案

構建編譯器常被視為系統程式設計中最艱巨的任務。多年來,業界高度依賴 LLVM,它已成為提供強大優化與廣泛架構支援的強力引擎。然而,對許多開發者而言,LLVM 的複雜度與編譯時間開銷過於龐大。於是 QBE 應運而生,它是一個小巧、可預測且高效的編譯器後端,旨在成為更精簡的替代方案。

QBE 是什麼?

QBE 是一個編譯器後端,接受特定的中間表示(IR)並為各種架構產生機器碼。與 LLVM 採用龐大的優化套件與複雜的靜態單賦值(SSA)形式以及顯式的 phi 節點不同,QBE 追求簡潔。它為語言實作者提供了一種方式,讓他們能夠針對機器碼,而不必為每個架構自行編寫組合語生成器。

生態系統:從 cproc 到 Blaise

QBE 最引人注目的面向之一是其上方衍生出的小而專注的工具與語言生態系統。由於 QBE 如此輕量,它成為實驗性或極簡編譯器的絕佳目標。

cproc

cproc 是在 QBE 之上實作的 C 編譯器。使用者指出,結合 QBE 後,cproc 能夠達到大約 gcc -O2 效能的 70%,而程式碼大小僅為其一小部分。這使得它對於那些偏好「純粹且簡單的 C 程式碼編譯器」而非 GCC 或 LLVM 那龐大代碼基礎的開發者具有吸引力。

Blaise

除了 C 之外,QBE 也被用於驅動較新的語言。Blaise 作為現代的 Object Pascal 實作,使用 QBE 作為其後端,展示了該專案在不同程式範式間的多樣性。

技術取捨與限制

雖然 QBE 的極簡主義是其最大優勢,但也伴隨著固有的技術取捨。資深開發者與編譯器工程師指出了若在 LLVM 等更完整系統之上選擇 QBE 時必須考慮的幾項關鍵限制:

  • ABI 與結構處理: QBE 處理傳遞與返回結構於暫存器的 ABI,但常會額外將資料複製至堆疊或從堆疊複製回來,可能導致輕微的效能開銷。
  • 除錯資訊: 產生資料的除錯資訊目前仍是挑戰。這可能是因為缺乏完整的組譯器支援,或 DWARF 格式本身的極度複雜所致。
  • 內聯與行號: 行號除錯資訊指令目前未有文件說明,且不支援內聯函式,使得對最佳化程式碼的深入除錯更加困難。
  • 記憶體管理: IR 本身不支援辨識 GC(垃圾回收)根。這意味著以 QBE 為目標的語言必須自行實作保守式 GC,或明確管理堆疊。

簡潔的吸引力

儘管有這些限制,社群仍認為 QBE 那「smol」的特性相當吸引人。某位使用者提到,它的擴充性極佳;例如,透過 AI 提示(Claude)加入 MIPS 支援,據說已足以將自訂語言編譯至 Nintendo 64。

"但它很小巧、高效,且不需要你處理 phi 節點!"

對於厭倦現代編譯器基礎設施複雜性的開發者而言,QBE 提醒我們,可預測、易用且小型的工具組合足以提供大多數專門任務所需的足夠功能。

Sources