在前面的旅程中,我們已經實作了整個的編譯器前端,我們也知道,前端的目標是將源代碼轉變為抽象語法樹,以供后端使用,從這一章開始,我們就要前往后端世界一探究竟了,現在,就讓我們來看看編譯器后端到底由哪些組件組成,其分別又是在做什么吧,
1. 編譯器后端的結構組成
不同于編譯器前端,編譯器后端并不是一個嚴格的流水線式結構,我想,用“A服務于B”這樣的形容是更為貼切的,在CMM編譯器的后端中,主要包含了語意分析器和代碼生成器這兩個組件;此外,由于虛擬機套件和后端關系密切,故我們這里也將其一起展示,請看下圖:
+-----------+
抽象語法樹 -> | 語意分析器 | -> 符號表
| +-----------+ |
| |
| v
| +-----------+ +-------+
+-----------------> | 代碼生成器 | -> 低級指令 -> | 虛擬機 |
+-----------+ +-------+
2. 什么是語意分析器
要回答這個問題,首先要討論的是:什么是語意?語意,說白了就是“一句話的意思”,在日常生活中,我們往往會聽到“每個字我都看得懂,但是我不知道這是在說什么”這樣的形容,這就是語意出現了問題導致的,在編程語言中也是一樣,有的代碼可能完全符合語法,但其仍然是錯誤的,比如:將兩個不能相加的型別進行相加,就屬于語意錯誤,因為在語法分析器看來,只要代碼滿足“A + B”,而不是“+ A B”、“A B +”或是什么別的錯誤寫法,就是符合語法的,也就是說,語法分析器對代碼的檢查能力并不能滿足編程語言中的全部要求,缺失的部分就需要由語意分析器來彌補,
語意分析器不僅僅是一個用于錯誤檢查的組件,其還負責另一項非常重要的作業:生成符號表,什么是符號表呢?符號表就是記錄抽象語法樹中任何你想額外記錄下的東西的表,這主要包括變數名、函式名、陣列大小等,以服務于代碼生成器,
我們將在語意分析器的相關章節進一步講述語意分析器和符號表的故事,
3. 什么是代碼生成器
代碼生成器,顧名思義:生成代碼的組件,代碼生成器一手拿著前端生成的抽象語法樹,一手拿著語意分析器生成的符號表,背包里還裝著諸如語法定義,指令集定義等物品,最終生成了可供虛擬機執行的低級指令,代碼生成器是整個編譯器中實作最為復雜,需要考慮的方面最多的部分,我們也將在代碼生成器的相關章節中走過相當長的一段旅程,
4. 什么是虛擬機
代碼生成器生成的代碼多種多樣:對于有的編譯器實作,其代碼生成器直接生成匯編語言代碼;而對于包括CMM編譯器在內的另一類編譯器,其代碼生成器生成的是編譯器作者自行設計的低級指令,這些低級指令就需要專門的虛擬機來執行,計算機執行機器指令,而虛擬機執行類似于機器指令的另一套指令,“虛擬機”因此得名,對于一個虛擬機來說,其自身模仿了計算機的硬體結構,也具有和管理暫存器、記憶體等“物理設備”,在真實的編譯器設計中,虛擬機是一個高度復雜的組件,但在CMM的編譯器實作中,我們設計了一套極為精簡的指令集和一個非常簡單的虛擬機,
我們將在虛擬機的相關章節進一步講述指令集和虛擬機的故事,
5. 給讀者的閱讀建議
不同于編譯器前端,編譯器后端的各組件之間相互聯系,共同完成目標,故編譯器后端各章節的閱讀是沒有嚴格的順序之分的,而更像是一種“并行閱讀”,如果你對某個地方為什么要這樣實作,或為什么需要某個東西不能理解,那就看看其他組件的相關章節吧,由于代碼生成器是整個編譯器后端的核心,故出于邏輯順序考慮,本文作者將這部分章節放在了最后講述,
接下來,就讓我們首先來看看語意分析器是怎么實作的,符號表又是什么樣子的吧,請看下一章:《實作語意分析器》,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/261227.html
標籤:C++
下一篇:題解 P1650 田忌賽馬
