張梅娟,張 榮,張 鉚,韋 祎
(中國(guó)電子科技集團(tuán)公司第五十八研究所,江蘇無(wú)錫 214072)
編譯工具是指一組編譯套件,實(shí)現(xiàn)把某種編程語(yǔ)言編寫(xiě)的代碼轉(zhuǎn)變成另一種計(jì)算機(jī)語(yǔ)言的功能。編譯技術(shù)是計(jì)算機(jī)領(lǐng)域的關(guān)鍵技術(shù)之一,隨計(jì)算機(jī)語(yǔ)言和處理器體系結(jié)構(gòu)的發(fā)展而發(fā)展,目前計(jì)算機(jī)系統(tǒng)高級(jí)語(yǔ)言已幾乎完全代替了匯編語(yǔ)言。常用的編譯工具包含了高級(jí)語(yǔ)言編譯器(C/C++等)、匯編器、鏈接器和其他二進(jìn)制工具。
高級(jí)語(yǔ)言編譯工具是一個(gè)大型系統(tǒng)軟件,開(kāi)發(fā)難度較大,最早期的高級(jí)語(yǔ)言編譯工具共花費(fèi)了18人/年的時(shí)間[1]。研究者們經(jīng)過(guò)幾十年的不懈努力,在編譯理論、技術(shù)和實(shí)驗(yàn)上積累了豐富的成果[2,3,4]。隨著嵌入式系統(tǒng)的發(fā)展和高性能體系結(jié)構(gòu)的出現(xiàn),編譯工具的開(kāi)發(fā)速度和質(zhì)量有了更高的要求,推動(dòng)了可重定向編譯系統(tǒng)的研究,逐步將與高級(jí)語(yǔ)言相關(guān)的詞法語(yǔ)法分析模塊設(shè)計(jì)成可復(fù)用的前端,機(jī)器相關(guān)的部分被封裝起來(lái),前端通過(guò)間接調(diào)用的方式與機(jī)器相關(guān)的部分發(fā)生關(guān)系。如圖1所示,針對(duì)不同處理器,只需要進(jìn)行目標(biāo)機(jī)器信息的描述(即編譯工具的移植),即可快速生成一套編譯工具。這大大減小了編譯工具的開(kāi)發(fā)難度和開(kāi)發(fā)時(shí)間。
圖1 可重定向編譯系統(tǒng)
可重定向編譯系統(tǒng)結(jié)構(gòu)定義良好,針對(duì)不同的后端,前端代碼基本上不用修改,做到了最大限度的代碼復(fù)用。但是前端只進(jìn)行了一些通用的代碼優(yōu)化,沒(méi)有做與目標(biāo)機(jī)相關(guān)的優(yōu)化,運(yùn)行效率有一定的提升空間。
GCC(GNU Compiler Collection,GNU 編譯器套件),是一套以GPL及LGPL許可證所發(fā)行的自由軟件,是可重定向編譯系統(tǒng)的代表,常被認(rèn)為是跨平臺(tái)編譯工具移植的事實(shí)標(biāo)準(zhǔn)。該系統(tǒng)在所有平臺(tái)上都能使用同一個(gè)前端處理程序,產(chǎn)生相同的中間代碼,因此在不同平臺(tái)上,使用GCC系統(tǒng)移植編譯工具,不僅可以保證編譯工具的性能質(zhì)量,還能縮短開(kāi)發(fā)周期[5]。但是嵌入式處理器體系結(jié)構(gòu)一般都不規(guī)則,對(duì)代碼質(zhì)量要求嚴(yán)格,必須對(duì)編譯系統(tǒng)的前端和后端進(jìn)行針對(duì)性的優(yōu)化設(shè)計(jì)才能滿足要求,因此移植具有其特殊的難度和復(fù)雜性[6]。
本文基于可重定向的GCC編譯系統(tǒng)的移植,成功構(gòu)建了cmdsp2f01處理器的編譯工具套件,經(jīng)測(cè)試驗(yàn)證,編譯工具套件編譯功能正確。
編譯工具的移植,需要描述目標(biāo)機(jī)器信息。cmdsp2f01是中國(guó)電科第58所開(kāi)發(fā)的一款高性能DSP芯片,該芯片處理器采用超長(zhǎng)指令字(VLIW)架構(gòu),支持單周期5條指令并行執(zhí)行,支持單指令多數(shù)據(jù)流(SIMD),使數(shù)據(jù)處理并行度更高,128 bit程序總線,雙256 bit數(shù)據(jù)總線,具備單精度浮點(diǎn)運(yùn)算,支持16 bit、24 bit指令編碼。其內(nèi)部流水線支持7級(jí),運(yùn)算能力達(dá)12.8 GMACs。
cmdsp2f01的DSP內(nèi)核架構(gòu)支持1字節(jié)、2字節(jié)和4字節(jié)數(shù)據(jù)格式,另支持32 bit單精度浮點(diǎn)數(shù)據(jù)格式和40 bit累加器值(MAC16時(shí)使用)。所有存儲(chǔ)在內(nèi)存的數(shù)據(jù)CPU都是字節(jié)尋址,字節(jié)順序固定為小端模式,即0字節(jié)是最低有效位字節(jié)。核指令基于32 bit虛擬和物理內(nèi)存尋址,指令和數(shù)據(jù)尋址可達(dá)4 GB尋址空間。尋址方式支持寄存器加立即數(shù)尋址。
圖2 處理器架構(gòu)信息
如圖2所示,cmdsp2f01 DSP除支持通用運(yùn)算和存取指令外,還增加了專(zhuān)用定點(diǎn)矢量指令。其中,通用指令包含Move指令、加減指令、乘加指令、比較指令、分支指令、地址運(yùn)算指令和存取指令。
本文所述的編譯工具是指一組編譯套件,含C編譯器和匯編器、鏈接器等二進(jìn)制工具集。移植的主要任務(wù)是目標(biāo)機(jī)器信息的描述。GCC系統(tǒng)中,機(jī)器信息的描述主要采用寄存器轉(zhuǎn)換語(yǔ)言RTL(Register Transfer Language)語(yǔ)言實(shí)現(xiàn),輔助以C接口函數(shù)(API)的設(shè)計(jì)。RTL中間表作為GCC C編譯器后端的核心內(nèi)容,將后端中可重用的部分剝離出來(lái),再通過(guò)相應(yīng)的接口為不同的目標(biāo)機(jī)器定義各自的映射規(guī)則,這種方式極大地提高了GCC的適應(yīng)性,也增強(qiáng)了它的可維護(hù)性、可擴(kuò)展性以及可移植性[7]。
本文的移植是結(jié)合cmdsp2f01處理器特點(diǎn),對(duì)機(jī)器描述進(jìn)行設(shè)計(jì)和實(shí)現(xiàn),構(gòu)建一套新的編譯工具。編譯工具套件基本功能如下:
(1)C編譯器(C-Compiler),將C語(yǔ)言程序代碼編譯成cmdsp2f01處理器對(duì)應(yīng)的匯編代碼,編譯器包括外殼程序(shell program)、優(yōu)化器和預(yù)處理器;
(2)匯編器(Assembler),把匯編語(yǔ)言源文件轉(zhuǎn)換成基于公用目標(biāo)文件(ELF)的機(jī)器目標(biāo)文件,也就是常用的*.out文件;
(3)鏈接器(Linker),把多個(gè)目標(biāo)文件組合成單個(gè)可執(zhí)行目標(biāo)模塊,除了能夠創(chuàng)建可執(zhí)行文件外,還可以調(diào)整外部符號(hào)的引用,鏈接器輸入的是可重定位的目標(biāo)文件和目標(biāo)文件庫(kù);
(4)歸檔器(archiver),允許用戶將一組文件收集到一個(gè)歸檔文件中,也叫歸檔庫(kù),其最常見(jiàn)的用法是創(chuàng)建目標(biāo)文件庫(kù),也可以通過(guò)刪除、替換、提取或添加文件操作來(lái)調(diào)整庫(kù);
(5)Objdump,用來(lái)查看目標(biāo)程序中的段信息和調(diào)試信息,也可以用來(lái)對(duì)目標(biāo)程序進(jìn)行反匯編;
(6)Objcopy,用來(lái)拷貝或是翻譯目標(biāo)文件;
(7)Nm,列出目標(biāo)文件、庫(kù)或是可執(zhí)行文件中的代碼符號(hào)及代碼符號(hào)所對(duì)應(yīng)的程序開(kāi)始地址;
(8)Size,顯示程序文件的段信息。
編譯工具包含C/C++編譯器及二進(jìn)制工具集(匯編、鏈接等工具),需要分別基于兩套代碼系統(tǒng)進(jìn)行移植。GCC是高級(jí)語(yǔ)言編譯器相關(guān)的工具代碼,移植后可生成預(yù)處理器、高級(jí)語(yǔ)言編譯器等工具,binutils是二進(jìn)制工具集代碼,移植后可生成匯編器、鏈接器、反匯編器等二進(jìn)制工具。
通常在編譯過(guò)程中所使用的GCC是一個(gè)驅(qū)動(dòng)程序,在實(shí)際執(zhí)行編譯的過(guò)程中將根據(jù)輸入的命令參數(shù),調(diào)用不同的程序(包括預(yù)處理器、編譯器、匯編器以及鏈接器等)進(jìn)行分析處理,實(shí)現(xiàn)對(duì)整個(gè)編譯過(guò)程的控制。
編譯工具移植實(shí)現(xiàn)步驟如下:
(1)移植環(huán)境準(zhǔn)備(源代碼獲取、移植環(huán)境選擇);
(2)分析處理器結(jié)構(gòu)及指令特點(diǎn),進(jìn)行目標(biāo)機(jī)信息的描述;
(3)構(gòu)建編譯工具;
(4)測(cè)試驗(yàn)證編譯工具。
GCC幾乎可以運(yùn)行在所有操作系統(tǒng)平臺(tái)上,如GNU/Linux、其他自由軟件平臺(tái)(BSD系列)等。通過(guò)Cygwin(或MinGW)工具,GCC也可以運(yùn)行在MS DOS、MS Windows多個(gè)版本的平臺(tái)上。本文移植工作主機(jī)系統(tǒng)選擇Windows平臺(tái),采用Cygwin作為虛擬環(huán)境。必要的源代碼包括gcc-5.2.0、二進(jìn)制工具源代碼binutils-2.23.1。代碼閱讀使用Source Insight3.5工具。
3.2.1 編譯器代碼移植
代碼移植就是在GCC框架內(nèi)添加目標(biāo)機(jī)器信息的描述,在./gcc-5.2.0/gcc/路徑中創(chuàng)建target文件夾,并在該文件夾中創(chuàng)建機(jī)器描述文件(如target.c、target.h、target.md等文件)。target.h定義大小端、指令類(lèi)型、數(shù)據(jù)類(lèi)型及字長(zhǎng)、內(nèi)存邊界及對(duì)齊、尋址模式類(lèi)型、標(biāo)準(zhǔn)寄存器的分配等信息。
cmdsp2f01處理器有16個(gè)32位通用地址寄存器,分別為a0~a15。設(shè)計(jì) a1用作棧指針sp,a2~a7用于函數(shù)調(diào)用處理。處理器寄存器信息定義如圖3所示。
target.c文件中定義一些API接口函數(shù),供target.md描述指令時(shí)使用。如圖4所示,在target.c文件中定義有符號(hào)8位立即數(shù)。
在target.md中描述加法操作數(shù)時(shí)引用該接口函數(shù),加法操作數(shù)詳細(xì)描述方法如圖5所示。
target.md文件中,使用RTL語(yǔ)言對(duì)機(jī)器指令特點(diǎn)進(jìn)行描述,描述語(yǔ)句遵循RTL語(yǔ)言規(guī)則。處理器支持5種加法類(lèi)型指令,16位寄存器尋址加法指令add.n,16位立即數(shù)尋址加法指令,24位寄存器尋址加法指令add,24位立即數(shù)尋址加法指令addi,24位立即數(shù)尋址加法指令addmi,立即數(shù)尋址時(shí)左移8位。加法指令的描述如圖6所示。
圖3 target.h文件內(nèi)容摘要
圖4 8位立即數(shù)API定義
圖5 加法操作數(shù)定義
圖6 加法指令描述
3.2.2 編譯器構(gòu)建過(guò)程
gcc-5.2.0版本的編譯需要mpc的支持,而mpc又依賴于gmp和mpfr庫(kù),因此需要從官網(wǎng)上下載源代碼mpc-0.8.1、gmp-4.3.2、mpfr-2.4.2。分別安裝3個(gè)庫(kù),由于庫(kù)之間有依賴關(guān)系,庫(kù)的安裝有先后順序,安裝順序?yàn)間mp/mpfr/mpc。3個(gè)庫(kù)安裝在默認(rèn)庫(kù)的路徑下(./usr/lib)。
GCC構(gòu)建時(shí),按照configure/make的步驟,詳細(xì)步驟如下:
構(gòu)建好的工具在路徑./usr/local/bin下。
3.2.3 二進(jìn)制代碼構(gòu)建
在../Binutils-2.23.1/include/路徑下,創(chuàng)建文件target-isa.h進(jìn)行處理器架構(gòu)宏定義。在../Binutils-2.23.1/gas/config路徑下,創(chuàng)建target.c和target.h指令集描述文件,實(shí)現(xiàn)對(duì)指令集的映射。構(gòu)建過(guò)程與GCC構(gòu)建過(guò)程類(lèi)似,配置選項(xiàng)相對(duì)簡(jiǎn)單很多。
編譯工具本身結(jié)構(gòu)復(fù)雜,進(jìn)行全面的測(cè)試比較困難。編譯工具的測(cè)試與其他類(lèi)型軟件的測(cè)試一樣,同樣分為黑盒測(cè)試與白盒測(cè)試。在實(shí)際工程應(yīng)用中,通常以黑盒測(cè)試為主,以白盒測(cè)試為輔[8]。黑盒測(cè)試具體是提供測(cè)試用例,將產(chǎn)生的結(jié)果與預(yù)期結(jié)果進(jìn)行比較,測(cè)試用例的設(shè)計(jì)和選擇尤為重要。為了避免測(cè)試用例受到開(kāi)發(fā)人員經(jīng)驗(yàn)、偏好等因素的影響,本文選擇處理器性能評(píng)價(jià)標(biāo)準(zhǔn)程序?yàn)闇y(cè)試用例,對(duì)本文構(gòu)建的編譯工具進(jìn)行測(cè)試驗(yàn)證。黑盒測(cè)試流程如圖7所示。
表1 標(biāo)準(zhǔn)benchmark測(cè)試程序
測(cè)試程序執(zhí)行如圖8所示的自定義makefile文件后,輸出編譯中間結(jié)果及最終可執(zhí)行二進(jìn)制文件。使用移植后的gdb加載運(yùn)行后,執(zhí)行結(jié)果與VS2008下編譯程序執(zhí)行的結(jié)果比較,結(jié)果正確無(wú)誤。
白盒測(cè)試,C語(yǔ)言編譯器輸出匯編代碼,編寫(xiě)簡(jiǎn)單的C源代碼如圖9 a.c文件,執(zhí)行taret-gcc5.2.0.exe-S a.c-o a.S命令后,輸出相應(yīng)匯編代碼,如圖9所示。加法操作被翻譯為16位寄存器尋址的加法指令add.n。常量數(shù)據(jù)放入特定的數(shù)據(jù)段.literal,每個(gè)變量定義了地址標(biāo)號(hào),便于立即尋址。
圖7 黑盒測(cè)試流程
圖8 自定義makefile文件
圖9 C語(yǔ)言編譯結(jié)果
本文基于GCC,針對(duì)特定目標(biāo)處理器實(shí)現(xiàn)了編譯工具的移植,全面描述了編譯工具移植的實(shí)施流程,針對(duì)目標(biāo)處理器架構(gòu)特點(diǎn),設(shè)計(jì)了機(jī)器描述文件內(nèi)容,成功構(gòu)建了特定處理器的編譯工具套件,并對(duì)工具套件進(jìn)行了功能驗(yàn)證。本文描述的技術(shù)同樣可用于其他處理器架構(gòu)編譯工具的移植開(kāi)發(fā),可節(jié)省開(kāi)發(fā)調(diào)試時(shí)間。
[1]Backus,J W,R J Beeber,S Best,et al.The Fortran automatic coding system[C].Western Joint Computer Conference,1957:188-198.
[2]Appel A W,Palsberg J.Modern Compiler Implementation in Java[M].Cambridge University Press,second edition,2002.
[3]Aho A V,Sethi R,Ullman JD.Compilers Principles,Techniques,and Tools[M].Person Education,1986.
[4]Muchnick S S.Advanced Compiler Design and Implementation[M].San Francisco,California:Morgan Kaufmann,1997.
[5]Wang Xiaowei,Wang Kuixing,Yang Quansheng.Research and DevelopmentofCompilerBased on GCC[C].CSIE 2011,LNEE 126:809-814.
[6]Rainer Leupers,Peter Marwedel.Retargetable compiler technology for embeded systems,tools and applications[M].Kluwer Academic Publishers,October 2001.
[7]石博慧,陳英.GCC代碼優(yōu)化技術(shù)研究[J].微機(jī)發(fā)展,2004(8):67-70.
[8]陳慈勇.基于GCC的交叉編譯器移植開(kāi)發(fā)及其測(cè)試方案的設(shè)計(jì)研究[D].廈門(mén),2011:67.