or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Do you want to remove this version name and description?
Syncing
xxxxxxxxxx
編譯器概論–游逸平
← 返回主頁面
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →2022/1 edit: 近期應該會開始把剩下的補完
Lecture 0 - Why learn Compiler?
注意本課程所提及的內容其實已經稍嫌過時,比較屬於上個世紀的技術,現今編譯器技術發展迅速,此課程內容只佔了非常小的一部分。建議各大學課程可以改用這本〈Engineering a compiler〉作為編譯器課程教材。有興趣更深入了解的建議再額外閱讀 gcc 或是 clang 的文件,或是 LLVM 框架的文件等第一手資料,以及 你所不知道的 C 語言:編譯器原理和案例分析。透過廣泛閱讀才有機會掌握現在迅速變革的技術。
Lecture 1 - Overview
先備課程:正規語言–陳穎平 (計算理論)
此課程著重於圖中 compiler 的部份
Compiler
Why FrontEnd/IR/BackEnd?
Ans: Reuse of Components
假設今天已經做好一個 c/c++ 的compiler,想改寫給Java用,那就只需要更改負責分析程式碼的 Front End 就好了,Back End可以繼續沿用。
同理,假設今天想從 x86 指令集執行換到 arm 指令集上執行,也只需要更改 Back End 就好

Assembler
把組語組譯成一個或多個 object program (不可執行)
Linker
把多個不可執行的 object file merge (例如.o) 起來變成可執行的 object file( 例如 .out/.exe),被引用的函式庫也是在這階段被 link 起來
Loader/Dynamic Linker
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →Others notes
越容易撰寫越有彈性的語言 compiler 要負起的責任就越大,例如需要考慮到各式的語法組合出來的各種 corner cases。
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →Interpreter vs Compiler vs Just-in-time compiler
Interpreter 像是一台 VM
一般我們用的 compiler 是 ahead-of-time compiler
Course project overview
Lecture 2 - Lexical 1
Lexical Analysis(語彙分析)
將輸入的字串分析,切割成數個 token,例如:
if ( b == 0 ) a = b;
,變成KW: if
(
ID
NUM
)
ID
=
ID
SEMI
Token
描述原始碼中一些字串邏輯上的意義的最小單位,為一對 token name 和 attribute 的組合,以下為範例,詳情見課本或作業
,
;
:
[
]
(
)
array
begin
boolean
var1
var2
1
123
348579
"sdkfjh"
"gfgjkhgjhg"
Pattern
一段表達式描述 lexeme 如何對應到 token,可以使用正規語言 (regular expression) 表達式,例如:
[A−Za−z_][A−Za−z0−9_]*
Error Recovery
(非課程重點) 碰到無法分析的錯誤該怎麼處理?
Regular Expression
規則有點多,自己看講義吧,要注意優先度。之前考試有出過給一個特定情境,請寫出能篩選出特定格式的 RE。
推薦一個線上測試 RE 的工具:https://regex101.com/
他還會逐步分析你寫的 RE,展示 test cases 是如何 match 到的
RE 是有能力限制的,並非所有語言都能描述,例如一個
(
就要與一個)
配對或是其他巢狀的敘述是無法使用 RE 描述的,會變成 infinite state machine- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →Interaction between Scanner and Parser
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →Implementation of Lexical Analysis
其中一種方法是使用 Transition Diagram 來描述並使用
while
配switch
實做- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →小問題: 像
if
then
else
這類的保留字會不會被當成一個 identifier? 會!方法一:先放到 symbol table 當成保留字 (reserved word) 存起來
方法二:特別為那些保留字寫 rule (e.g.
if -> KW: if
) 來辨識保留字,不過這樣會跟原本的 rule 有衝突,造成 ambiguity,所以要訂出 rule 之間的優先順序。之後在作業中碰到的方法會是用方法二Lecture 3 - Lexical 2
Finite Automata
輸入一個字串,從 start state 開始照著 transition rules 走,會停在 Final state 的就是 accept 其餘皆 reject。
NFA vs DFA
兩者實質上是等價的,RE 一定可以轉成同等辨識能力 NFA 和 DFA
實做上會採用 NFA 和 DFA 呢? (點擊展開)
DFA,因為一次只有一個 transition 比較好做,但是圖的大小會比 NFA 大指數倍 (理論上)(實際上可能差不多),之後會有詳細分析其中一種儲存 transition 的方法是用 state 對 state 的 transition table,使用查表的方式使用,如此就不用寫一堆
switch
cases。不過有可能會有太多沒使用到的欄位的缺點,之後會介紹另一個比較有效率的儲存方式。不過實際上 regular expression matching engine 實做方法有千百種,依據不同使用場合有不同實做方式,例如 cregex 就是一個值得參考的短小精悍實做
實做 NFA 的麻煩點
但是 NFA 對人類來說比較好建構,比較直覺,所以會先 Tompson's construction 建構出 NFA ,之後再轉成 DFA
Thompson's construction
Trivial- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →Analysis
(n(operators) + n(operands)) * 2
個 stateNFA to DFA
核心概念:合併 epsilon transitions
操作方法:
Subset construction
a
)a
在 move 前後的 set 之間pseudo algorithm:
範例
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →有空再用 graphiz 畫
Analysis
DFA minimization
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →我懶得畫,有空再補
或是看誰要幫我補
Distinguishability between states:
如何辨識兩個 state 可不可以合併:
s
還是t
出發都會做一樣的決定,那他們就是 indistinguishable (equivalent)講義上的定義:
x
distinguishes states
from statet
if exactly one of the states reached froms
andt
by following the path with labelx
is an accepting states
is distinguishable from statet
if there is some string that distinguishes thembb
distinguishes stateA
from stateB
Method
完了才寫一天就又想偷懶了
需要有人斗內食物QQ
Lecture 4 - lex
作業內容暫時先跳過
Lecture 5 - CFG
Lecture 6 - Parsing 1
Lecture 7 - Parsing 2
Lecture 8 - yacc
作業內容暫時先跳過
Lecture 9 - SDT (Semantic Analysis)
SDD/SDT
舉例:算式in-fix轉post-fix
SDD: 看到
expr
oprator
term
就把expr
的 attibute concatenateterm
的 attibute 再 concatenateoprator
SDT: semantic actions,
E.g.
rest -> + term { print('+') } rest 1
把SDD定義的動作實做出來
Synthesis/Inherit Attribute
舉例:以先乘除後加減的計算算式
請參照講義上 parse tree 的箭頭
[待補圖]
Order of evaluate attribute
正常型況下沒有 cycle 的 DAG (的topology sort的所有可能) 才能執行 SDD,這會需要 two pass,也就是先建構完 parse tree 才建構AST。
如果要邊建構 parse tree 邊執行 SDD,會需要對 SDD 做限制
S-attribute
S-attribute 只要用 buttom up 的順序就能計算,所以 buttom up parsing 就可以邊 parse 邊計算。
L-attribute
(derivation rule)只能由左至右傳遞 attribute,避免產生cycle,亦即在 parse tree 中只能由左至右,由上至下傳遞
建立Syntax tree
Implementation of SDT
General SDT implementation
not that general SDT
post-fix SDT: 都放在 body 最右手邊的 action。最簡單實做的SDT。使用一個stack
舉例:用一個stack和多個action處理四則運算。
SDT with action inside productions: 還沒 match 完整條 grammar rule 就執行 action。不是所有這類的SDT都能正常的邊 parse 邊執行。
有問題的SDT在 parsing 的時候會有conflict,亦即在做LR parsing的時候會有conflict
不確定yacc看到有問題的SDT(講義上的舉例)會怎麼做,需要查一下。保守作法就是action都寫在最後面就好了
有問題的SDT還是可以執行的,但是就是沒辦法邊parse邊執行,需要採正常的兩階段執行
消除left recursion why?
L-attributed SDD to SDT
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →Lecture 10 - IR
編譯器的中介語言,需要有IR的原因在 Lecture 1 已經提及了。
IR有high level到low level之分,高的比較接近我們寫的程式碼,低的比較接近machine code
Syntax tree: 把parse tree精鍊過只剩下所需資料的tree
DAG: 一樣leaf都是operand,不過operator不會重複出現,還有GVA(Global Value Numbering)最佳化。產生一個node之前會檢查是不是已經存在了,已經存在了就直接指過去,<ValueNumber , Signature> pair存在hash table裡面來查詢 signature: <op, l, r>
Basic info
之前提到的Three address code (e.g.
t1 = t2 + t3
) 比較接近 machine code表示法,接下來說明一些資料結構來存放three address code課本裡的IR有8種operation,我們這邊以這8種為例
ph1
ph2
ph3
ph4
ph5
ph6
ph7
ph8
不管什麼語言都轉成這8種opration
範例:把Do-while loop轉成IR
using symbolic label/numbering label兩種後者比較接近machine code
選擇允許的IR的operation是一個很重要的設計
IR的資料結構
Quadruple
< op - arg1 - arg2 - result >
three address直接的轉譯的結果
透過temperary存放result
Triple
沒有temperary需要value number來reference其他operation的計算結果
行為上和syntax tree一樣(op, arg1, arg2)
Indirect Numbering
Triple的變形,解決需要reference的問題。多maintain一個array,這個array會存放每個指令,對調指令時是對調array裡面存放指令的順序而不是更動指令本身,所以就不用動reference了
不過大多open source的IR還是quad因為比較直覺(編譯什麼的吃多一點記憶體很正常的吧)
SSA(課本沒有)
一個變數只會被定義一次
所以會需要renaming,如果有重複用到同一個變數的話
不過在condition的時候會有confliction,所以會用phy function來解決(最後轉成machine code的時候會拿掉)
現今open source compiler常用
詳情請見:〈SSA-based Compiler Design〉
Type Checking
在Symantic Analysis的時候會檢查。現在CPU都是control unit和arithmetic-logic unit是分開的,所以data存在哪個相對位址 (storage layout,等等補圖) compiler要先決定好,arithmetic-logic unit 只負責去存取
Static data: 存放的位置不改變,e.g. 全域變數, static variable
dynamic data: e.g.
malloc
,new
, local variableType Expression:表示型別的方式, variable, function都有,在動態語言裡面甚至有type variable在type expression裡面來攜帶型別資訊。儲存上可以用graph來儲存
什麼叫做「一樣」的型別?
Storage layout of Names
看到變數宣告就知道要分配多少空間、放在哪,再存放到symbol table,下次要存取變數就查表,直接去那個位置拿資料
當存取資料的位址不能被4(在一次存取4 byte的平台上而言,帶補充)整除時,就會多耗很多operation去拿資料,例如一次拿出來之後再抽絲剝繭拿出你要的
在traverse parse tree的時候用SDT產出相關資料
以上在你做完作業4之後會很有感覺
Translation of Expressions
用SDD定義看到各express的grammar rule該怎麼做
array的記憶體擺放方法,這個是compiler決定好的,像fortran這種row major的擺法或是C這種column major
存取方法: base + offset
兩種Type checking
有Overloading時該怎麼知道在用哪個?
一樣是作type checking,每個東西都有type expression,checking完一樣的就用他。Template function也是一樣的道理,檢查傳進來的參數的型別
e.g. function的type expression可以長這樣
\[ (for\ all)\ a\ list(a) -> integer \]
input -> output
Compiler正規化推斷型別的流程 <–我覺得這部份會考歐
用已知的資訊推導未知資訊
(帶補講義圖p.62)
題外話:Just In Time compiler 也是需要先做 type inference
Control flow Statements
Boolean expression
short circuit expression
缺點:
SDD for Boolean expression
backpatching: 把label換成instruction編號
Lecture 11 - Runtime
Lecture 12 - Code Generation & Code Optimization
Compiler 最有趣的地方都在這邊
參考資料
Lectuer 13 - Controlflow
← 返回主頁面
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →廢話
G_G …
我怎麼寫起來都像廢話,排版也亂七八糟
之後有空慢慢寫
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →2022 - March -
那明年來上這個好了
How to compile C/C++ for WASM, pure Clang, no libs, no framework
https://github.com/ern0/howto-wasm-minimal
或是參考 你所不知道的 C 語言:編譯器原理和案例分析,從最佳化開始講之類的,至少用現代化一點的教材
參考資料
LLVM
聽過 GCC 就也要聽過 LLVM