GCC(GNU Compiler Collection,GNU編譯(yi)器套件(jian))是由GNU開發的(de)編程語言(yan)譯(yi)器。GNU編譯(yi)器套件(jian)包括C、C++、Objective-C、 Fortran、Java、Ada和Go語言(yan)前端,也包括了這些語言(yan)的(de)庫(如libstdc++,libgcj等。)
GCC的(de)初衷是(shi)為GNU操作系(xi)統專(zhuan)門編寫的(de)一款編譯器。GNU系(xi)統是(shi)徹(che)底(di)的(de)自(zi)由(you)軟件。此處,“自(zi)由(you)”的(de)含義是(shi)它尊重用戶的(de)自(zi)由(you)。
GCC的(de)外部接(jie)口(kou)長得像一(yi)個標準的(de)Unix編(bian)譯器。使用(yong)者在命令列下鍵入gcc之(zhi)程(cheng)序名,以(yi)及一(yi)些命令參數,以(yi)便決定每個輸入檔案使用(yong)的(de)個別(bie)語言編(bian)譯器,并為輸出程(cheng)序碼使用(yong)適(shi)合此硬(ying)件平臺的(de)組合語言編(bian)譯器,并且選擇性地(di)執行連接(jie)器以(yi)制造可執行的(de)程(cheng)序。
每(mei)個語(yu)(yu)言(yan)編(bian)譯(yi)器都(dou)是(shi)獨(du)立程(cheng)序,此程(cheng)序可處理輸入的(de)原始(shi)碼(ma),并輸出(chu)組合(he)語(yu)(yu)言(yan)碼(ma)。全(quan)部(bu)的(de)語(yu)(yu)言(yan)編(bian)譯(yi)器都(dou)擁有共(gong)通的(de)中介架構:一個前端解(jie)析(xi)符合(he)此語(yu)(yu)言(yan)的(de)原始(shi)碼(ma),并產(chan)生一抽象語(yu)(yu)法樹,以(yi)及一翻譯(yi)此語(yu)(yu)法樹成為GCC的(de)暫存器轉換語(yu)(yu)言(yan)〈RTL〉的(de)后端。編(bian)譯(yi)器最佳化(hua)與靜態程(cheng)序碼(ma)解(jie)析(xi)技(ji)術(例如(ru)FORTIFY_SOURCE,一個試圖發現緩沖區溢位〈buffer overflow〉的(de)編(bian)譯(yi)器)在(zai)此階(jie)段應用(yong)于(yu)程(cheng)序碼(ma)上。最后,適用(yong)于(yu)此硬件架構的(de)組合(he)語(yu)(yu)言(yan)程(cheng)序碼(ma)以(yi)Jack Davidson與Chris Fraser發明(ming)的(de)算法產(chan)出(chu)。
幾(ji)乎全部的GCC都由C寫(xie)成,除了Ada前端大部分以Ada寫(xie)成。
前端的功(gong)能在于(yu)產(chan)生一個(ge)可讓后(hou)端處理之(zhi)語法(fa)樹(shu)。此語法(fa)解析器(qi)是手寫之(zhi)遞歸語法(fa)解析器(qi)。
直到2004年,程序的(de)語法(fa)樹(shu)結構(gou)(gou)尚無法(fa)與欲產出的(de)處理器(qi)架構(gou)(gou)脫鉤(gou)。而語法(fa)樹(shu)的(de)規則有(you)時(shi)在(zai)不同的(de)語言前(qian)端也(ye)不一樣,有(you)些前(qian)端會提供它們特別的(de)語法(fa)樹(shu)規則。
在(zai)2005年,兩種與(yu)語(yu)(yu)(yu)言(yan)脫鉤(gou)的(de)(de)(de)(de)(de)新(xin)型態語(yu)(yu)(yu)法樹納(na)入GCC中。它們稱為GENERIC與(yu)GIMPLE。語(yu)(yu)(yu)法解(jie)析變(bian)成產生(sheng)與(yu)語(yu)(yu)(yu)言(yan)相關的(de)(de)(de)(de)(de)暫時語(yu)(yu)(yu)法樹,再將它們轉成GENERIC。之(zhi)后再使(shi)用(yong)"gimplifier"技術降低GENERIC的(de)(de)(de)(de)(de)復雜(za)結構,成為一(yi)較簡單的(de)(de)(de)(de)(de)靜態唯一(yi)形式(shi)(Static Single Assignment form,SSA)基礎的(de)(de)(de)(de)(de)GIMPLE形式(shi)。此形式(shi)是一(yi)個(ge)與(yu)語(yu)(yu)(yu)言(yan)和處(chu)理(li)器架構脫鉤(gou)的(de)(de)(de)(de)(de)全域最佳(jia)化通(tong)用(yong)語(yu)(yu)(yu)言(yan),適用(yong)于大多數的(de)(de)(de)(de)(de)現代編程語(yu)(yu)(yu)言(yan)。
一般編譯(yi)器作者會將語(yu)法樹的最(zui)佳化(hua)放在前端,但(dan)其實此步(bu)驟并不看語(yu)言(yan)的種類而(er)有不同,且不需要用到語(yu)法解(jie)析器。因(yin)此GCC作者們將此步(bu)驟歸入通稱(cheng)為中介階段的部分里(li)。此類的最(zui)佳化(hua)包括消解(jie)死碼、消解(jie)重復(fu)運(yun)算(suan)與全域數值重編碼等(deng)。許多最(zui)佳化(hua)技(ji)巧也(ye)正在實作中。
GCC后(hou)端的(de)(de)行(xing)為(wei)因不(bu)同的(de)(de)前(qian)處理器宏和特定(ding)架(jia)構的(de)(de)功能而不(bu)同,例如(ru)不(bu)同的(de)(de)字符尺(chi)寸、呼叫方式(shi)與大小(xiao)尾序等。后(hou)端接口的(de)(de)前(qian)半部利用這些(xie)訊息決定(ding)其(qi)RTL的(de)(de)生成形式(shi),因此(ci)雖然GCC的(de)(de)RTL理論上不(bu)受處理器影響(xiang),但在此(ci)階段(duan)其(qi)抽象指令已被轉換(huan)成目(mu)標(biao)架(jia)構的(de)(de)格式(shi)。
GCC的最(zui)佳化(hua)技(ji)巧依其釋(shi)出版本(ben)而有很大不同,但(dan)都包含(han)了標(biao)準的最(zui)佳化(hua)算法(fa),例如(ru)循環最(zui)佳化(hua)、執(zhi)行緒(xu)跳躍、共通(tong)程(cheng)序子句消減、指令排程(cheng)等等。而RTL的最(zui)佳化(hua)由于可用(yong)的情形(xing)較(jiao)(jiao)少(shao),且缺乏較(jiao)(jiao)高(gao)階的資(zi)訊,因此相比較(jiao)(jiao)起來,增加的GIMPLE語法(fa)樹形(xing)式,便顯得比較(jiao)(jiao)不重要。
后端經(jing)由一次重(zhong)讀取(qu)步驟后,利(li)用描述目標處(chu)理(li)器(qi)的(de)指(zhi)令(ling)集時所(suo)取(qu)得的(de)信(xin)息,將抽象暫存器(qi)替換成處(chu)理(li)器(qi)的(de)真實暫存器(qi)。此階段非常復雜,因為它(ta)必須關(guan)注所(suo)有GCC可移植平臺的(de)處(chu)理(li)器(qi)指(zhi)令(ling)集的(de)規格與技(ji)術(shu)細節。
后(hou)端的(de)(de)最后(hou)步驟相當公式(shi)化,僅僅將前一階(jie)段得到的(de)(de)匯編語言代碼(ma)藉由簡(jian)單的(de)(de)子例程轉換其暫存器與內存位置成相對應的(de)(de)機器碼(ma)。
以2006年5月24日釋出的4.1.1版為(wei)準,本編譯(yi)器(qi)版本可處理(li)下列(lie)語言:
Ada〈GNAT〉
C〈GCC〉
C++(G++)
Fortran〈Fortran77:G77,Fortran90:GFORTRAN〉
Java〈編譯器:GCJ;解(jie)釋(shi)器:GIJ〉
Objective-C〈GOBJC〉
Objective-C++
先前(qian)版本納(na)入的(de)CHILL前(qian)端由于缺乏維護而被廢棄。
Fortran前(qian)端在(zai)4.0版(ban)之前(qian)是G77,此前(qian)端僅支援Fortran77。在(zai)本版(ban)本中,G77被(bei)廢棄而(er)采用(yong)更新的GFortran,因為(wei)此前(qian)端支援Fortran95。
下列(lie)前(qian)端(duan)依然(ran)存在:
Modula-2
Modula-3
Pascal
PL/I
D語言
Mercury
VHDL