當(dāng)然锦积,因?yàn)長LVM實(shí)在太強(qiáng)大,你會聽到許多其他特性(它可以是個(gè)JIT歉嗓;支持了一大批非類C語言丰介;還是App Store上的一種新的發(fā)布方式等等)。這些都是真的,不過就這篇文章而言哮幢,還是上面的定義更重要带膀。
下面是一些讓LLVM與眾不同的原因:
LLVM的“中間表示”(IR)是一項(xiàng)大創(chuàng)新。LLVM的程序表示方法真的“可讀”(如果你會讀匯編)橙垢。雖然看上去這沒什么要緊垛叨,但要知道,其他編譯器的中間表示大多是種內(nèi)存中的復(fù)雜數(shù)據(jù)結(jié)構(gòu)柜某,以至于很難寫出來嗽元,這讓其他編譯器既難懂又難以實(shí)現(xiàn)。
然而LLVM并非如此喂击。其架構(gòu)遠(yuǎn)比其他編譯器要模塊化得多剂癌。這種優(yōu)點(diǎn)可能部分來自于它的最初實(shí)現(xiàn)者。
盡管LLVM給我們這些狂熱的學(xué)術(shù)黑客提供了一種研究工具的選擇翰绊,它還是一款有大公司做后臺的工業(yè)級編譯器佩谷。這意味著你不需要去在“強(qiáng)大的編譯器”和“可玩的編譯器”之間做妥協(xié)——不像你在Java世界中必須在HotSpot和Jikes之間權(quán)衡那樣。
為什么人人需要懂點(diǎn)兒LLVM监嗜?
是谐檀,LLVM是一款酷炫的編譯器,但是如果不做編譯器研究裁奇,還有什么理由要管它稚补?
答:只要你和程序打交道,了解編譯器架構(gòu)就會令你受益框喳,而且從我個(gè)人經(jīng)驗(yàn)來看课幕,非常有用。利用它五垮,可以分析程序要多久一次來完成某項(xiàng)工作乍惊;改造程序,使其更適用于你的系統(tǒng)放仗,或者模擬一個(gè)新的處理器架構(gòu)或操作系統(tǒng)——只需稍加改動润绎,而不需要自己燒個(gè)芯片,或者寫個(gè)內(nèi)核诞挨。對于計(jì)算機(jī)科學(xué)研究者來說莉撇,編譯器遠(yuǎn)比他們想象中重要。建議你先試試LLVM惶傻,而不用hack下面這些工具(除非你真有重要的理由):
架構(gòu)模擬器棍郎;
動態(tài)二進(jìn)制分析工具,比如Pin银室;
源代碼變換(簡單的比如sed涂佃,復(fù)雜一些的比如抽象語法樹的分析和序列化)励翼;
修改內(nèi)核來干預(yù)系統(tǒng)調(diào)用;
任何和虛擬機(jī)管理程序相似的東西辜荠。
就算一個(gè)編譯器不能完美地適合你的任務(wù)汽抚,相比于從源碼到源碼的翻譯工作,它可以節(jié)省你九成精力伯病。
下面是一些巧妙利用了LLVM造烁,而又不是在做編譯器的研究項(xiàng)目:
UIUC的Virtual Ghost,展示了你可以用編譯器來保護(hù)掛掉的系統(tǒng)內(nèi)核中的進(jìn)程午笛。
UW的CoreDet利用LLVM實(shí)現(xiàn)了多線程程序的確定性惭蟋。
在我們的近似計(jì)算工作中,我們使用LLVM流程來給程序注入錯(cuò)誤信息季研,以模仿一些易出錯(cuò)的硬件。
重要的話說三遍:LLVM不是只用來實(shí)現(xiàn)編譯優(yōu)化的誉察!LLVM不是只用來實(shí)現(xiàn)編譯優(yōu)化的与涡!LLVM不是只用來實(shí)現(xiàn)編譯優(yōu)化的!
組成部分
LLVM架構(gòu)的主要組成部分如下(事實(shí)上也是所有現(xiàn)代編譯器架構(gòu)):
前端持偏,流程(Pass)驼卖,后端
下面分別來解釋:
前端獲取你的源代碼然后將它轉(zhuǎn)變?yōu)槟撤N中間表示。這種翻譯簡化了編譯器其他部分的工作鸿秆,這樣它們就不需要面對比如C++源碼的所有復(fù)雜性了酌畜。作為一個(gè)豪邁人,你很可能不想再做這部分工作卿叽;可以不加改動地使用Clang來完成桥胞。
“流程”將程序在中間表示之間互相變換。一般情況下考婴,流程也用來優(yōu)化代碼:流程輸出的(中間表示)程序和它輸入的(中間表示)程序相比在功能上完全相同贩虾,只是在性能上得到改進(jìn)。這部分通常是給你發(fā)揮的地方沥阱。你的研究工具可以通過觀察和修改編譯過程流中的IR來完成任務(wù)缎罢。
后端部分可以生成實(shí)際運(yùn)行的機(jī)器碼。你幾乎肯定不想動這部分了考杉。
雖然當(dāng)今大多數(shù)編譯器都使用了這種架構(gòu)策精,但是LLVM有一點(diǎn)值得注意而與眾不同:整個(gè)過程中,程序都使用了同一種中間表示崇棠。在其他編譯器中咽袜,可能每一個(gè)流程產(chǎn)出的代碼都有一種獨(dú)特的格式。LLVM在這一點(diǎn)上對hackers大為有利枕稀。我們不需要擔(dān)心我們的改動該插在哪個(gè)位置酬蹋,只要放在前后端之間某個(gè)地方就足夠了及老。
開始
讓我們開干吧。
獲取LLVM
首先需要安裝LLVM范抓。Linux的諸發(fā)行版中一般已經(jīng)裝好了LLVM和Clang的包骄恶,你直接用便是。但你還是需要確認(rèn)一下機(jī)子里的版本匕垫,是不是有所有你要用到的頭文件僧鲁。在OS X系統(tǒng)中,和XCode一起安裝的LLVM就不是那么完整象泵。還好寞秃,用CMake從源碼構(gòu)建LLVM也沒有多難。通常你只需要構(gòu)建LLVM本身偶惠,因?yàn)槟愕南到y(tǒng)提供的Clang已經(jīng)夠用(只要版本是匹配的春寿,如果不是,你也可以自己構(gòu)建Clang)忽孽。
具體在OS X上绑改,Brandon Holt有一個(gè)不錯(cuò)的指導(dǎo)文章。用Homebrew也可以安裝LLVM兄一。
去讀手冊
你需要對文檔有所了解厘线。我找到了一些值得一看的鏈接:
自動生成的Doxygen文檔頁非常重要。要想搞定LLVM出革,你必須要以這些API的文檔維生造壮。這些頁面可能不太好找,所以我推薦你直接用Google搜索骂束。只要你在搜索的函數(shù)或者類名后面加上“LLVM”耳璧,你一般就可以用Google找到正確的文檔頁面了。(如果你夠勤奮展箱,你甚至可以“訓(xùn)練”你的Google楞抡,使得在不輸入LLVM的情況下它也可以把LLVM的相關(guān)結(jié)果推到最前面)雖然聽上去有點(diǎn)逗,不過你真的需要這樣找LLVM的API文檔——反正我沒找到其他的好方法析藕。
《語言參考手冊》也非常有用召廷,如果你曾被LLVM IR dump里面的語法搞糊涂的話。
《開發(fā)者手冊》描述了一些LLVM特有的數(shù)據(jù)結(jié)構(gòu)的工具账胧,比如高效字符串竞慢,vector和map的替代品等等。它還描述了一些快速類型檢查工具isa治泥、cast和dyn_cast)筹煮,這些你不管在哪都要跑。
?如果你不知道你的流程可以做什么居夹,讀《編寫LLVM流程》败潦。不過因?yàn)槟阒皇莻€(gè)研究人員而不是浸淫于編譯器的大牛本冲,本文的觀點(diǎn)可能和這篇教程在一些細(xì)節(jié)上有所不同。(最緊急的是劫扒,別再用基于Makefile的構(gòu)建系統(tǒng)了檬洞。直接開始用CMake構(gòu)建你的程序吧,讀讀《“源代碼外”指令》)盡管上面這些是解決流程問題的官方材料沟饥,
不過在在線瀏覽LLVM代碼時(shí)添怔,這個(gè)GitHub鏡像有時(shí)會更方便。
原文鏈接:http://adriansampson.net/blog/llvm.html
譯者:張洵愷
覺得很有用贤旷,就轉(zhuǎn)載到這里广料,但有些地方不太明白,望高手進(jìn)行深入解讀S资弧0印!