GUN、GCC、LLVM和Clang

Glen2017發表於2018-06-15

GUN

GUN的全稱是GUN’s Not Unix。沒錯,Unix就是經常說到的Unix作業系統。很明顯這裡的意思是要跟Unix槓上了。它其實是一個類Unix作業系統,實現了Unix系統的標準介面,目的就是用來取代Unix作業系統。

1983年,著名的黑客大師理查德·斯托曼提出了一項GUN計劃,內容就是開發一個完全自由、開放原始碼的作業系統,以取代當時的Unix系統(當時的Unix系統是收費的商業軟體,並且只開放了部分原始碼)。這個作業系統就叫GUN,即GUN’s Not Unix的遞迴首字母縮寫。它的LOGO是一頭牛羚:

GUN LOGO

其中有一個理由是“重現當年軟體界合作互助的團結精神”,就是說這份計劃由個人自願無償參與貢獻完成。那個年代開源計劃真的很盛行,程式設計師沒那麼多利益思想,只有一個共同的理想,做一件對人類有益的事,很偉大!向前輩們致敬!

GUN作業系統的核心是Hurd,這個核心至今都沒有完成。這也是GUN被人吐槽最多的地方。但是GUN計劃完成了很多其他的功能,比如編譯器、文字編輯器、shell命令集等等,這些都是非常優秀的軟體工具,得到了廣泛的應用。其中就包括著名的GCC編譯器。

GCC

全稱叫GUN Compile Collection(GUN編譯器套裝),是一套GUN開發的程式語言編譯器。也是許多類Unix系統和MacOS作業系統的標準編譯器。最初GCC只支援C語言,後來擴充套件到C++、Objective-C、Java等其他語言。

GCC和GUN

傳統編譯器是一個三層模型結構,包括前端編譯器、優化器、後端編譯器。前端主要負責原始碼的編譯解析、錯誤檢查以及生成抽象語法樹。優化器主要負責對語法樹的優化,以提高程式碼的執行時間,比如消除冗餘計算等。後端主要負責將優化後的中間程式碼轉成機器碼,這個階段會針對不同的機器架構、指令集優化以提高程式碼的執行效能。

傳統編譯器的三層結構

這個模型可以針對不同的語言開發不用的前端,也可以針對不用的機器架構開發使用不用的後端,只要保證中間程式碼一致,就可以使用同一套通用的優化方案。所以這個結構變成了下面這個樣子:

多語言多架構編譯器方案圖

大多數的直譯器和編譯器都實現了這個模型,比如Java和.net的虛擬機器、G++、GCC等。我們著重說一下GCC,GCC支援了很多前端語言和後端架構,而且是開源的,所以得到了很多編譯器愛好者支援和貢獻。但是它被設計成了一個整體的應用,導致它無法被拆分成單獨的庫來使用,有時候我們只想使用它的某個特性,卻不得不引入整個編譯器程式碼。

這裡面的原因有很多,比如它內部使用了的大量的全域性變數、不合理的資料結構設計、大量的巨集定義以避免重複編譯、程式碼耦合度高、log不清晰不明確等等。

儘管這樣,GCC依然是現在跨平臺軟體編譯器的首選。
複製程式碼

LLVM

LLVM是Low Level Virtual Machine的首字母縮寫。 本來是一個低階別的虛擬機器,但現在它是一種編譯器的基礎程式集合,包括一些LLVM中介碼、LLVM除錯工具等,這個名字已經不能表達它的真實含義了,僅僅是一種沿用名稱而已。它利用虛擬技術(中介碼)為開發語言的編譯期、連結期、執行期以及閒置期提供了優化和改良。它的創始人就是大名鼎鼎的Chris Lattner。LLVM的幾大優勢:

1、良好的架構設計,模組複用性高

2、引入IR(Intermediate Representation)概念,相容性高

3、錯誤和警告資訊提示友好,日誌檔案可讀性強

4、與目標語言和平臺無關

5、與IDE的配合良好

這裡解釋一下IR,LLVM編譯器在傳統的三層模型中加入了中介碼,前端完成原始碼解析編譯後,轉成中介碼,LLVM編譯器針對中介碼進行優化和改良,然後將中介碼送入目標平臺編譯器生成目的碼,整個編譯過程中都是中介碼在參與,所以說跟目標語言和平臺無關。他們的結構如下:

LLVM三層模型圖

Clang

蘋果原來預設的官方編譯器是GCC,隨著蘋果自家的語言Objective-C不斷髮展,加入很多新特性,導致GCC無法滿足蘋果的編譯要求。蘋果希望找到一個高效的、模組化的、與IDE無縫結合的編譯器,於是在2005年請來了Chris Lattner負責他們的編譯器優化。Lattner完全拋棄了GCC,而是從頭開始重新寫了一個前端編譯器就叫Clang。Clang只支援C家族的三門語言C、C++和Objective-C,相比於GCC,Clang的優勢在於速度快、記憶體佔用體積小、模組化、診斷資訊可讀性強、設計清晰擴充套件性強等。

目前蘋果已經將官方的編譯器從GCC改為了Clang+LLVM。

相關文章