<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 探索 GCC 前端的內部結構(1)

探索 GCC 前端的內部結構(1)

——
作者: 時(shí)間:2007-04-17 來(lái)源:嵌入開(kāi)發(fā)網(wǎng) 收藏

GNU 家族 GCC 介紹

作為自由軟件的旗艦項目,Richard Stallman 在十多年前剛開(kāi)始寫(xiě)作 GCC 的時(shí)候,還只是把它當作僅僅一個(gè) C 程序語(yǔ)言的;GCC 的意思也只是 GNU C Compiler 而已。經(jīng)過(guò)了這么多年的發(fā)展,GCC 已經(jīng)不僅僅能支持 C 語(yǔ)言;它現在還支持 Ada 語(yǔ)言,C++ 語(yǔ)言,Java 語(yǔ)言,Objective C 語(yǔ)言,Pascal 語(yǔ)言,COBOL 語(yǔ)言,以及支持函數式編程和邏輯編程的 Mercury 語(yǔ)言,等等。而 GCC 也不再單只是 GNU C 語(yǔ)言的意思了,而是變成了 GNU Compiler Collection 也即是 GNU 編譯器家族的意思了。 

另一方面,說(shuō)到 GCC 對于各種硬件平臺的支持,概括起來(lái)就是一句話(huà):無(wú)所不在。幾乎所有有點(diǎn)實(shí)際用途的硬件平臺,甚至包括有些不那么有實(shí)際用途的硬件平臺,比如 Don Knuth 設計的 MMIX 計算機,GCC 都提供了完善的支持。 

我們在這篇文章中要弄清楚的就是 GCC 是如何做到能夠支持這么多種程序語(yǔ)言的。所謂的 GCC 的程序語(yǔ)言前端到底是怎么回事。如果我們要設計實(shí)現自己的編程語(yǔ)言的話(huà),應該從何入手?;卮疬@些問(wèn)題的第一步,就是分析清楚 GCC 源碼包中,為了說(shuō)明 GCC 的程序語(yǔ)言前端的編寫(xiě)方法,而寫(xiě)作的 Treelang 編程語(yǔ)言在 GCC 中的實(shí)現細節。 

如果把我們自己的程序語(yǔ)言的實(shí)現建立于 GCC 之上,也立刻使得我們的程序語(yǔ)言的實(shí)現版本可以運行在幾乎所有有用的硬件平臺之上。這對于程序語(yǔ)言的作者來(lái)說(shuō),也是一個(gè)確實(shí)的有極大誘惑力的好處。 

關(guān)于代碼分析

在這一小節里面我們著(zhù)重說(shuō)明兩個(gè)問(wèn)題:第一、為什么要閱讀源代碼;第二、代碼分析應該怎么寫(xiě)。 

閱讀源代碼對提高自己的編程水平是非常有幫助的。這個(gè)幫助至少體現在兩個(gè)方面。第一個(gè)方面是學(xué)會(huì )大型軟件項目設計的模式。這樣的模式是真實(shí)可靠的第一手資料,這樣學(xué)來(lái)的模式要比從書(shū)本上,用日常語(yǔ)言陳述的模式,更能深入到你的腦海中去。而且它的真實(shí)性和可靠性都是有保證的。并且這樣的模式還非常的具體。我曾經(jīng)看到計算機系的同學(xué)推薦去讀亞歷山大的建筑學(xué)方面的經(jīng)典著(zhù)作;個(gè)人以為這是走的太遠了。與其去讀建筑學(xué)的書(shū),不如去分析一下成功的自由軟件項目的源代碼。具體的用代碼說(shuō)明的模式,無(wú)論如何要比虛無(wú)飄渺的美學(xué)概念,或者模棱兩可的工程紀律,都要更加容易學(xué)習吧? 

閱讀源代碼的第二個(gè)好處,是增加自己的自信心。就象學(xué)習英語(yǔ),要和別人談話(huà),要看看別人的文章,不能只是看教科書(shū)上的簡(jiǎn)單的例子。教科書(shū)上的例子限于篇幅,不可能做到像真實(shí)、完整的英文小說(shuō)那樣,把一個(gè)完整的設計呈現在你的面前。只有當你硬著(zhù)頭皮,拋開(kāi)字典,把一本英文小說(shuō)生生啃下來(lái)之后,你才能有把握說(shuō):我的確能做到。類(lèi)似的,只有當我們看過(guò)大型軟件項目的源代碼,作過(guò)修改,摸爬滾打之后,我們才能有把握的說(shuō):我也能寫(xiě)出來(lái)。 

上面說(shuō)了閱讀源代碼至少有這么兩個(gè)好處。那么在閱讀源代碼的時(shí)候,我們必然要做代碼分析筆記。這個(gè)代碼分析筆記如何寫(xiě),這就是我們關(guān)心的一個(gè)問(wèn)題了。在這里,我提出一些我自己的也許不太成熟的看法,也請讀者朋友們不吝指教。 

我總覺(jué)得,與其作一行一行的代碼注釋?zhuān)f(shuō)明每一行代碼的作用;不如設計一個(gè)故事,把代碼的框架說(shuō)清楚。這也是我前面提到的,所謂模式一說(shuō)。因為閱讀源代碼,最關(guān)鍵的是要了解大型軟件項目設計的模式,而不是要把每一次讀者分析每一行代碼細節的樂(lè )趣從此剝奪掉。 

另一方面,代碼分析的寫(xiě)作風(fēng)格,可以是參考手冊似的;也可以是航海日志似的。我個(gè)人覺(jué)得參考手冊似的代碼分析是比較乏味的,讀起來(lái)乏味,寫(xiě)起來(lái)也不免乏味,雖然它可能更有用。對于一個(gè)急著(zhù)要快點(diǎn)結束加班工作的軟件工程師來(lái)說(shuō),也許參考手冊更加實(shí)用。但是對于一個(gè)想要了解這一份成功的軟件背后的工作奧秘的探索者來(lái)說(shuō),一個(gè)航海日志似的代碼分析,也許讀起來(lái)更有味道,更能讓一個(gè)程序員在鍵盤(pán)與屏幕之間,體會(huì )到那地理大發(fā)現的激動(dòng)與樂(lè )趣。 

Treelang 的代碼框架

讀者朋友們在閱讀這一部分代碼分析的時(shí)候,手邊最好能準備上一份 GCC 3.3 的源代碼。這個(gè)源代碼可以從 GCC 的站點(diǎn) http://gcc.gnu.org上獲得。本文作者力圖做到把整個(gè)情況像說(shuō)故事一樣娓娓道來(lái),但是讀者朋友們如果在適當的時(shí)候能夠查閱一下源代碼,可能更能把問(wèn)題了解的清楚透徹。 

這個(gè) treelang 語(yǔ)言的實(shí)現,主要有兩個(gè) C 語(yǔ)言文件,把整個(gè)代碼框架分成兩個(gè)部分。第一部分以 tree1.c 為主,帶上 parse.y 這個(gè) YACC 源程序,組成了和 GCC 前端的接口;第二部分以 treetree.c 為主,組成了和 GCC 后端的接口。 

這里首先說(shuō)明一下 tree1.c 這個(gè)文件。它和上級目錄中的 GCC 框架文件 toplev.c 交互作用,實(shí)現 tree1 這個(gè)執行程序的主體部分。這個(gè) tree1 就相當于 GCC 的 C 語(yǔ)言前端中的 cc1 執行程序,該程序是 C 語(yǔ)言編譯器前端的主體。 

我們首先試圖說(shuō)明從 toplev.c 到 tree1.c 的路徑。這樣我們就注意到 toplev.c 中這個(gè)引人注目的 lang_hooks 變量。當然,接下來(lái)就注意到在 toplev.c 同一目錄下的 langhooks.c 這個(gè)文件。我們希望在其中發(fā)現一點(diǎn)有趣的東西。這一共是三個(gè)文件:langhooks.[ch] 和 langhooks-def.h 其中在 langhooks.h 中定義了一堆各式各樣的 struct lang_hooks_for_xxx 結構,以及最后還有一個(gè) struct lang_hooks 結構把前面的那些 for_xxx 的結構都總括了起來(lái)。這每一個(gè)結構都是若干個(gè)至少看上去像是回調函數的函數指針??磥?lái)這就是我們要尋找的東西。那么大概就是這樣了,編譯器前端向 GCC 主體部分注冊自己的 lang_hooks 來(lái)完成各樣的任務(wù)。接下來(lái)一個(gè)自然的問(wèn)題就是這個(gè)注冊是如何進(jìn)行的;另外一個(gè)問(wèn)題就是要對這些回調函數指針進(jìn)行分析了。 

這個(gè) langhooks.h 文件中關(guān)于 struct lang_hooks 結構字段的注釋很詳細,這里我們暫時(shí)先跳過(guò)去。等到 treelang 中具體的注冊回調函數出現的時(shí)候,我們根據需要再做仔細說(shuō)明。在 langhooks-def.h 文件中定義了一些這個(gè) struct lang_hooks 結構的默認值。 

現在我們進(jìn)入 treelang 目錄下的 treetree.c 這個(gè)文件。來(lái)察看一下在 treelang 中對 struct lang_hooks 這個(gè)結構的初始化過(guò)程。這個(gè)過(guò)程不是按照我們通常所熟悉的 C 語(yǔ)言的 C99 標準或者是 GCC 擴展語(yǔ)法來(lái)進(jìn)行的。而是采用了大量的 #define 和 #undef 并結合上層目錄中的 langhooks-def.h 來(lái)進(jìn)行。細想一下,這是理所當然的事情,因為這是在編譯 C 語(yǔ)言編譯器本身嘛。當然就不好用到 C 語(yǔ)言的新的東西或者是自己做的擴展的東西。 



評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>