編譯技術中各環節比重如何?

這學期學習編譯原理課。

大部分教學內容停留在詞法分析和語法分析上。特別是在語法分析上,比如LL(1),LR(1),LR(0)等文法的語法分析表建立過程中需要的一些概念和分析過程。

而中間代碼生成和代碼生成幾乎只是一提而過。大部分時間都在研究一些晦澀,枯燥的和離散數學有關的知識。

不知整個編譯過程中,各環節的重要程度是怎樣的?這些語法分析和詞法分析是不是已經有成熟的解決方案,或者說市面上的語言基本就包含在這幾種文法裡面了。所以這些編譯器前端知識並不是特別重要?理解就行?當然,不是不需要學。

還是說前端有時候是一個語言的核心部分,比如某些語言的難點是在語法分析上?那麼就需要專研這類語法分析的過程,引入一些概念和數學研究的成果。比如LL(1)中FIRST,LAST,SELECT,簡單優先文法的優先順序大於,小於等這些語法分析過程中得概念和方法。(這些方法只會用,不知道為什麼,書上都是定義和定理)

我當然不是覺得學老師教學的內容就夠了,我只是覺得教學比重分配上,理論性過高,是否有應付考試的成分。

請各位編譯大神給些方向性的指導,太細的估計也不容易說清楚。


學界基本上不怎麼做前端的工作了,因為這一塊從理論到應用都已經高度成熟。理論從Chomsky的工作開始,到各種LL/LR/TDPL之類文法的定義、對應parser演算法、文法優缺點都研究得很透。實際運用的話,一大半市面上編譯器的parser都是手寫(不外乎遞歸下降和狀態機),剩下的就是自動構造parser了,從爺爺輩的yacc到ANTLR再到函數式語言里時髦的各種parser組合子,都有人造過輪子,都有人在用。

國內的編譯原理課花了一大半時間講parsing,中間優化和代碼生成講得少。真正有挑戰性、有意義的地方恰恰是這些部分。隨便列幾個題目。

怎樣使你的編譯器容易port到不同架構上?你需要自學一下gcc/llvm的中間表示,對體系結構起碼有csapp水平的了解。

怎樣設計和實現一個位元組碼虛擬機?直接解釋執行ast的性能可是相當受限的。你需要把哪些指令設計出來,你的代碼怎麼對應到這些指令,這個需要你對自己要實現語言的語義精確了解,能透過語法抽象出控制原語,這裡稍微了解一點編程語言理論,包括operational semantics,有很大幫助。

怎樣充分利用語言特性使編譯器生成又快又正確的代碼?你的語言有高階函數和閉包需要優化嗎?你的語言有mutable嗎,可能產生aliasing嗎,有垃圾回收嗎?支持多線程嗎,有消息傳遞嗎,需要GIL嗎?可擴展嗎,FFI做成什麼樣?。。等等,每作出一個tradeoff,語言和編譯器就包含了更多你的個人口味,你也需要看更多文章。

應付考試的話不需要了解這些。一門課也沒辦法覆蓋這麼多,因為我在談論編譯器的時候,實際上在談編程語言理論,在談體系結構,在談操作系統,在談分散式計算。。。etc

拋磚引玉,見笑了。


參考Stanford Compiler課程的講義

分為早期編譯器和現代編譯器,比重不一樣,分布示意圖參考Alex Aiken的課堂塗鴉

L short for Lexical analysis

P short for Parsing

S short for Semantic analysis

O short for Optimization

CG short for Code Generation

上面的比例示意圖是早期的編譯器比重,下面的是現在的


如果純粹來說編譯技術,我認為都重要,編譯器的每一個步驟幾乎都是環環相扣的。但是若不是專業的編譯開發者,我還是認為編譯器前端技術更重要一些,因為這會讓你學習新語言更快,對程序語言的理解也更深。


看不同場景了,如果是白手起家自己做一個,那個人覺得優化和運行環境的構建是大頭,尤其是其中的數據流分析和GC非常需要深挖

但如果依賴於已有的一些東西,那麼可以把關注點更多放在「做什麼」而不是「怎麼做」上,比如自己設計一個語言,後端交給java或C,這樣只需要考慮這個語言該有什麼語法能適合需求,而將其做詞法分析和語法分析並轉換為java或C一般來說不是那麼難了


我們老闆說指針分析性能優化最難,我們也不太懂


感覺前端的理論本身就很有意思。雖然我們很早就學會了一門自然語言,但是很多語言相關的概念也是學了編譯原理才明白的。比如什麼是語言,什麼是語法,什麼是語義。

詞法分析,語法分析確實有現成的工具。但是,它們並沒有那麼好用。可以試著做一下Stanford compilers課程的大作業。就是用這些工具寫的cool語言的編譯器。cool語言算是很乾凈的語言了,寫起來感覺也挺費勁的。


對於國內的編譯器開發者而言,前端的重要性不高,因為前端主要是針對特定語言(如c,fortran等)的詞法,語法分析,並轉化為編譯器的內部表示語言。

除非你要開發新的語言,或者增加新的語法特性,否則已有的編譯器前端足以滿足需求,只需簡單移植即可。

後端主要是是把內部表示語言轉化為指令,與機器平台密切相關,由於目前處理器國產化的熱潮,關注後端得開發者很多,他們要針對自己開發的處理器特性對後端做大量修改。

編譯器就是處理器最親密的夥伴,最重要的配套軟體之一。當然,了解了編譯原理和編譯器的工作方法,對於編程查錯和優化更加有用。

畢竟真正運行的不是你的程序代碼,而是經編譯器翻譯之後的指令流。你要清楚這傢伙真正幹了什麼!


重要程度看怎麼分了,不過語法解析肯定是基礎中的基礎,解析出了問題後面那幾張什麼控制流數據流都是在扯淡了。不過解析確實基本已經很完善了,之前從事GCC相關工作,解析基本都不碰,主要是一些優化,大部分是跟後端架構相關的,在RTL上的優化,偶爾會跑到TREE上進行一些優化。

前端的知識(TREE)比較通用,後端(RTL)基本都依賴架構。

龍書我記得推薦是要一學年修完的吧,編譯原理確實是一個理論比較複雜的課程,我們裡面就說,數學系比計算機和軟工更適合做編譯器。龍書關注的也是不考慮源和目標語言(如下圖)。下下圖是龍書引論的部分。

PS:

感覺GCC隨便抽出一個pass都可以講上幾節課,而且數學要求可能更高。總的有一兩百個pass(功能和性能)。gcc file -O2 -fdump-tree-all -fdump-rtl-all自己看看。

或者說市面上的語言基本就包含在這幾種文法裡面了

感覺最近幾年興起的語言越來越多了。。。。。。。。。。


編譯原理教學「理論性」過高?編譯原理課程就是講一些理論知識足夠了,然後實踐方面,就靠你的基本功了,畢竟編譯原理實踐也不外乎那幾種常用的數據結構和演算法。


Parsing技術已經很成熟了,而且現在的共識是語法不要設計得太複雜。

語義分析比較有趣,優化比較有得搞。


推薦閱讀:

有沒有比較好用的圖片文字識別軟體?
繪製架空世界地圖的方法及軟體?
彈窗到底算不算流氓行為?
如何給文件/文件夾添加備註?
有沒有特別方便畫動態流程圖的軟體?

TAG:軟體 | 計算機科學 | 編譯原理 | 編譯器 | 計算機語言 |