GCC(GNU Compiler Collection,,GNU編譯器套件)是由GNU開發(fā)的編程語言譯器。GNU編譯器套件包括C,、C++,、Objective-C、 Fortran,、Java,、Ada和Go語言前端,也包括了這些語言的庫(如libstdc++,,libgcj等,。)
GCC的初衷是為GNU操作系統(tǒng)專門編寫的一款編譯器。GNU系統(tǒng)是徹底的自由軟件,。此處,,“自由”的含義是它尊重用戶的自由。
GCC的外部接口長得像一個標準的Unix編譯器,。使用者在命令列下鍵入gcc之程序名,,以及一些命令參數(shù),以便決定每個輸入檔案使用的個別語言編譯器,,并為輸出程序碼使用適合此硬件平臺的組合語言編譯器,,并且選擇性地執(zhí)行連接器以制造可執(zhí)行的程序。
每個語言編譯器都是獨立程序,,此程序可處理輸入的原始碼,,并輸出組合語言碼。全部的語言編譯器都擁有共通的中介架構:一個前端解析符合此語言的原始碼,,并產(chǎn)生一抽象語法樹,,以及一翻譯此語法樹成為GCC的暫存器轉換語言〈RTL〉的后端。編譯器最佳化與靜態(tài)程序碼解析技術(例如FORTIFY_SOURCE,,一個試圖發(fā)現(xiàn)緩沖區(qū)溢位〈buffer overflow〉的編譯器)在此階段應用于程序碼上,。最后,適用于此硬件架構的組合語言程序碼以Jack Davidson與Chris Fraser發(fā)明的算法產(chǎn)出,。
幾乎全部的GCC都由C寫成,,除了Ada前端大部分以Ada寫成,。
前端的功能在于產(chǎn)生一個可讓后端處理之語法樹,。此語法解析器是手寫之遞歸語法解析器,。
直到2004年,程序的語法樹結構尚無法與欲產(chǎn)出的處理器架構脫鉤,。而語法樹的規(guī)則有時在不同的語言前端也不一樣,,有些前端會提供它們特別的語法樹規(guī)則。
在2005年,,兩種與語言脫鉤的新型態(tài)語法樹納入GCC中,。它們稱為GENERIC與GIMPLE,。語法解析變成產(chǎn)生與語言相關的暫時語法樹,,再將它們轉成GENERIC。之后再使用"gimplifier"技術降低GENERIC的復雜結構,,成為一較簡單的靜態(tài)唯一形式(Static Single Assignment form,,SSA)基礎的GIMPLE形式。此形式是一個與語言和處理器架構脫鉤的全域最佳化通用語言,,適用于大多數(shù)的現(xiàn)代編程語言。
一般編譯器作者會將語法樹的最佳化放在前端,但其實此步驟并不看語言的種類而有不同,,且不需要用到語法解析器。因此GCC作者們將此步驟歸入通稱為中介階段的部分里,。此類的最佳化包括消解死碼,、消解重復運算與全域數(shù)值重編碼等。許多最佳化技巧也正在實作中,。
GCC后端的行為因不同的前處理器宏和特定架構的功能而不同,,例如不同的字符尺寸、呼叫方式與大小尾序等。后端接口的前半部利用這些訊息決定其RTL的生成形式,,因此雖然GCC的RTL理論上不受處理器影響,,但在此階段其抽象指令已被轉換成目標架構的格式,。
GCC的最佳化技巧依其釋出版本而有很大不同,但都包含了標準的最佳化算法,例如循環(huán)最佳化,、執(zhí)行緒跳躍、共通程序子句消減,、指令排程等等,。而RTL的最佳化由于可用的情形較少,,且缺乏較高階的資訊,,因此相比較起來,增加的GIMPLE語法樹形式,,便顯得比較不重要,。
后端經(jīng)由一次重讀取步驟后,利用描述目標處理器的指令集時所取得的信息,,將抽象暫存器替換成處理器的真實暫存器,。此階段非常復雜,因為它必須關注所有GCC可移植平臺的處理器指令集的規(guī)格與技術細節(jié),。
后端的最后步驟相當公式化,,僅僅將前一階段得到的匯編語言代碼藉由簡單的子例程轉換其暫存器與內(nèi)存位置成相對應的機器碼。
以2006年5月24日釋出的4.1.1版為準,,本編譯器版本可處理下列語言:
Ada〈GNAT〉
C〈GCC〉
C++(G++)
Fortran〈Fortran77:G77,Fortran90:GFORTRAN〉
Java〈編譯器:GCJ,;解釋器:GIJ〉
Objective-C〈GOBJC〉
Objective-C++
先前版本納入的CHILL前端由于缺乏維護而被廢棄。
Fortran前端在4.0版之前是G77,,此前端僅支援Fortran77,。在本版本中,G77被廢棄而采用更新的GFortran,,因為此前端支援Fortran95,。
下列前端依然存在:
Modula-2
Modula-3
Pascal
PL/I
D語言
Mercury
VHDL