第1章 開始制作編譯器 11.1 本書的概要 2本書的主題 2本書制作的編譯器 2編譯示例 2可執行文件 3編譯 4程序運行環境 61.2 編譯過程 8編譯的4 個階段 8語法分析 8語義分析 9生成中間代碼 9代碼生成 10優化 10總結 101.3 使用cь編譯器進行編譯 11cь編譯器的必要環境 11安裝cь編譯器 11cь的hello, world! 12第2章 cь和cbc 132.1 cь語言的概要 14cь的hello, world ! 14cь中刪減的功能 14import 關鍵字 15導入文件的規范 162.2 cь編譯器cbc 的構成 17cbc 的代碼樹 17cbc 的包 18compiler 包中的類群 18main 函數的實現 19commandmain 函數的實現 19java5 泛型 20build 函數的實現 20java 5 的foreach 語句 21compile 函數的實現 21第1部分 代碼分析第3章 語法分析的概要 243.1 語法分析的方法 25代碼分析中的問題點 25代碼分析的一般規律 25詞法分析、語法分析、語義分析 25掃描器的動作 26單詞的種類和語義值 27token 28抽象語法樹和節點 293.2 解析器生成器 30什么是解析器生成器 30解析器生成器的種類 30解析器生成器的選擇 313.3 javacc 的概要 33什么是javacc 33語法描述文件 33語法描述文件的例子 34運行javacc 35啟動javacc 所生成的解析器 36中文的處理 37第4章 詞法分析 394.1 基于javacc 的掃描器的描述 40本章的目的 40javacc 的正則表達式 40固定字符串 41連接 41字符組 41排除型字符組 41重復1 次或多次 42重復0 次或多次 42重復n 次到m 次 42正好重復n 次 43可以省略 43選擇 434.2 掃描沒有結構的單詞 44token 命令 44掃描標識符和保留字 44選擇匹配規則 45掃描數值 464.3 掃描不生成token 的單詞 48skip 命令和special_token 命令 48跳過空白符 48跳過行注釋 494.4 掃描具有結構的單詞 50*長匹配原則和它的問題 50基于狀態遷移的掃描 50more 命令 51跳過塊注釋 52掃描字符串字面量 53掃描字符字面量 53第5章 基于javacc 的解析器的描述 555.1 基于ebnf 語法的描述 56本章的目的 56基于javacc 的語法描述 56終端符和非終端符 57javacc 的ebnf 表示法 58連接 58重復0 次或多次 59重復1 次或多次 59選擇 60可以省略 605.2 語法的二義性和token 的超前掃描 61語法的二義性 61javacc 的局限性 62提取左側共通部分 63token 的超前掃描 63可以省略的規則和沖突 64重復和沖突 65更靈活的超前掃描 66超前掃描的相關注意事項 66第6章 語法分析 686.1 定義的分析 69表示程序整體的符號 69語法的單位 69import 聲明的語法 70各類定義的語法 71變量定義的語法 72函數定義的語法 73結構體定義和聯合體定義的語法 74結構體成員和聯合體成員的語法 75typedef 語句的語法 76類型的語法 76c 語言和cь在變量定義上的區別 77基本類型的語法 776.2 語句的分析 79語句的語法 79if 語句的語法 80省略if 語句和大括號 80while 語句的語法 81for 語句的語法 81各類跳轉語句的語法 826.3 表達式的分析 83表達式的整體結構 83expr 的規則 83條件表達式 84二元運算符 856.4 項的分析 88項的規則 88前置運算符的規則 88后置運算符的規則 89字面量的規則 89第2部分 抽象語法樹和中間代碼第7章 javacc 的action 和抽象語法樹 927.1 javacc 的action 93本章的目的 93簡單的action 93執行action 的時間點 93返回語義值的action 95獲取終端符號的語義值 95token 類的屬性 96獲取非終端符號的語義值 98語法樹的結構 99選擇和action 99重復和action 100本節總結 1027.2 抽象語法樹和節點 103node 類群 103node 類的定義 105抽象語法樹的表示 105基于節點表示表達式的例子 107第8章 抽象語法樹的生成 1108.1 表達式的抽象語法樹 111字面量的抽象語法樹 111類型的表示 112為什么需要typeref 類 113一元運算的抽象語法樹 114二元運算的抽象語法樹 116條件表達式的抽象語法樹 117賦值表達式的抽象語法樹 1188.2 語句的抽象語法樹 121if 語句的抽象語法樹 121while 語句的抽象語法樹 122程序塊的抽象語法樹 1238.3 聲明的抽象語法樹 125變量聲明列表的抽象語法樹 125函數定義的抽象語法樹 126表示聲明列表的抽象語法樹 127表示程序整體的抽象語法樹 128外部符號的import 128總結 1298.4 cbc 的解析器的啟動 132parser 對象的生成 132文件的解析 133解析器的啟動 134第9章 語義分析(1)引用的消解 1359.1 語義分析的概要 136本章目的 136抽象語法樹的遍歷 137不使用visitor 模式的抽象語法樹的處理 137基于visitor 模式的抽象語法樹的處理 138vistor 模式的一般化 140cbc 中visitor 模式的實現 141語義分析相關的cbc 的類 1429.2 變量引用的消解 144問題概要 144實現的概要 144scope 樹的結構 145localresolver 類的屬性 146localresolver 類的啟動 146變量定義的添加 147函數定義的處理 148pushscope 方法 149currentscope 方法 149popscope 方法 150添加臨時作用域 150建立variablenode 和變量定義的關聯 151從作用域樹取得變量定義 1519.3 類型名稱的消解 153問題概要 153實現的概要 153typeresolver 類的屬性 153typeresolver 類的啟動 154類型的聲明 154類型和抽象語法樹的遍歷 155變量定義的類型消解 156函數定義的類型消解 157第10章 語義分析(2)靜態類型檢查 15910.1 類型定義的檢查 160問題概要 160實現的概要 161檢測有向圖中的閉環的算法 162結構體、聯合體的循環定義檢查 16310.2 表達式的有效性檢查 165問題概要 165實現的概要 165dereferencechecker 類的啟動 166semanticerror 異常的捕獲 167非指針類型取值操作的檢查 167獲取非左值表達式地址的檢查 168隱式的指針生成 16910.3 靜態類型檢查 170問題概要 170實現的概要 170cь中操作數的類型 171隱式類型轉換 172typerchecker 類的啟動 173二元運算符的類型檢查 174隱式類型轉換的實現 175第11章 中間代碼的轉換 17811.1 cbc 的中間代碼 179組成中間代碼的類 180中間代碼節點類的屬性 181中間代碼的運算符和類型 182各類中間代碼 183中間代碼的意義 18411.2 irgenerator 類的概要 185抽象語法樹的遍歷和返回值 185irgenerator 類的啟動 185函數本體的轉換 186作為語句的表達式的判別 18711.3 流程控制語句的轉換 189if 語句的轉換(1)概要 189if 語句的轉換(2)沒有else 部分的情況 190if 語句的轉換(3)存在else 部分的情況 191while 語句的轉換 191break 語句的轉換(1)問題的定義 192break 語句的轉換(2)實現的方針 193break 語句的轉換(3)實現 19411.4 沒有副作用的表達式的轉換 196unaryopnode 對象的轉換 196binaryopnode 對象的轉換 197指針加減運算的轉換 19811.5 左值的轉換 200左邊和右邊 200左值和右值 200cbc 中左值的表現 201結構體成員的偏移 202成員引用(expr.memb)的轉換 203左值轉換的例外:數組和函數 204成員引用的表達式(ptr->memb)的轉換 20511.6 存在副作用的表達式的轉換 206表達式的副作用 206有副作用的表達式的轉換方針 206簡單賦值表達式的轉換(1)語句 207臨時變量的引入 208簡單賦值表達式的轉換(2)表達式 209后置自增的轉換 210第3部分 匯編代碼第12章 x86 架構的概要 21412.1 計算機的系統結構 215cpu 和存儲器 215寄存器 215地址 216物理地址和虛擬地址 216各類設備 217緩存 21812.2 x86 系列cpu 的歷史 220x86 系列cpu 22032 位cpu 220指令集 221ia-32 的變遷 222ia-32 的64 位擴展——amd64 22212.3 ia-32 的概要 224ia-32 的寄存器 224通用寄存器 225機器! 226機器棧的操作 227機器棧的用途 227棧幀 228指令指針 229標志寄存器 22912.4 數據的表現形式和格式 231無符號整數的表現形式 231有符號整數的表現形式 231負整數的表現形式和二進制補碼 232字節序 233對齊 233結構體的表現形式 234第13章 x86 匯編器編程 23613.1 基于gnu 匯編器的編程 237gnu 匯編器 237匯編語言的hello, world! 237基于gnu 匯編器的匯編代碼 23813.2 gnu 匯編器的語法 240匯編版的hello, world! 240指令 241匯編偽操作 241標簽 241注釋 242助記符后綴 242各種各樣的操作數 243間接內存引用 244x86 指令集的概要 24513.3 傳輸指令 246mov 指令 246push 指令和pop 指令 247lea 指令 248movsx 指令和movzx 指令 249符號擴展和零擴展 25013.4 算術運算指令 251add 指令 251進位標志 252sub 指令 252imul 指令 252idiv 指令和div 指令 253inc 指令 254dec 指令 255neg 指令 25513.5 位運算指令 256and 指令 256or 指令 257xor 指令 257not 指令 257sal 指令 258sar 指令 258shr 指令 25913.6 流程的控制 260jmp 指令 260條件跳轉指令(jz、jnz、je、jne、……) 261cmp 指令 262test 指令 263標志位獲取指令(setcc) 263call 指令 264ret 指令 265第14章 函數和變量 26614.1 程序調用約定 267什么是程序調用約定 267linux/x86 下的程序調用約定 26714.2 linux/x86 下的函數調用 269到函數調用完成為止 269到函數開始執行為止 270到返回原處理流程為止 271到清理操作完成為止 271函數調用總結 27214.3 linux/x86 下函數調用的細節 274寄存器的保存和復原 274caller-save 寄存器和callee-save 寄存器 274caller-save 寄存器和callee-save 寄存器的靈活應用 275大數值和浮點數的返回方法 276其他平臺的程序調用約定 277第15章 編譯表達式和語句 27815.1 確認編譯結果 279利用cbc 進行確認的方法 279利用gcc 進行確認的方法 28015.2 x86 匯編的對象與dsl 282表示匯編的類 282表示匯編對象 28315.3 cbc 的x86 匯編dsl 285利用dsl 生成匯編對象 285表示寄存器 286表示立即數和內存引用 287表示指令 287表示匯編偽操作、標簽和注釋 28815.4 codegenerator 類的概要 290codegenerator 類的字段 290codegenerator 類的處理概述 290實現compilestmts 方法 291cbc 的編譯策略 29215.5 編譯單純的表達式 294編譯int 節點 294編譯str 節點 294編譯uni 節點(1) 按位取反 295編譯uni 節點(2) 邏輯非 29715.6 編譯二元運算 298編譯bin 節點 298實現compilebinaryop 方法 299實現除法和余數 300實現比較運算 30015.7 引用變量和賦值 301編譯var 節點 301編譯addr 節點 302編譯mem 節點 303編譯assign 節點 30315.8 編譯jump 語句 305編譯labelstmt 節點 305編譯jump 節點 305編譯cjump 節點 305編譯call 節點 306編譯return 節點 307第16章 分配棧幀 30816.1 操作! 309cbc 中的棧幀 309棧指針操作原則 310函數體編譯順序 31016.2 參數和局部變量的內存分配 312本節概述 312參數的內存分配 312局部變量的內存分配:原則 313局部變量的內存分配 314處理作用域內的局部變量 315對齊的計算 316子作用域變量的內存分配 31616.3 利用虛擬棧分配臨時變量 318虛擬棧的作用 318虛擬棧的接口 319虛擬棧的結構 319virtualpush 方法的實現 320virtualstack#extend 方法的實現 320virtualstack#top 方法的實現 321virtualpop 方法的實現 321virtualstack#rewind 方法的實現 321虛擬棧的運作 32216.4 調整棧訪問的偏移量 323本節概要 323stackframeinfo 類 323計算正在使用的callee-save寄存器 324計算臨時變量區域的大小 325調整局部變量的偏移量 325調整臨時變量的偏移量 32616.5 生成函數序言和尾聲 327本節概要 327生成函數序言 327生成函數尾聲 32816.6 alloca 函數的實現 330什么是alloca 函數 330實現原則 330alloca 函數的影響 331alloca 函數的實現 331第17章 優化的方法 33317.1 什么是優化 334各種各樣的優化 334優化的案例 334常量折疊 334代數簡化 335降低運算強度 335削除共同子表達式 335消除無效語句 336函數內聯 33617.2 優化的分類 337基于方法的優化分類 337基于作用范圍的優化分類 337基于作用階段的優化分類 33817.3 cbc 中的優化 339cbc 中的優化原則 339cbc 中實現的優化 339cbc 中優化的實現 33917.4 更深層的優化 341基于模式匹配選擇指令 341分配寄存器 342控制流分析 342大規模的數據流分析和ssa 形式 342總結 343第4部分 鏈接和加載第18章 生成目標文件 34618.1 elf 文件的結構 347elf 的目的 347elf 的節和段 348目標文件的主要elf 節 348使用readelf 命令輸出節頭 349使用readelf 命令輸出程序頭 350使用readelf 命令輸出符號表 351readelf 命令的選項 351什么是dwarf 格式 35218.2 全局變量及其在elf 文件中的表示 354分配給任意elf 節 354分配給通用elf 節 354分配.bss 節 355通用符號 355記錄全局變量對應的符號 357記錄符號的附加信息 357記錄通用符號的附加信息 358總結 35818.3 編譯全局變量 360generate 方法的實現 360generateassemblycode 方法的實現 360編譯全局變量 361編譯立即數 362編譯通用符號 363編譯字符串字面量 364生成函數頭 365計算函數的代碼大小 366總結 36618.4 生成目標文件 367as 命令調用的概要 367引用gnuassembler 類 367調用as 命令 367第19章 鏈接和庫 36919.1 鏈接的概要 370鏈接的執行示例 370gcc 和gnu ld 371鏈接器處理的文件 372常用庫 374鏈接器的輸入和輸出 37419.2 什么是鏈接 375鏈接時進行的處理 375合并節 375重定位 376符號消解 37719.3 動態鏈接和靜態鏈接 379兩種鏈接方法 379動態鏈接的優點 379動態鏈接的缺點 380動態鏈接示例 380靜態鏈接示例 381庫的檢索規則 38119.4 生成庫 383生成靜態庫 383linux 中共享庫的管理 383生成共享庫 384鏈接生成的共享庫 385第20章 加載程序 38720.1 加載elf 段 388利用mmap 系統調用進行文件映射 388進程的內存鏡像 389內存空間的屬性 390elf 段對應的內存空間 390和elf 文件不對應的內存空間 392elf 文件加載的實現 39320.2 動態鏈接過程 395動態鏈接加載器 395程序從啟動到終止的過程 395啟動ld.so 396系統內核傳遞的信息 397aux 矢量 397讀入共享庫 398符號消解和重定位 399運行初始化代碼 400執行主程序 401執行終止處理 402ld.so 解析的環境變量 40220.3 動態加載 404所謂動態加載 404linux 下的動態加載 404動態加載的架構 40520.4 gnu ld 的鏈接 406用于cbc 的ld 選項的結構 406c 運行時 407生成可執行文件 408生成共享庫 408第21章 生成地址無關代碼 41021.1 地址無關代碼 411什么是地址無關代碼 411全局偏移表(got) 412獲取got 地址 412使用got 地址訪問全局變量 413訪問使用got 地址的文件內部的全局變量 414過程鏈接表(plt) 414調用plt 入口 416地址無關的可執行文件:pie 41621.2 全局變量引用的實現 418獲取got 地址 418picthunk 函數的實現 418刪除重復函數并設置不可見屬性 419加載got 地址 420locatesymbols 函數的實現 421全局變量的引用 421訪問全局變量:地址無關代碼的情況下 422函數的符號 423字符串常量的引用 42421.3 鏈接器調用的實現 425生成可執行文件 425generatesharedlibrary 方法 42621.4 從程序解析到執行 428build 和加載的過程 428詞法分析 429語法分析 429生成中間代碼 430生成代碼 431匯編 432生成共享庫 432生成可執行文件 433加載 433第22章 擴展閱讀 43422.1 參考書推薦 435編譯器相關 435語法分析相關 435匯編語言相關 43622.2 鏈接、加載相關 43722.3 各種編程語言的功能 438異常封裝相關的圖書 438垃圾回收 438垃圾回收相關的圖書 439面向對象編程語言的實現 439函數式語言 440附 錄 441a.1 參考文獻 442a.2 在線資料 444a.3 源代碼 445