LLVM和GCC的區別(LLVM提供了模塊化的編譯模塊,很是有利於重用,之前的編譯器都沒有作到這一點)

最近在Mac OS X Mountain Lion下用Xcode進行開發,發如今編譯選項裏有以下所示的這兩種編譯器:一個是Apple LLVM compiler 4.2,另一個是LLVM GCC 4.2。html

近幾年一直聽人說LLVM比GCC好,可是我一直沒有時間研究這兩者的差異。由此問題出發,我又給本身拋出了不少疑問:前端

  • cc, c89, c99是什麼?有何區別?
  • gcc, g++, cpp, gpp又是什麼?
  • LLVM與GCC區別大嗎?
  • Apple LLVM compiler 4.2和LLVM GCC 4.2有何區別?
  • LLVM GCC 4.2究竟是LLVM仍是GCC?

接下來讓咱們一塊兒補補歷史課。算法

CC, C89, C99

Unix誕生以後,不少公司都開發了本身的Unix系統而且使用了本身專門的編譯器。這樣就致使在不一樣的Unix系統上,想編譯C語言代碼就須要使用不一樣的命令。因而POSIX標準Commands and Utilities中就規定了將CC做爲不一樣編譯器的統一命令接口,而且也規定了CC命令須要提供哪些必須的參數。後端

隨着後續ISO C標準的肯定,POSIX標準又規定分別將C89C99做爲ISO C的接口,而CC則繼續做爲非標準C的接口。但實際上後續大多數C語言編譯器都實現了ISO C標準,因此POSIX標準規定後續應將CC這一歷史遺留的命令取消。架構

GCC, G++, CPP, GPP

隨着開源運動的興起,自由軟件基金會開發了本身的開源免費的C語言編譯器GNU C Compiler,簡稱GCC。GCC中提供了C Preprocessor這個C語言的預處理器,簡稱CPP。後來GCC又加入了對C++等其它語言的支持,因此他的名字也改成GNU Compiler Collection。G++則是專門用來處理C++語言的。在GNU的官方手冊中,有一個章節叫作G++ and GCC介紹了這兩者的區別。G++是GCC編譯器集合的一個前端。關於前端、後端的概念下面有更詳細的介紹。而GPP呢,這個名字比較特殊,若是你用的是Linux系統,可能並無這個命令。可是在某些特殊的系統下,例如DOS,是沒法建立G++這樣帶有特殊符號的文件名的。因此按照DJGPP編譯器的作法,GPP其實就是G++。post

LLVM與GCC

回顧GCC的歷史,雖然它取得了巨大的成功,但開發GCC的初衷是提供一款免費的開源的編譯器,僅此而已。可後來隨着GCC支持了愈來愈多的語言,GCC架構的問題也逐漸暴露出來。但GCC到底有什麼問題呢?咱們一塊兒看看這篇文章:The Architecture of Open Source Applications: LLVM。LLVM的優勢也正是GCC的缺點。性能

傳統編譯器

傳統編譯器的工做原理基本上都是三段式的,能夠分爲前端(Frontend)、優化器(Optimizer)、後端(Backend)。前端負責解析源代碼,檢查語法錯誤,並將其翻譯爲抽象的語法樹(Abstract Syntax Tree)。優化器對這一中間代碼進行優化,試圖使代碼更高效。後端則負責將優化器優化後的中間代碼轉換爲目標機器的代碼,這一過程後端會最大化的利用目標機器的特殊指令,以提升代碼的性能。優化

事實上,不光靜態語言如此,動態語言也符合上面這個模型,例如Java。Java Virtual Machine也利用上面這個模型,將Java代碼翻譯爲Java bytecode。翻譯

這一模型的好處是,當咱們要支持多種語言時,只須要添加多個前端就能夠了。當須要支持多種目標機器時,只須要添加多個後端就能夠了。對於中間的優化器,咱們可使用通用的中間代碼。code

這種三段式的結構還有一個好處,開發前端的人只須要知道如何將源代碼轉換爲優化器可以理解的中間代碼就能夠了,他不須要知道優化器的工做原理,也不須要了解目標機器的知識。這大大下降了編譯器的開發難度,使更多的開發人員能夠參與進來。

雖然這種三段式的編譯器有不少有點,而且被寫到了教科書上,可是在實際中這一結構卻歷來沒有被完美實現過。作的比較好的應該屬Java和.NET虛擬機。虛擬機能夠將目標語言翻譯爲bytecode,因此理論上講咱們能夠將任何語言翻譯爲bytecode,而後輸入虛擬機中運行。可是這一動態語言的模型並不太適合C語言,因此硬將C語言翻譯爲bytecode並實現垃圾回收機制的效率是很是低的。

GCC也將三段式作的比較好,而且實現了不少前端,支持了不少語言。可是上述這些編譯器的致命缺陷是,他們是一個完整的可執行文件,沒有給其它語言的開發者提供代碼重用的接口。即便GCC是開源的,可是源代碼重用的難度也比較大。

LLVM

LLVM最初是Low Level Virtual Machine的縮寫,定位是一個虛擬機,可是是比較底層的虛擬機。它的出現正是爲了解決編譯器代碼重用的問題,LLVM一上來就站在比較高的角度,制定了LLVM IR這一中間代碼表示語言。LLVM IR充分考慮了各類應用場景,例如在IDE中調用LLVM進行實時的代碼語法檢查,對靜態語言、動態語言的編譯、優化等。

從上面這個圖中咱們發現LLVM與GCC在三段式架構上並無本質區別。LLVM與其它編譯器最大的差異是,它不只僅是Compiler Collection,也是Libraries Collection。舉個例子,假如說我要寫一個XYZ語言的優化器,我本身實現了PassXYZ算法,用以處理XYZ語言與其它語言差異最大的地方。而LLVM優化器提供的PassA和PassB算法則提供了XYZ語言與其它語言共性的優化算法。那麼我能夠選擇XYZ優化器在連接的時候把LLVM提供的算法連接進來。LLVM不只僅是編譯器,也是一個SDK。

Apple LLVM compiler 4.2和LLVM GCC 4.2

如今咱們能夠回答本文最前面我遇到的那個問題了。Apple LLVM compiler 4.2是一個真正的LLVM編譯器,前端使用的是Clang,基於最新的LLVM 3.2編譯的。LLVM GCC 4.2編譯器的核心仍然是LLVM,可是前端使用的是GCC 4.2編譯器。從LLVM的下載頁面能夠看出,LLVM從1.0到2.5使用的都是GCC做爲前端,直到2.6開始才提供了Clang前端。

http://www.cnblogs.com/zuopeng/p/4141467.html

相關文章
相關標籤/搜索