The Architecture of Open Source Applications -- llvm

         本文闡述在形成LLVM的過程中所做的一些設計決策, LLVM是一個基金項目,用來解決和開發一套緊密的底層工具鏈組件(比如:彙編器,編譯器,調試器等等),它被設計成可以兼容Unix系統上的現有工具,'LLVM'一度是一個縮略語,現在僅僅是此基金項目的代名詞。LLVM提供了一些獨特的能力,以一些偉大工具著稱(比如:clang編譯器,一個C/C++/Objective-C編譯器,提供了一些優於GCC編譯器的特性), 但LLVM區別於其他編譯器的主要特點在於它內部的架構。

         LLVM項目始於2000年12月,被設計成一組可以重用的有良好接口定義的庫,當時,開源程序語言的實現被設計成特別目的的工具,通常是一個單一的執行程序。例如,重用靜態編譯器(比如GCC)的解析器做一些靜態分析或重構的工作是非常困難的。而腳本語言通常提供一種方法嵌入他們的實時運行或者解釋器到大型應用中,這種實時是一個單一的代碼快被包含或者排除。沒有辦法去重用,而且不同語言實現項目之間很少有共享。

          除了編譯器自身的組合特性(composition?),流行語言實現的團體通常嚴重的兩極分化:實現通常提供像GCC、Free Pascal、FreeBasic的靜態編譯器或者提供解釋器、JIT的實時編譯器。很難能見到同時支持上兩種的語言實現,即使同時支持,通常也很少共享代碼。

          在過去10年裏,LLVM相當多的改變了這種狀況。 LLVM現在作爲一個通用框架用來實現很多不同的靜態和動態編譯語言(例如,GCC、JAVA、.NET、Python、Ruby、Scheme、Haskell,D支持的語言族,以及很多不計其數不爲人知的語言)。它同樣淘汰了一大批特殊用途的編譯器,例如Apple的OpenGL棧中的實時規範引擎,Adobe的After Effects產品中的圖像處理庫。最後,LLVM也用於建立一大批新的產品,可能最有名的是OpenCL GPU的編程語言和實時庫。

11.1 經典編譯器設計的快速簡介
         傳統靜態編譯器(像大多數的C編譯器)最流行的設計是三段式設計,主要部分包括前端、優化器、後端(如圖11.1)。前端用於解析源代碼,錯誤檢查,生成一個特定語言的抽象語法樹來表示輸入碼。 AST可以隨意(optionally)轉化爲一種新的表示用於優化, 而優化器和後端在代碼上執行。

         優化器負責各種各樣的轉換來嘗試提高執行效率,如消除冗餘計算,通常或多或少的獨立於語言和目標機。 後端(又叫代碼生成器)把代碼映射成目標指令集。除了生成正確的代碼,它還負責生成好的代碼以利用支持目的機架構的不尋常特性。 編譯器後端的通用部分包括指令集的選擇,寄存器的分配,以及指令調度。
          這個模型很好的應用在解釋器和JIT編譯器。JVM是這個模型的一個實現,它是java byetecode作爲前端和優化器間的接口。
 11.1.1 設計的暗示
         當編譯器決定支持多種源碼語言或者多個目的架構時,這種經典設計的最重要的優勢就體現出來了, 如果編譯器在優化器中使用通用代碼表示,前端可以爲任何可以編譯成這種中間形式的語言服務,後端可以爲任何目的機服務,目的機來自從中間形式編譯。如圖11.2。

         使用這種設計,移植這種編譯器使其支持一種新的語言(例如,Algol或者BASIC),只需要實現一個新的前端, 而已經存在的優化器和後端可以重用。 如果這些部分沒有分離,實現一種新的語言需要從頭開始,支持N種目的機和M種語言需要N*M個編譯器。
         三段式設計(which follows directly from retargetability)的另一個優點是,相較於只支持一種語言和一種目的機,此種編譯器可以服務一大批程序員。對於一個開源項目,意味着會有一大批社區的潛在貢獻者,很自然的增強和改進已有的編譯器。這就是爲什麼開源編譯器服務於很多社區(比如GCC),生成好的優化機器碼,而閉源編譯器(比如FreePASCASL)不能的原因。專有編譯器情況則不同, 它的質量與項目的經費直接相關。例如,Intel ICC編譯器已它生成的代碼質量聞名,即使只有服務於很少一部分人。  
        三段式設計最後一個優勢是實現一個前端使用的技術不同於實現優化器和後端,把這些部分獨立,對個性化前端來說,使得增強和維護編譯器的各個部分更容易。雖然這是個社會問題而不是技術問題,在實踐中確實非常要緊的,特別是對於開源項目需要儘可能低的消除相互貢獻的障礙。

11.2   現有語言的實現
        雖然三段式設計的優點在編譯器教材中有有完整的描述(compelling and well-documented),實際上從來都沒有完全的實現過。在LLVM沒有出現前,瀏覽開源語言的實現,你會發現Perl,Python,Ruby,Java的實現沒有共享任何代碼。並且,像Glasgow Haskell Compiler(GHC)和FreeBASIC這樣的項目可重定向(retargetable)到多個不同的CPU,但他們的實現只特定於他們支持的單一語言。還有各種各樣的特定目的的編譯器技術配置到JIT編譯器中,用於圖像處理、正則表達式、圖形卡驅動及其它需要高效使用CPU的子領域中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章