天天看點

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

LLVM 與 Clang 介紹

{ 撰文/guest }

來源:http://linuxtoy.org/archives/llvm-and-clang.html

LLVM 是 Low Level Virtual Machine 的簡稱,這個庫提供了與編譯器相關的支援,能夠進行程式語言的編譯期優化、連結優化、線上編譯優化、代碼生成。簡而言之,可以作為多種語言編譯器的背景來使用。如果這樣還比較抽象的話,介紹下 Clang 就知道了:Clang 是一個 C++ 編寫、基于 LLVM、釋出于 LLVM BSD 許可證下的 C/C++/Objective C/Objective C++ 編譯器,其目标(之一)就是超越 GCC。

Clang 開發事出有因,Wiki 介紹如下:

Apple 使用 LLVM 在不支援全部 OpenGL 特性的 GPU (Intel 低端顯示卡) 上生成代碼 (JIT),令程式仍然能夠正常運作。之後 LLVM 與 GCC 的內建過程引發了一些不快,GCC 系統龐大而笨重,而 Apple 大量使用的 Objective-C 在 GCC 中優先級很低。此外 GCC 作為一個純粹的編譯系統,與 IDE 配合很差。加之許可證方面的要求,Apple 無法使用修改版的 GCC 而閉源。于是 Apple 決定從零開始寫 C family 的前端,也就是基于 LLVM 的 Clang 了。

Clang 的特性:

  1. 快:通過編譯 OS X 上幾乎包含了所有 C 頭檔案的 carbon.h 的測試,包括預處理 (Preprocess),文法 (lex),解析 (parse),語義分析 (Semantic Analysis),抽象文法樹生成 (Abstract Syntax Tree) 的時間,Clang 是 Apple GCC 4.0 的 2.5x 快。(2007-7-25)
  2. 記憶體占用小:Clang 記憶體占用是源碼的 130%,Apple GCC 則超過 10x。
  3. 診斷資訊可讀性強:我不會排版,推薦去網站觀看。其中錯誤的文法不但有源碼提示,還會在錯誤的調用和相關上下文的下方有~~~~~和^的提示,相比之下 GCC 的提示很天書。
  4. GCC 相容性。
  5. 設計清晰簡單,容易了解,易于擴充增強。與代碼基礎古老的 GCC 相比,學習曲線平緩。
  6. 基于庫的子產品化設計,易于 IDE 內建及其他用途的重用。由于曆史原因,GCC 是一個單一的可執行程式編譯器,其内部完成了從預處理到最後代碼生成的全部過程,中間諸多資訊都無法被其他程式重用。Clang 将編譯過程分成彼此分離的幾個階段,AST 資訊可序列化。通過庫的支援,程式能夠擷取到 AST 級别的資訊,将大大增強對于代碼的操控能力。對于 IDE 而言,代碼補全、重構是重要的功能,然而如果沒有底層的支援,隻使用 tags 分析或是正規表達式比對是很難達成的。

當然,GCC 也有其優勢:

  • 支援 JAVA/ADA/FORTRAN
  • 目前的 Clang 的 C++ 支援落後于 GCC,參見 http://clang.llvm.org/cxx_status.html。(近日 Clang 已經可以自編譯,見 http://www.phoronix.com/scan.php?page=news_item&px=Nzk2Mw)
  • GCC 支援更多平台
  • GCC 更流行,廣泛使用,支援完備
  • GCC 基于 C,不需要 C++ 編譯器即可編譯

相信介紹到這裡大家能夠對 Clang 和 LLVM 有所了解了。除去 Clang 之外,LLVM 還被用在 Gallium3D 中進行 JIT 優化,Xorg 中的 pixman 也有考慮使用 LLVM 來優化執行速度,llvm-lua 使用 LLVM 來編譯 Lua 代碼,gpuocelot 使用 LLVM 可以令 CUDA 程式無需重新編譯即可運作在多核 X86CPU、IBM Cell、支援 OpenCL 的裝置之上... 我個人感覺 Apple 在開源界口碑較差(也許是我的錯覺?),不過 Apple 也為開源界貢獻了不少,Webkit,OpenCL(雖說隻是個标準),Clang。我最為佩服的是雖然出身于指令行之上的 Unix 族系統,但有魄力寫出自成體系的圖形棧,其圖形界面優美而人性化,可謂也為開源界貢獻了自己的精神與思想。對于 Clang 這個很有潛力的項目,我希望其 C++ 支援(尤其是 template 支援)能夠早日完善。因為 GCC 在 template 出錯時的診斷資訊如同小說一般...

{ Thanks guest. }

雪豹的心髒:LLVM和Clang

來源:http://news.weiphone.com/news/apple/blog/2009-09-27/xuebaodexinzangLLVMheClang_206356.shtml

     Mac OS X 10.6即所謂的Snow Leopard作業系統已正式發售。一如既往,Apple産品光鮮的外表下凝聚了太多艱辛的勞作。ArsTechnic的John Siracusa以其獨特的、專業的、全面的視角深入翔實地體驗這款最新的作業系統。   

      Weiphone.com将對該綜述進行翻譯整理并獨家連載。歡迎關注。

譯注:為了幫助您更加順暢地了解本文的内容,這裡補充了文中一些相關概念的背景資料。

       編譯器(compiler):是一種能夠将源代碼(通常由進階别的程式語言編寫而成)轉換為低級别機器語言的程式。源碼轉換最重要的一個目的在于建立可執行檔案。 詳情請參考wikipedia。

       LLVM(Low Level Virtual Machine,低級虛拟機):是構架編譯器(compiler)的架構系統,以C++編寫而成,用于優化以任意程式語言編寫的程式的編譯時間(compile-time)、連結時間(link-time)、運作時間(run-time)以及空閑時間(idle-time),對開發者保持開放,并相容已有腳本。LLVM計劃啟動于2000年,最初由University of Illinois at Urbana-Champaign的Chris Lattner主持開展。2006年Chris Lattner加盟Apple Inc.并緻力于LLVM在Apple開發體系中的應用。Apple也是LLVM計劃的主要資助者。 詳情請參考llvm.org以及 wikipedia。

       GCC(GNU Compiler Collection,縮寫為GCC):是GNU計劃推出的支援多種程式語言的編譯器系統。GCC是GNU Toolchain的主要元件。同時作為GNU作業系統的官方編譯器,GCC已被作為很多現代作業系統的标準編譯器,如GNU/Linux,BSD以及Mac OS X;同時也可用于很多嵌入式平台,如Symbian,AMCC等;還可用于一些遊戲機平台如Playstation和Sega Dreamcast等。 詳情請參閱Wikipedia以及 GCC.GNU.org。

       IDE(Integrated development environment):是一種能夠為程式員和軟體開發提供廣泛支援的軟體程式。IDE通常由源碼編輯器、編譯器、自動化建構工具以及調試器組成。 詳情請參閱Wikipedia。  

      早在幾年以前,Apple就在LLVM開源計劃上做出了重要的戰略性投資。我曾在一篇介紹Mac OS X Leopard的文章中簡要介紹了LLVM的一些基本情況,Leopard利用LLVM技術為JIT編譯軟體的OpenGL功能提供了高效的執行支援。在那篇綜述的最後,我這樣結尾:對于LLVM,Apple擁有相當宏偉的計劃:逐漸摒棄Mac OS X中現有的GCC編譯器集合(complier collection),并采用全新的基于LLVM的編譯器系統。該計劃稱為"Clang",并且已有了一些可喜的進展。                 随着Snow Leopard的推出,這一切開始逐漸浮出水面:Clang和LLVM已成為Apple現行的編譯政策。LLVM甚至還有一個全新的帥氣的标志:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      目前,Apple為Mac OS X總共提供了四種編譯器:GCC 4.0,GCC4.2,LLVM-GCC 4.2,以及Clang。這裡是一個圖表:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      所有這些編譯器在Mac OS X上均具有二進制相容性(binary-compatible),這就意味着您可以使用一種編譯器建立一個資源庫并與使用另一個編譯器建立的可執行檔案相連結。并且,理論上講,這些都是指令行編輯器并且都具有資源相容性。然而,Clang目前暫不支援GCC的一些複雜功能,同時Clang隻支援C、Objective-C和一點點C++(而GCC支援的相對較多)。Apple承諾,Clang未來将會為C++提供全方位支援,并且希望能夠在Snow Leopard的“服役期間”内解決GCC的不相容問題。

      Apple為Clang帶來了兩條引人注目的特性,那就是:更短的編譯時間和更快的可執行檔案。Apple用其自身的軟體如iCal,Address Book,Xcode,以及一些第三方軟體如Adium和Growl進行了測試,Clang編譯器比GCC4.2快了近乎3倍。而對于編譯的可執行檔案運作速度,由Clang生成的可執行檔案則比GCC 4.2生成的可執行檔案快5~25%。

      同時,與其前任GCC相比,Clang提供了更為友好的開發環境。我承認這和多核CPU等新技術的優勢并無很大關聯,但這确實開發者在使用Clang時首先面對的。

      對于新手來說,Clang具有可嵌入性,是以Xcode可以在IDE的一些互動功能中使用和最終的可執行檔案相同的編譯器結構。在編譯過程中,Clang建立并保留了大量詳細的中繼資料(metadata),進而有利于調試和錯誤報告。例如,如果GCC傳回如下錯誤:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      這時候很難說清問題究竟在哪,對于程式設計新手來說尤為如此。好吧,牛人或許已經看出來問題在哪了(如果您在WWDC上看到了這個例子的話),但是我相信大家都會認為Clang傳回的錯誤報告更有用:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

       可能個别菜鳥仍然不知所措,但是至少可以清晰地看到問題究竟出在哪裡了:與GCC含糊其辭的回應相比,Clang明明白白告訴你,哥們兒我不認識“NSString”這個類型… 

       而且,有時候即使錯誤資訊很明确,具體細節卻未必如此,譬如GCC傳回的這個錯誤提示:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      很明顯,“無效的運算符号+”,但是這條語句中有4個“+”,究竟哪一個有問題呢?多虧這些相近的中繼資料(metadata),Clang可以明确地為您指出問題所在:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      更進一步擡杠。有時候錯誤一目了然,譬如這個GCC的例子,在報錯行以上的語句中丢失了一個分号“;”:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      而Clang則更進一步,指出了究竟哪裡丢失了這個分号:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      樓下同學說了,這些都是“小事兒”,完全是雞蛋裡頭挑骨頭沒事兒找事兒,然而對于程式員來說,Clang提供的這種更為細緻和細心的提示是相當貼心的。當然,還有一些細節對于程式員來說則意義重大了,譬如這個基于LLVM的靜态分析器(static analyzer)。下圖顯示了靜态分析器發現并指出了一處可能的bug:

[轉] 編譯器Clang介紹雪豹的心髒:LLVM和Clang

      圖中高亮的部分明确地指出了任何一位程式員都有可能犯的bug。靜态分析器檢測到,這一系列嵌套條件中,“myName”變量在至少一條路徑裡中未被初始化,進而使得在最後一行發送“mutableCopy”時存在潛在的危險。

      我相信Apple一定在其所有應用程式和作業系統上運作過靜态分析器,以檢查一些潛在的bug。而對程式員來說,能夠在龐大的代碼庫中自動監測潛在的bug,無疑是一件非常爽的事情,對于自己開發平台的程式員來說更是如此。某種程度上來講,Mac OS X 10.6.0中存在的bug比先前的任何一個10.x.0系統的bug都要少,無疑這将歸功于LLVM。

      通過Clang/LLVM的進一步推廣和完善,Apple終于能夠完全掌控其自己的開發平台了。CodeWarrior的經驗顯然使Apple更加清晰地認識到,依賴于第三方平台開發工具是相當不明智的。盡管花費了許多年的時間,但我認為即使最頑固的Metrowerks支援者也會認為,Snow Leopard提供的Xcode确實是個相當不錯的IDE。

      許多年以來Apple一直糾結于GCC計劃與Apple自身的編譯需求之間的脫節,現在Apple終于痛下決心另辟蹊徑。誠然,GCC 4.2仍然是Snow Leopard的預設編譯器,但是很顯然Apple已進入的過渡期。Clang自然是推薦的編譯器,并且在可預見的将來,Apple的焦點将集中于此。 llvm/clang将把FreeBSD帶向何方? 來源: http://www.linuxsir.org/bbs/thread353921.html 對于FreeBSD最近的發展,最引人注目、最讓人有所期待、最讓人遐想的就是在将來的某個版本裡将引入llvm/clang。這是一個什麼東西?為什麼值得期待?請聽我慢慢地扯。

llvm/clang是一個編譯器,llvm是類似虛拟機的東西( www.llvm.org),這個虛拟機不是類似java或者說python的VM,llvm的目的不是運作而是編譯生成代碼。也就是說這個llvm是編譯器的後端。clang呢,( clang.llvm.org)簡單來說就是llvm一個C語言家族的前端,它的責任就是把C家族語言翻譯成llvm認識的中間代碼,然後再由llvm後端生成具體架構的彙編代碼,最後由系統中的彙編器、連接配接器生成某一個架構下的可執行檔案。

說實話,任何編譯器不都是這個套路嗎?分前端後端,代碼生成,也許還有代碼優化, llvm到底有什麼不同?最主要的是llvm提供的是函數庫,一組較好定義的接口,使得編譯器前端的設計相當的傻瓜。我們可以為Perl寫一個llvm的前端,它就可以把perl腳本編譯成本地二進制代碼運作;給python寫個前端,它一樣可以編譯。不要以為這個前端有多麼的複雜,通過llvm比較合理的接口,這個工作不是很難。

是以總得來說llvm/clang的架構要優于GCC的架構(其實寫個GCC的語言前端也不是什麼大事,但是你必須了解GCC内部的機制和細節,并不能像llvm那樣調用幾個庫函數就把事情給搞定。),就因為這個優勢,FreeBSD準備遷移到llvm/clang上面。怎麼可能? 不要太天真了。一個龐大的作業系統要遷移到另外一個還在開發之中的編譯器上,不是一件容易的事情。這麼做的原因其實是GNU把後續開發的GCC變成GPLv3了,BSD的人本來就對GPL不感冒,這個V3影響到了使用FreeBSD做商業運作的公司的核心利益。其實如果使用FreeBSD的商業公司願意對FreeBSD貢獻一下力量的話(确實已經貢獻了不少力量),llvm/clang不用多久就可以引入FreeBSD的base,而且llvm/clang本身還能有長足的發展。但是人嘛,總是隻想得到不想付出的,商業公司做事的唯一考量就是做這件事情有沒有利益。是以llvm/clang要真正實用不是近期的事情,雖然FreeBSD的svn中有了clangbsd這個項目。

有人也曾經提出一個Unix的source base裡面隻能有C語言寫的程式,是以FreeBSD隻需要PCC( http://pcc.ludd.ltu.se/)。PCC也是一個老壺裝新酒的編譯器,它是UNIX的research版本的編譯器,後來有人重新修改、重寫了一遍,變成一個經典的分2個pass的C編譯器,并支援C99标準。這個沒有能進入FreeBSD其實一方面是在目前的工業界是回避不了C++的(llvm/clang是使用C++寫的,clang對C++的全面的支援是一定的,不然clang自己都不能bootstrap啊。),除非做個理想的作業系統如Plan9那樣,設計的好不好,當然好,就是20多年還沒有被大衆接受。要讓一個Unix系統中隻用C語言就像讓現在的中國走社會主義道路一樣,好不好?當然好,就是現實做不到。第二個方面用PCC編譯FreeBSD的事情沒有人肯去做,我也在mailling list上呼籲過,說什麼可以使用PCC啊,多麼經典啊,多麼簡單啊,自己就是不想去修改一個Makefile,不想去檢視一行代碼。嗨。。人嘛,就設個本性,牛都是要吹的,事情最好都人家做。(BTW:一直想修改FreeBSD的msdosfs讓其支援UTF-8的中文檔案名的,就是一直沒做,其實是想等别人來做或者允許我找個借口--忙啊!!囧)

革命呢,還是要充滿樂觀主義情緒的,是以我相信llvm/clang最終會進入FreeBSD的base。那個時候我們剛裝完FreeBSD後,第一個要幹的事情是到ports中安裝最新的gcc。因為大量的ports中的軟體是非gcc不可編譯的,當然有些簡單的軟體是可以用clang編的,比如shell/bash(我試過,編出來的可執行檔案比gcc編出來的小,但是編譯時間比gcc長,執行性能就不知道了)。

革命呢,也是要認清人民群衆的本性的。如果想要在近年内完全脫離GNU編譯器族,那也不太可能。llvm/clang就是個C/C++編譯器,最後還要使用系統中的彙編器和連接配接器來生成可執行檔案的,在FreeBSD中這些as和ld可都是GNU的。雖然BSD的binutils早就在開發了,除了有個ar,nm之類的東西開發完成,as,ld估計是八字沒有一瞥呢。當然,我也了解啊,有的用就先用着,何必為了licence去重造輪子呢?對于assembler估計llvm項目自己會出一個,好像叫“mc”(也是聽人家在mailling list上吹的),至于linker嘛,雖說不是什麼複雜的軟體,估計要等GNU把它的ld變成GPLv3才有希望看到BSD的linker了。

最後,這個新的編譯器将把FreeBSD帶向哪裡?也不能帶向哪裡(我承認我是個标題黨。。。),不就是個編譯器嘛,再說近期還不可能實用。倒是FreeBSD-8的新東西比較吸引人,新的TTY層、增強的kernel SMP、ULE、Gaint lock 進一步去除,特别是網絡棧中Gaint lock的去除,我就等待着FB-8的性能測試報告,估計在多CPU的情況下,網絡棧的性能要上個檔次!還有新的USB代碼(我沒有覺得老代碼有什麼不好,新代碼估計是架構上的改進,具體還沒看。。),增加amd64上kernel記憶體的極限,這下使用ZFS更加啦風了。新的AHCI(SATA)driver,進入了CAM子系統,終于把SATA當作SCSI處理了,(是不是落後與Linux了?無所謂,穩定了的東西我們才用)。

等着FreeBSD-8吧,就在近期了。(要習慣于跳票哦,呵呵)

繼續閱讀