在編譯器中構(gòu)建基于圖的中間表示的方法
【技術(shù)領(lǐng)域】
[0001]本發(fā)明涉及一種構(gòu)建圖數(shù)據(jù)結(jié)構(gòu)的方法以及一種將源代碼編譯為在計(jì)算機(jī)系統(tǒng)的處理器上運(yùn)行的可執(zhí)行機(jī)器代碼的裝置。
[0002]特別是,本發(fā)明涉及計(jì)算機(jī)軟件工程領(lǐng)域。具體而言,本發(fā)明涉及一種通過使用中間代碼表示來編譯源代碼的方法和裝置。更具體地,本發(fā)明涉及表示源程序的方法,源程序即為應(yīng)該被編譯為機(jī)器內(nèi)存中的可執(zhí)行機(jī)器代碼的源程序。
【背景技術(shù)】
[0003]編譯計(jì)算機(jī)程序涉及將高級(jí)語(yǔ)言代碼,即源代碼101,轉(zhuǎn)換為計(jì)算機(jī)系統(tǒng)的處理器中的指令109。該流程在圖1中示出。源代碼101由編譯器111編譯為可執(zhí)行程序代碼109。編譯器111基于源代碼101構(gòu)建103中間表示,優(yōu)化105該中間表示并生成107可以用作程序代碼109的可執(zhí)行文件“program.exe”。
[0004]編譯器通常用中間表示以能夠修改而進(jìn)行分析和轉(zhuǎn)換的方式表示源程序。分析和轉(zhuǎn)換通常由編譯器執(zhí)行以優(yōu)化源程序以便進(jìn)行快速執(zhí)行源程序。編譯器本身是一種程序并且以某種語(yǔ)言編寫。通常,開發(fā)編譯器是一項(xiàng)復(fù)雜的任務(wù),該任務(wù)通常被劃分為許多子任務(wù)。在下文中,當(dāng)編譯器以面向?qū)ο笳Z(yǔ)言編寫時(shí)會(huì)考慮上述情況。
[0005]將源程序表示為機(jī)器內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)有多種方式。該數(shù)據(jù)結(jié)構(gòu)通常為基于某種“抽象語(yǔ)法樹”或“圖”的表示。選擇其中之一是眼前具體問題中的重要問題。在本發(fā)明之前,在文檔“C.Click和M.Paleczny,簡(jiǎn)單的基于圖的中間表不(A simple graph-basedintermediate representat1n),1995年”中描述了一種程序的中間表不(intermediaterepresentat1n,]:!?)。該中間表示具有與本發(fā)明相關(guān)的以下兩種屬性:第一,它是基于圖的,即,它是具有存儲(chǔ)在圖節(jié)點(diǎn)中的某些具體信息的“圖數(shù)據(jù)結(jié)構(gòu)”。第二,它可以通過面向?qū)ο笳Z(yǔ)言予以實(shí)現(xiàn)?;趫D的IR的節(jié)點(diǎn)對(duì)應(yīng)于源程序的操作。各條邊對(duì)應(yīng)于操作之間的數(shù)據(jù)流。操作的執(zhí)行順序不由圖明確指定,而是由節(jié)點(diǎn)之間的依賴關(guān)系決定。
[0006]機(jī)器內(nèi)存中基于圖的IR是一種由對(duì)象組成的數(shù)據(jù)結(jié)構(gòu)。下文中它被簡(jiǎn)稱為“圖”。通常,為了構(gòu)建圖,對(duì)象‘Graph’的程序方法被調(diào)用以將新節(jié)點(diǎn)添加到該圖中。圖數(shù)據(jù)結(jié)構(gòu)中的每個(gè)圖節(jié)點(diǎn)由(S,N)對(duì)表示:‘S’是全局唯一標(biāo)識(shí)符,其通常被稱為符號(hào),而該符號(hào)通常只是一個(gè)數(shù)字。所有符號(hào)由類‘Sym’的實(shí)例表示。每個(gè)符號(hào)指它所標(biāo)識(shí)的節(jié)點(diǎn)并且可以用于訪問該節(jié)點(diǎn)。‘N’是從‘Node’類派生出的某個(gè)類的實(shí)例。節(jié)點(diǎn)的具體類表示一種操作。不同的操作由不同的類來表示。操作的類可以形成一種類層次結(jié)構(gòu)。該層次結(jié)構(gòu)中的抽象類表示某個(gè)操作子集。該圖中的各條邊由存儲(chǔ)在節(jié)點(diǎn)中的符號(hào)表示。
[0007]圖2所示為第I行到第5行范圍內(nèi)的示例源程序200。函數(shù)在編譯和運(yùn)行時(shí)計(jì)算數(shù)組中所有數(shù)值的平均值。它如以下所述操作。第I行描繪了函數(shù)“average”,其中‘a(chǎn)rr’是函數(shù)的引數(shù)。當(dāng)調(diào)用該函數(shù)時(shí),參數(shù)‘a(chǎn)rr ’是對(duì)類‘Array〈Float>,的實(shí)例的引用,類‘Array〈Float〉’表示一個(gè)值數(shù)組(或者索引集合)。它是函數(shù)調(diào)用方提供的浮點(diǎn)數(shù)數(shù)組并且應(yīng)當(dāng)由該函數(shù)處理。函數(shù)主體逐步按序執(zhí)行。第2行是使用實(shí)例‘ arr ’對(duì)類‘ Array,的方法‘ sum ’的調(diào)用。該方法計(jì)算該數(shù)組中所有元素的總和。第3行是使用實(shí)例‘a(chǎn)rr’對(duì)類‘Array’的方法‘length’的調(diào)用。該方法計(jì)算該數(shù)組中的元素的數(shù)量。最后,在第4行計(jì)算平均值并返回平均值作為函數(shù)的結(jié)果。第5行所示為源程序200的結(jié)尾。
[0008]圖3所示為圖2中程序的基于圖的中間表示300。參數(shù)‘a(chǎn)rr’301由提供中間結(jié)果‘ sum’ 和 ‘ Ien ’ 的兩個(gè)函數(shù) ‘FloatArraySum(arr),303和 ‘FloatArrayLength(arr),305使用,中間結(jié)果由函數(shù)卞10&七0丨¥(811111,1611)’用于提供最終結(jié)果‘代8’307。
[0009]圖4所示為程序圖的內(nèi)存表示400。第一符號(hào)401與圖3中描述的參數(shù)‘a(chǎn)rr’301關(guān)聯(lián)。第二符號(hào)403與圖3中描述的函數(shù)‘FloatArraySum(arr) ’303關(guān)聯(lián),其中該函數(shù)的引數(shù)在此處對(duì)應(yīng)于第一符號(hào)‘ Sym(I) ’ 401。第三符號(hào)405與圖3中描述的函數(shù)‘FloatArrayLength(arr)’305關(guān)聯(lián),其中該函數(shù)的引數(shù)在此處對(duì)應(yīng)于第一符號(hào)‘Sym(l)’401。第四符號(hào)407與圖3中描述的函數(shù)‘FloatDiv(sum, Ien) ’307關(guān)聯(lián),其中該函數(shù)的引數(shù)在此處對(duì)應(yīng)于第二符號(hào)‘37111(2)’403和第三符號(hào)‘37111(3)’405。符號(hào)401、403、405、407等描述該圖的圖節(jié)點(diǎn)。
[0010]圖5所示為用于將圖表示為機(jī)器內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)的類的編程接口500。編程接口500 定義了 類 ‘ Graph ’ 501、抽象類 ‘ Node ’ 503 和類 ‘ FloatArrayLength ’ 505。類 ‘ Graph ’ 501 包括第一函數(shù)‘Sym addNode(Node node)’,用于將節(jié)點(diǎn)添加到該圖中;第二函數(shù)‘ NodegetNode(Sym symbol) ’,用于按節(jié)點(diǎn)的符號(hào)查找節(jié)點(diǎn);以及第三函數(shù)‘Sym f indNode(Nodenode)’,用于在該圖中找到節(jié)點(diǎn)。抽象類‘Node’ 503包括作為對(duì)該節(jié)點(diǎn)的所有者的引用的圖‘g’,以及返回該節(jié)點(diǎn)符號(hào)的符號(hào)‘nodeSymbol (),。類‘FloatArrayLength’ 505包括符號(hào)‘a(chǎn)rr’,其為表示數(shù)組‘a(chǎn)rr’的節(jié)點(diǎn)的符號(hào)。該圖的節(jié)點(diǎn)對(duì)應(yīng)于源程序的操作。例如,‘FloatArrayLength’對(duì)應(yīng)于程序代碼中的 ‘a(chǎn)rr.length() ’。
[0011]圖6所示為圖構(gòu)建流程600。它是圖3中所示圖的構(gòu)建步驟。在第I行,圖‘g’由函數(shù)‘new GraphO ’構(gòu)建。在第2行,符號(hào)‘a(chǎn)rr ’被設(shè)為函數(shù)‘g.addNode(new VarO ) ’。在第3行,符號(hào) ‘sum’被設(shè)為函數(shù)‘g.addNode(new FI oa t Ar ray Sum (ar r)) ’。在第4 行,符號(hào) ‘ Ien ’ 被設(shè)為函數(shù) ‘ g.addNode(new FI oat Array Length (arr)) ’。在第5行,符號(hào) ‘res ’ 被設(shè)為函數(shù)‘ g.addNode(new FloatDiv( sum,Ien)) ’。該圖的各條邊由存儲(chǔ)在節(jié)點(diǎn)中的符號(hào)表示。例如,‘FloatDiv’節(jié)點(diǎn)保存操作的兩個(gè)操作數(shù)的符號(hào)‘sum’和‘ len’。
[0012]圖1至6所描述的現(xiàn)有技術(shù)顯示了以下兩個(gè)主要問題。第一,大量“樣板代碼”在圖構(gòu)建中使用。即使對(duì)于圖2中所描繪的簡(jiǎn)單程序,使用‘Graph’類的接口來構(gòu)建圖是非常繁瑣的。圖構(gòu)建代碼應(yīng)當(dāng)盡可能看起來接近圖2中所示的源代碼,但是使用類似于圖6所示流程的明確圖構(gòu)建流程是不可能的。第二,代碼難以泛化。當(dāng)考慮泛化圖2中的示例這項(xiàng)任務(wù)時(shí),函數(shù)‘a(chǎn)verage ’不僅應(yīng)當(dāng)處理‘Float ’數(shù)組,還應(yīng)處理含任何類型為‘ T’的元素的數(shù)組,該數(shù)組支持被整數(shù)除。例如,‘Int’、‘Double’、‘Decimal’和其它類型的數(shù)組。一種抽象地形成數(shù)組元素類型的方式將是引入類型參數(shù)‘T’,其產(chǎn)生圖7所示的代碼700。類型為T的函數(shù)‘ average,和引數(shù)‘ Array〈T>arr,和‘Div0p〈T>div ’包括如第2行所示的指令‘ T sum =arr.sum'、如第3行所示的‘Int len = arr.length ',以及如第4行所示的‘ret urndiV.apply(SUm,len)’。這個(gè)泛化代碼具有從除法運(yùn)算抽象得來的額外參數(shù),但是該代碼的總體結(jié)構(gòu)保持與圖2中所描繪的原始樣本相同。
[0013]當(dāng)嘗試對(duì)如圖6中所示的圖構(gòu)建流程進(jìn)行相同泛化時(shí),問題在于代碼包含具體類‘FloatArraySum’、‘F1atArrayLength’和‘FloatDiv’并且這些具體類預(yù)期該數(shù)組包含類型為‘Float ’的項(xiàng)目。如何泛化該代碼并非很清楚。
【發(fā)明內(nèi)容】
[0014]本發(fā)明的目的在于提供一種用于編譯源代碼的改進(jìn)技術(shù),具體而言,提供一種構(gòu)建源代碼的中間表示的子任務(wù)的改進(jìn)技術(shù)。
[0015]此目的可以通過獨(dú)立權(quán)利要求的特征來實(shí)現(xiàn)。其它實(shí)施方式在從屬權(quán)利要求、具體說明和附圖中顯而易見。
[0016]本發(fā)明基于以下觀點(diǎn):如上所述的圖構(gòu)建中的樣板代碼可以通過使用新方法消除,這種新方法允許圖構(gòu)建代碼盡可能看起來接近源程序的源代碼。這種新方法設(shè)計(jì)用于以面向?qū)ο笳Z(yǔ)言實(shí)現(xiàn)“階段性評(píng)估”。這種新方法用于擴(kuò)展現(xiàn)有技術(shù)的基于圖的IR數(shù)據(jù)結(jié)構(gòu),以支持“泛型程序”的階段性評(píng)估,泛型程序即一種類型待定的