編譯器,優化,及目標代碼生成.


本文介紹從源文件開始到目標代碼生成的過程.

  • 首先,是我們每天都要接觸的源文件.源文件是由純ASCII或者其他字符集組成的文本,由程序員使用文本編輯器創建.它有以下的幾種形式
    • 純文本.好處是易於維護.並且可以使用處理文本文件的程序來處理源文件.
      • 這個就是我們最常見的源代碼形式了.甚至可以使用notepad來處理源文件!
    • 記號化的源文件.使用專門的單字節"記號"值來表示源文件中的保留字等語句元素.
      • 好處1:尺寸小,由於使用單字節的符號來"壓縮"多字符的保留字,所以比純文本源文件小.
      • 好處2:由於識別單字節比識別多字符高效,所以使得解釋器效率更高.
      • 好處3:基於記號化的源文件,也很容易的構建出原先(或者類似的)文本源文件.
      • 缺陷1:會丟棄空白區域.
      • 缺陷2:引入了專有的格式.不方便使用普通的文本文件處理程序來進行處理.
    • 專門的源文件格式.
      • 使用圖形元素來表示程序要完成的指令.如Delphi等.
  • 源文件編寫完成后,要在計算機上運行,需要使用計算機處理程序來進行處理.主要有以下幾種的處理程序.
    • 純解釋器.
      • 工作方式:直接工作於文本源文件.持續掃描源文件,將其作為字符串進行處理.
      • 問題:沒有效率.在識別"詞素(lexeme)"時的耗時,甚至會大於程序實際的執行時間.
      • 適用場景:1)期望語言處理程序非常緊湊時.2)腳本語言和超高級語言(在程序執行期間將源代碼當做字符串操作).
    • 解釋器
      • 工作方式:運行時,執行源文件的替身.對符號化的源文件(對文本源文件需要進行符號化的轉換)進行操作,省去了執行時的詞素分析.
      • 問題:無法將字符串當做程序語句進行執行.
    • 編譯器
      • 工作方式:在運行之前,先將源文件轉換為可執行的機器碼.
      • 特性:生成的機器指令可以由CPU直接執行.所以運行時,所有的資源都可以用來執行機器碼,而不必浪費時間解析源文件.
      • 問題:源文件到機器碼的轉換是單向的,很難進行逆向的操作.
    • 增量編譯器
      • 工作方式:編譯器和解釋器的交集.將源代碼轉化為某種中間形式.中間形式與原始文件的聯系不緊密,而通常是"虛擬(假想)機器"的機器碼,而不是可以執行在物理CPU上執行的機器碼.然后對虛擬機編寫解釋器,然后它來實際執行代碼.
      • 優勢:虛擬機具有可移植性.而真正的機器碼只能在特定的CPU上執行.這樣是JAVA宣稱的"一次編譯,到處運行".
      • 可以使用"即時編譯"來提升性能.
        • 在運行期間,大部分的事件都花在獲得並解析虛擬機代碼的操作上了.程序執行期間,解釋過程會反復進行.
        • 在首次遇到虛擬指令時,就將虛擬代碼轉換為實際的機器碼,然后在后續過程需要同一語句時省去解釋過程.
        • 這樣就是很多.NET程序首次啟動很慢,而之后速度會變得很快的原因了.
  • 語言處理程序在轉化源文件到目標代碼時,需要經過幾個階段.
    • 詞法分析
      • 掃描程序負責讀取從源文件中找到的字符和字符串數據,並將這些數據分類為表示源文件詞素項的記號.詞素項就是源文件中的字符序列(程序的原子級組件).對每個詞素創建一個小的數據包,記號並將此數據包發往語法分析程序.
      • 此過程可選,語法分析可直接工作於源文件,但是這樣的話,語法分析程序在處理源文件時就得多次引用某記號.通過預處理源文件,將其分類為一系列的記號后,編譯過程就更高效.
      • 將字符串詞素轉化成較小的記號包,掃描程序就能讓語法分析程序將記號按整數值對待,而無需依照字符串進行操作.CPU處理小值整數比字符串高效,而且語法分析要多次引用記號數據,這樣省去很多時間.

      • 在分析階段多次掃描每個記號的語言系統只有純解釋器.所以其很慢.

    • 語法分析
      • 編譯器的一部分.負責檢查源程序的語法語義是否正確,且將記號流(即源代碼)重組為更復雜的數據結構,使之表示程序的意思即語義.
      • 掃描程序和語法分析程序一般以線行方式從頭到尾加工源文件,編譯器通常只讀源文件一次,隨后通過構建表示源代碼的數據結構(AST:抽象語法樹)來隨即訪問引用源文件體.
      • 使得方便地引用程序的不同部分.減輕代碼生成和優化階段的負擔.
    • 中間代碼生成.
      • 不直接轉化為本機機器碼的原因.
        • 1)編譯器的優化階段可以進行某些類型的優化(對中間代碼形式操作較容易).
        • 2)許多編譯器是跨平台的,能生成工作於不同CPU架構的機器碼.然后將所有不依賴於特定CPU的動作放到中間代碼生成階段,只需生成這些代碼一次,而跟特定CPU相關的放到各個執行PC上來進行.
    • 優化階段
      • 通常是消除AST中不必要的項目.
      • 問題:效率的定義是程序對某些資源的最小占用.主要的資源是內存(體積)CPU周期(速度).問題在於:朝着某個目標優化,可能與朝着其他目標的優化措施發生沖突.所以優化是個折中過程,需要犧牲某些次要目標來換取某個合理的結果.
      • 優化對編譯時間的影響:編譯器還得在合理的時間內產生可執行的結構,這是個”NP-完全問題(NP-complete problem):正確解顯然是存在的,但必須經過海量的計算.計算量之大,使得求出正確解沒有可行性.所以我們只能找出可行的近似解”.解決NP-問題所需的時間與輸入量呈指數關系.編譯器使用啟發式和案例性算法來確定生成應采取的轉換.
      • 基本塊,可歸約代碼和優化.
        • 優化時會隨着貫穿程序的控制流跟蹤變量值,該過程稱為數據流分析”.以確定變量:何處尚未初始化,何時包含某值,何時不再被使用,何時對變量值一無所知.優化是固有的緩慢過程
        • 在時間上的讓步:在進行下步前,對一段代碼找尋較多可能的優化辦法.因此編程風格很容易搞糊塗編譯器,使得無法產生最優化.
        • 將源代碼划分為基本塊的序列.基本塊就是順序執行的機器指令序列,除了塊的開始和結束位置外沒有任何分支.確定基本塊的起止:只要有地方時條件分支/跳轉,無條件跳轉,或調用指令就表明該基本塊到頭了.基本塊包含將控制發往別處的指令,該指令后是另一基本塊的開始處.
        • 基本塊使得跟蹤基本塊內對變量及其他數據的操作變得方便.
        • 當兩個基本塊的路徑匯集到同一代碼流時,某變量可能的值的數目就會隨着if語句數量呈指數增長.
        • 即使來自於基本塊的路徑匯集到一起,程序也會經常對變量賦新值,因此編譯器不必跟蹤舊信息.編譯器假設程序不會在每個路徑內都對變量賦予不同值,其內部數據結構也據此構建.
        • 合理的程序會產生可歸約的流程圖”:程序控制流的圖形化表示.圖內,各基本塊的結束處與其傳送控制的基本塊開始處用箭頭連接.
        • 不用Goto的程序是可歸約的.可歸約的程序內的基本塊可縮寫成提綱方式,后者的塊繼承了基本塊內在的特性.提綱方式使得優化程序只需應對數目較少的基本塊,而不是大量的語句.
      • 編譯器常見的優化措施.
        • 常量折疊:在編譯時期就計算出常量或子表達式的值,而不是運行時才發送代碼去計算結果.
        • 常量傳播:如果能確定在前面的代碼中某變量被賦值以常量,那么將要訪問該變量的地方替換成常量值.
        • 死代碼消除:刪除那些與特定源代碼語句(其結果從未被使用過,或者條件塊從不為True)關聯的目標碼.
        • 公共子表達式消除:如果子表達式中變量值並未改變,就將其緩存,而無需在下次出現時重復計算該表達式的值.
        • 強度消弱:采用與源代碼不同的運算符(開銷小)來直接計算出結果.
        • 歸納:許多表達式中某個變量值完全依賴於其他某個變量,這時省去對其新值的計算,或者在循環內將變量值計算與表達式計算合並.
        • 循環不變量:不會隨着每輪循環改變的表達式,只要在循環外一次計算出其結果,然后代碼移動將其移出循環.
      • 控制編譯器的優化.
        • 默認時,編譯器不采取任何優化措施,必須明確地告訴編譯器執行某些優化.理由:
          • 1)優化是漫長的過程;
          • 2)優化后許多調試器不能很好地工作;
          • 3)編譯器的大部分缺陷都在優化程序中.”優化”對不同的人有不同的意義,所以有各種方面的優化.
  • 編譯器的輸出.也就是語言處理程序最終將源文件轉換的結果.大部分的輸出都不是特定CPU能夠執行的.
    • 1)輸出高級語言代碼(可讀,易驗證,跨平台,可利用其他高級語言編譯器的優化程序;但耗費更多的處理時間,高級語言很難高效地映射到底層機器碼).
    • 2)輸出匯編語言代碼(允許嵌入內聯的匯編語言語句來滿足時間嚴格要求的場景);
    • 3)輸出目標文件(需要鏈接器再加工);
    • 4)輸出可執行文件.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM