GCC(GNU Compiler Collection)是現代最主流的編譯器基礎設施。理解其編譯流程不僅有助於優化建構腳本、診斷編譯錯誤,更是深入掌握編譯原理工程實踐的關鍵。本文以圖解方式拆解 GCC 從原始碼到可執行檔的完整管線。
一條典型指令 gcc main.c -o main 背後經歷 9 個主要階段:
cpp 處理 #include、#define、條件編譯,輸出 .i 檔。.s。as 將組合語言轉為機器碼目標檔 .o。ld 合併多個 .o 及庫檔,解析符號,生成最終可執行檔。| 縮寫 | 全稱 | 角色 |
|---|---|---|
| FE | Front End | 各語言前端(C/C++/Fortran/Go 等),負責步驟 1-4,輸出通用 AST。 |
| GIMPLE | GNU SIMPLE | 三地址碼中間表示,SSA 形式,機器無關優化載體。 |
| SSA | Static Single Assignment | 每個變數只被賦值一次,便於資料流分析。 |
| RTL | Register Transfer Language | 類組合語言的低層中間表示,機器相關優化載體。 |
| BE | Back End | 目標機器後端(x86/ARM/RISC-V 等),負責 RTL 降級、指令生成。 |
以簡單 C 敘述 a = b + c; 為例:
IDENT(a) OP(=) IDENT(b) OP(+) IDENT(c) SEMI(;)
=
/ \
a +
/ \
b c
a,b,c 型別,標記 AST 節點型別屬性。t1 = b + c; a = t1;(引入臨時變數,單賦值形式)。.md 機器描述檔定義)。mul 2 → shl 1)。| 參數 | 停留階段 | 輸出檔案 |
|---|---|---|
-E | 預處理 | .i |
-S | 組合代碼生成 | .s |
-c | 組譯 | .o |
-fdump-tree-gimple | GIMPLE | .c.004t.gimple |
-fdump-rtl-expand | RTL 展開後 | .c.040r.expand |
-O2/-O3 | 啟用優化 | — |
-flto | 啟用 LTO | — |
GCC 編譯流程是「前端統一 → 中間表示多層降級 → 後端機器適配」的教科書級架構。掌握 GIMPLE/SSA/RTL 三大中間表示的角色與轉換鏈路,能讓開發者從「參數調優」進階到「原理優化」,甚至開發自定義編譯器通道或靜態分析工具。