# 編譯器設計
###### tags: `資工系課程`
## CH1
### Compiler(編譯器)
![](https://i.imgur.com/x4b06ss.png)
翻譯與產生執行檔
### Interpreter(直譯器)
![](https://i.imgur.com/215L7qd.png)
翻譯與直接執行
### Interpreter vs. Compiler
![](https://i.imgur.com/jT7waA2.png)
- Interpreter通常比較慢,因為要同時做兩件事
- Interpreter可以給比較明確的錯誤訊息,因為執行有問題就停住,會知道哪裡有問題
### The Structure of a Compiler
![](https://i.imgur.com/A9RY6Ra.png)
每個部分稱為phase,需要的部分都可以存在symbol-table中,phase有需要就可以去拿。
可以把很多的phase組合起來,像是front-end中的phase組合起來變成pass,就稱為front-end pass。
#### Lexical Analysis
會做詞彙上的分析,切出每個word
![](https://i.imgur.com/o11NXFy.png)
**Token: <token-name, attribute-value>**
token-name:類別
attribute-value:屬性,通常會用指標指到某個symbol table
![](https://i.imgur.com/3uK4WI5.png)
#### Syntax Analysis
進行語法檢查、並構建由輸入的單詞組成的資料結構
![](https://i.imgur.com/MHNsm76.png)
#### Semantic Analysis
會做語意上的分析,看是否符合程式語言的規範
![](https://i.imgur.com/QH5Aqk8.png)
![](https://i.imgur.com/y6eZacA.png)
#### Intermediate Code Generation
產生中間表示式,兩個重要的特性1.Easy to produce 2.Easy to translate into the target machine
![](https://i.imgur.com/nLQcedU.png)
![](https://i.imgur.com/qgiLUg7.png)
#### Code Optimization
做程式碼的優化
![](https://i.imgur.com/9ezvWXF.png)
#### Code Generation
輸出組合語言
![](https://i.imgur.com/4wFncHg.png)
#### summary
![](https://i.imgur.com/h180YEl.png)
![](https://i.imgur.com/BUvbTYh.png)
### Metalanguages
**a language used to describe,define, or discuss another language**
舉例來說一些compiler tool會需要有一些規範,這些規範用的語言就是metalanguages
![](https://i.imgur.com/aXedL5W.png)
## CH3
### Lexical Analyzer and Parser
![](https://i.imgur.com/3J9kiyp.png)
Lexical analyzer會做出一個一個token,後一個parser(syntax analysis)會主動地要求這些token,並且這兩個偶爾會到symbol table去放資料
### Token
![](https://i.imgur.com/5UO0w2C.png)
token是程式語言語法的最小單位
可將token分類成有限的一連串的token type。
### Pattern
描述token長什麼樣子
![](https://i.imgur.com/Q0zRRMo.png)
### Lexeme
實際上的樣子
![](https://i.imgur.com/hlv1BVh.png)
![](https://i.imgur.com/HvaPjaX.png)
![](https://i.imgur.com/WMw8YW5.png)
### Problems When Recognizing Tokens
![](https://i.imgur.com/7Hzmrry.png)
有的時候需要往後多看幾個才能決定怎麼切
### Concatenation
![](https://i.imgur.com/vGeGlp9.png)
### Kleene Closure
![](https://i.imgur.com/hcNeozX.png)
從 L 中取出任意數量的字符串(可能沒有)形成的字符串集合,可能有重複並連接所有這些字符串。
### Regular Expression (RE)
- A language allows us to use a finite description to specify a (possibly infinite) set
- **RE is the metalanguage used to define the token types of a programming language.**
![](https://i.imgur.com/2h0EadN.png)
![](https://i.imgur.com/Iy7HodO.png)
還有一堆例子,請參考簡報
### Regular Definition
Names for regular expressions
類似於給綽號
![](https://i.imgur.com/YIHZNXJ.png)
C identifiers are strings of letters, digits, and underscores.
### Notational Abbreviations
![](https://i.imgur.com/AGIqtQx.png)
[^abc] 除了a或b或c之外的都可以
[a-z] 如果是連續的就用-代替
![](https://i.imgur.com/HTWjOND.png)
[0-9]+ 至少要有一個
[0-9]* 可能沒有
### Finite Automata
#### Nondeterministic Finite Automata (NFA)
S: a finite set of states(state是有限的)
∑: a finite set of input symbols(symbols有限)
δ: a transition function that maps (state, symbol) pairs to sets of states(當你在某個state遇到某些symbol就會跑到其他的state)
範例1:
![](https://i.imgur.com/u0rVQDP.png)
NFA可接受
![](https://i.imgur.com/MmI2Xo0.png)
NFA不可接受
![](https://i.imgur.com/5DErEur.png)
範例2:
![](https://i.imgur.com/UleCPqS.png)
![](https://i.imgur.com/GnJqreL.png)
#### Operations on NFA states
ε-closure(s):可以瞬間移動到某一個state
ε-closure(S):可以瞬間移動到某一些state
move(s, c): set of states to which there is a
transition on input symbol c from a state s
move(S, c):與上方同理
![](https://i.imgur.com/ppZK0uW.png)
#### NFA pseudo code
![](https://i.imgur.com/TJtauez.png)
練習:
![](https://i.imgur.com/n2CqYBw.png)
### Deterministic Finite Automata (DFA)
S: a finite set of states
∑: a finite set of input symbols
**δ: a transition function that maps (state, symbol) pairs to a state in S**
s0: a state distinguished as start state
F: a set of states distinguished as final state
#### DFA與NFA不同
- No state has an ε-transition
- **For each state s and input symbol a, there is at most one edge labeled a leaving s**
![](https://i.imgur.com/x4y4hHr.png)
一個label a在一個state只有一條或是0條路
#### example
![](https://i.imgur.com/wdsqHXz.png)
#### DFA可接受
![](https://i.imgur.com/oav29zM.png)
#### DFA不可接受
![](https://i.imgur.com/owHI0a0.png)
#### DFA pseudo code
![](https://i.imgur.com/Q3N6bWj.png)
### Combined Finite Automata
![](https://i.imgur.com/alK9S5Q.png)
NFA只要用ε move就可以滿足三種狀況
![](https://i.imgur.com/0yEQwDb.png)
碰到iffail+可能會有問題,所以應該要match到最長的那個
解決方法:
![](https://i.imgur.com/KwM4AF4.png)
P是指該字元在字串中的第幾個位置
### From a RE to an NFA
![](https://i.imgur.com/wGIfFOK.png)
i表示start state,f表示final state
![](https://i.imgur.com/doAyv15.png)
最下方的路徑代表可能什麼都沒有,最上方的代表可能會繞很多次,中間兩個代表可能只有一次
![](https://i.imgur.com/FeKQKOG.png)
### NFA to DFA
Example:
![](https://i.imgur.com/Ggnsboq.png)
![](https://i.imgur.com/O7f7CMh.png)
![](https://i.imgur.com/ZO1Ge5Y.png)
Pseudo code
![](https://i.imgur.com/19EXRxN.png)
Dstates為上方大寫的ABCDE
### Minimizing the Number of States
Example
![](https://i.imgur.com/G7XuQac.png)
拆分流程
![](https://i.imgur.com/IbkJ3nS.png)
E跟其他人不一樣是因為是final state
D跟其他的不一樣是因為只有他可以到final state
因為AC遇到ab之後的反應是一樣的所以為一組
縮減結果
![](https://i.imgur.com/JlVhZGS.png)
### Recognize Lexemes
![](https://i.imgur.com/NfaKWa1.png)
## CH4
### Syntax Error Handling
目標:
- It should report the presence of errors clearly and accurately.(處理語法上錯誤時應該要精確且快速)
- It should recover from each error quickly enough to be able to detect subsequent errors.(錯誤可能會有很多,發現錯誤時要很快偵測,後續的也是趕快抓出來)
- It should not significantly slow down the processing of correct programs.(抓錯不該拖慢編譯的效率)
### Error Recovery Strategies
#### Panic mode
在發現錯誤時,parser一次丟棄一個輸入符號,直到找到一個synchronizing
tokens(像是分號),然後就重新再繼續檢查。
#### Phrase level
遇到錯誤的時候,替換一個能讓目前parser執行下去的符號,例如把逗號換成分號
#### Error production
清楚語法規則,把最有可能出錯的地方,寫成 production rules
例如知道正確的語句語法為 $<stat> → <id><=><expr><;>$
預知錯誤的形式可能是少「=」或「;」
$<stat> → <id>error<expr><;>$
$<stat> → <id><=><expr>error$
#### Global correction
- 嘗試以最低修正次數將有錯誤的輸入改成正確的
- 最接近的正確程式可能不是programmer的想法,所以還是得告訴programmer做了什麼樣的修正,並且讓programmer決定
### Context-Free Grammars (CFG)
可以用context-free grammars描述語法
#### 優點
- 能精確描述程式語言
- 已證明若某些context-free grammars符合特定限制,我們便能找到工具自動產生parser
- 用設計良好的 grammars轉譯target code/機器碼比較方便
- 新的語法很容易更新加入現有的grammars
#### 一些定義
**G = (VN, VT, P, S)**
- VN為nonterminals可用來表示a set of strings
- VT為terminals是basic symbols (token types)
- A set of productions P: rules specifying how the terminals and nonterminals can be combined to form strings
- The start symbol S: a distinguished nonterminal that denotes the whole language
舉例:
![](https://i.imgur.com/J6K2nZM.png)
![](https://i.imgur.com/PvhMTjH.png)
#### Derivations推導
推導基本上是一系列生產規則,以獲取輸入字符串
S => … => a
or S =>* a
S =>+ a
![](https://i.imgur.com/xGTB8kA.png)
### Scanner and Parser
![](https://i.imgur.com/a2Xks59.png)
### Notational Conventions
看一下就好
![](https://i.imgur.com/2zOUrJp.png)
![](https://i.imgur.com/h0yjCfK.png)
![](https://i.imgur.com/F3ID9o5.png)
### CFG v.s. RE
- CFG也可以描述RE描述的東西
- CFG雖然比較強大,但RE更簡單理解及對於lexical analyzers更有效率
### Construct the CFG from a NFA
1. 每個NFA的state i 會產生nonterminal Ai
2. If state i has a transition to state j on input a, add the production Ai → aAj(如果state i在碰到a時有transition到state j 則新增production Ai → aAj)
3. If state i goes to state j on input ε, add the production Ai → Aj(如果i到j之間有ε,新增production Ai → Aj)
5. If i is an accepting state, add Ai → ε(如果i是accepting state又可稱final state,就新增Ai → ε)
6. If i is the start state, make Ai be the start symbol of the grammar(如果i是start state,則Ai就是start symbol)
### Parse Trees
- root為start symbol
- 每個最底層的葉子都由一個token標記或是ε
- 每個中間的node都是nonterminal,也就是最底層是terminal
**Example**
![](https://i.imgur.com/pbn0tLK.png)
### Three General Types of Parsers for Grammars
都是由左而右去看input
**Universal**
- Can parse any grammar
- Too inefficient to use in production compilers
**Top-down**
- Build parse trees from the top to the bottom
**Buttom-up**
- Build parse trees from the bottom to the top
### Push Down Automata (PDA)
- We will use $ to represent the end-of-file
marker
- We will also use $ to represent the bottom of stack maker
**example**
![](https://i.imgur.com/wCpFEJb.png)
a↓表示push到stack中 (a, $)表示遇到a且stack的top為 $則做下方的事
### Top-Down Parsing
![](https://i.imgur.com/FMFYSIz.png)
目標是cad,要挑對的prodection rule使得變為cad
第三個還沒有錯誤,所以不用backtrack
### Predictive Parsing
是top-down的parsing並不需要backtracking
因為會偷偷看下一個token是什麼所以就會知道production要選哪個
![](https://i.imgur.com/FX3AhfG.png)
像是知道是if就會猜到後面有then else這些
也被稱為LL(k) parsing,第一個L代表input掃描是從左到右,第二個L代表leftmost derivation(之後要修改都是選最左邊的)
K代表會提前多看K個lookahead
#### LL(1) Parsing
有兩種實作方式
- Recursive-descent parsing
- Table-driven predictive parsing
### Recursive Descent Parsing
![](https://i.imgur.com/w39gQwU.png)
S有三個選擇、L有兩個、E有一個選擇,一開始S先選begin那個之後L選S;L
再來S選Print、最後E就是num
![](https://i.imgur.com/F9Is6Nu.png)
FOLLOW是指看緊跟在L後面的有誰,因為看這個才知道L是不是變成ε,且因為begin L end那行,所以如果L變ε就代表可以直接看到end,因此這樣就可以知道L是不是變ε
```c=
const int IF = 1, THEN = 2, ELSE = 3,
BEGIN = 4, END =5, PRINT = 6,
SEMI = 7, NUM = 8, EQ = 9;
int token = scanner();
void match(int t)
{
if (token == t)
token = scanner();
else
error();
}
void S() {
switch (token) {
case IF: match(IF); E(); match(THEN); S();
match(ELSE); S();
break;
case BEGIN: match(BEGIN); L();
match(END);
break;
case PRINT: match(PRINT); E();
break;
default: error();
}
}
void L() {
switch (token) {
case IF:
case BEGIN:
case PRINT: S(); match(SEMI); L();
break;
case END: break;
default: error();
}
}
void E() {
switch (token) {
case NUM: match(NUM); match(EQ);
match(NUM);
break;
default: error();
}
}
```
### Computing First Sets
![](https://i.imgur.com/BwLocWF.png)
第三點在講如果First(x)是Yi,代表Yi之前的全部都是ε才有可能這樣,並且First(Yi)為a,所以First(x)裡面也有a;如果整個都有可能不見(Y1~Yk)則ε就會加進First(x)中
![](https://i.imgur.com/I6GmF1l.png)
第二點是如果要看follow(B)就要看First(β)中除了ε以外的
第三點是指如果今天A可以推到αB,就代表Follow(A)也會在Follow(B)中。舉例如果今天有Aa這個東西,follow(A)就為a,且A可以替換掉,最後變成αBa,所以Follow(B)=中就有a
![](https://i.imgur.com/qjU2vrV.png)
Follow(E)的部分是因為S可以推到Print E,因此S的follow也會在E的follow裡面;另外因為S是start symbol所以會有錢字號。
### Table-Driven Predictive Parsing
![](https://i.imgur.com/fUB0QP5.png)
因為L->S;L所以First(L)中就有First(S)的,另外因為L->ε所以要看有沒有碰到Follow(L)也就是end的部分
![](https://i.imgur.com/apKzeIq.png)
就是看stack中的top對應到input第一個詞之後再參考上面的表格對應的句子,之後替換掉stack中的top,如果stack(top)==input(top)則pop出變成matched中的詞
![](https://i.imgur.com/LJzlq5s.png)
**講義後還有一個例子可以參考練習(推薦要看,因為好難)**
### LL(1) Grammars
A grammar is LL(1) iff its predictive parsing table has no multiply-defined entries(不能有多個rule)
![](https://i.imgur.com/T3lE7gB.png)
第一點是若兩個有重複的為{y} 則今天A遇到y時,要把A->α跟A->β都填進去
範例:
![](https://i.imgur.com/8mL11zH.png)
Ambiguous Grammars 範例:
![](https://i.imgur.com/4kx20xW.png)
Solution:
![](https://i.imgur.com/W972zBK.png)
### Left Recursive Grammars
![](https://i.imgur.com/yUY2OWf.png)
可以改寫成
![](https://i.imgur.com/M856J2S.png)
範例:
![](https://i.imgur.com/SQUJcbN.png)
![](https://i.imgur.com/WtOK2pr.png)
### Left factoring
![](https://i.imgur.com/1kiYaqn.png)
有common的部分可以等到之後再決定不一樣的地方是誰
範例:
![](https://i.imgur.com/AWKVlQZ.png)
### Error Handling in Predictive Parsing
自行看講義p95
## CH5
### Definition
syntax-directed definition是指context-free grammar加上semantic attributes及semantic rules
semantic rules:是用來計算attributes的規則
Each grammar symbol is associated with a set of semantic attributes
![](https://i.imgur.com/aibxEuI.png)
#### Semantic Attributes
attribute如果是synthesized表示他從children拿值來計算得到的
如果是inherited則從parent and siblings拿值來計算得到的
Terminals can have synthesized attributes, **but not inherited attributes.**
#### Attribute Grammar
An SDD (syntax-directed definition) without side effects is sometimes called an attribute grammar(沒有做其他額外的事:add an entry into symbol table, generate intermediate code,...)
### Annotated Parse Trees
A parse tree, **showing the value(s) of its
attribute(s)** is called an annotated parse tree
![](https://i.imgur.com/4ubL77z.png)
![](https://i.imgur.com/tpFgkJz.png)
值都是從children過來
### Inherited Attributes
Example1:
![](https://i.imgur.com/skhyooA.png)
![](https://i.imgur.com/qeDhEGF.png)
![](https://i.imgur.com/9VBQTfm.png)
Example2:
![](https://i.imgur.com/41NT1AE.png)
![](https://i.imgur.com/unue6Zr.png)
![](https://i.imgur.com/I2xwyUu.png)
### Semantic Rules
![](https://i.imgur.com/oaE90kj.png)
### Dependency Graphs
![](https://i.imgur.com/Mpy38tK.png)
![](https://i.imgur.com/0yfPYnb.png)
![](https://i.imgur.com/MhP7ZBY.png)
### S-Attributed Attribute Grammars
grammar is S-attributed if it uses **synthesized attributes exclusively**
![](https://i.imgur.com/CKQtKIG.png)
### L-Attributed Attribute Grammars
grammar is L-attributed if each attribute computed in each semantic rule for each production is a **synthesized attribute, or an inherited attribute**
舉例:A → X~1~ X~2~ … X~n~
1. the attributes of X~1~, X~2~, …, X~j-1~, 1<=j<=n
2. the inherited attributes of A
![](https://i.imgur.com/i7w8sWW.png)
### Translation Schemes
Syntax-directed translation scheme (SDT):
A translation scheme is a context-free grammar in which program fragments called **semantic actions**(有包含動作,用大括號刮起來) are embedded within the right sides of productions
![](https://i.imgur.com/8tnzg4u.png)
SDT會很清楚告訴你什麼時候要做這些動作以及順序關係
![](https://i.imgur.com/SOudPaK.png)
下面的為SDT,上面是SDD
### An Example - Translation
![](https://i.imgur.com/YrnFFs9.png)
![](https://i.imgur.com/HuJrVIT.png)
![](https://i.imgur.com/wCLTo2H.png)
![](https://i.imgur.com/knq9BQC.png)
因為T()有回傳值,所以透過tnptr去接;ri=tnptr為大括號的動作
rs為R()的回傳值,ri為R()需要的傳入參數
![](https://i.imgur.com/XBvasVW.png)
syntax_tree_node * R(syntax_tree_node * i) 會有括號中的東西是因為會有傳入參數
![](https://i.imgur.com/DbQif83.png)
### Syntax Tree
Use a data structure AST (abstract syntax tree)to **serve as the central data structure** for all post parsing activities
In a syntax tree, operators and keywords do not appear as leaves
![](https://i.imgur.com/64KIF7Y.png)
![](https://i.imgur.com/Ltd59DX.png)
![](https://i.imgur.com/0UIv0gS.png)
### An Example: Syntax tree for “a-4+b”
![](https://i.imgur.com/fL2R1G8.png)
![](https://i.imgur.com/RCjhAQN.png)
### Type Declarations
![](https://i.imgur.com/3hDMLqe.png)
![](https://i.imgur.com/SdLejI0.png)
![](https://i.imgur.com/QwOXdpu.png)
statement 幾乎都有先檢查,再指派S的type
## CH6
### Three-Address Code(Pseudo Assembly Code)
==There is at most one operator on the right side of an instruction==
![](https://i.imgur.com/bGinRtV.png)
![](https://i.imgur.com/ardft3D.png)
#### Types of Three-Address Code
![](https://i.imgur.com/Wzzlpzt.png)
![](https://i.imgur.com/FFKXnjb.png)
![](https://i.imgur.com/cKmq0fK.png)
### Implementation of Three-Address Code
![](https://i.imgur.com/vcADGkG.png)
優化很容易,因為資訊都存起來很清楚,但有點浪費空間
![](https://i.imgur.com/CZEHsCu.png)
這個的result被移除,但會用index描述一些argument像是1的arg2
節省空間
![](https://i.imgur.com/McGfW9r.png)
方便後續compiler在優化的時候調整用,直接調整instruction的資料結構就好,不用動到其他地方
![](https://i.imgur.com/Quy7JD9.png)
每個變數只會被define一次,執行效能會比較好,以及可以得知某個變數在哪裡被define的訊息,對compiler優化分析很重要
#### Example
![](https://i.imgur.com/1zDkyvm.png)
要將t2移動到t3跟t4之間,但不能直接交換表格中的東西,因為可能會影響到index
![](https://i.imgur.com/FuECApz.png)
需要scan一遍受到影響到index 1跟index 2並修改
![](https://i.imgur.com/tnjoOKE.png)
但如果是inderect只要改instruction的表格就好
### Three-Address Code for Expression
![](https://i.imgur.com/UjULr1A.png)
a = b + -c;的範例
![](https://i.imgur.com/8l0Kf82.png)
![](https://i.imgur.com/FDuAdlD.png)
被遮住的部分
### Array Accesses
![](https://i.imgur.com/rmCzoQ0.png)
low是array最開始的index,w是每個element的長度
A[2][3]代表的是長的有兩條,裡面的每格就是放[3]所以可以切成3格
#### Example
![](https://i.imgur.com/hQnGNeT.png)
![](https://i.imgur.com/NPEYRtG.png)
![](https://i.imgur.com/rPD9obz.png)
![](https://i.imgur.com/qRcP18H.png)
左邊那些cdoe都是gen的東西,i是* 4是因為int是4bit
另一個例子
![](https://i.imgur.com/C3oSGRU.png)
three address code:
![](https://i.imgur.com/cVjYNm1.png)
### Type Conversion
#### Widening conversions
![](https://i.imgur.com/bjMw9NI.png)
較低的可以轉成較高的type
#### Narrowing conversions
跟上面的相反
### Example
if (a < b) v=a;
![](https://i.imgur.com/rCtjUv6.png)
![](https://i.imgur.com/p1VbPkH.png)
![](https://i.imgur.com/IV6rfFp.png)
[詳細過程](https://youtu.be/oNsUKuJ8zYw?t=1006)
three address code
![](https://i.imgur.com/72NNSiX.png)
自己練習:
![](https://i.imgur.com/QnH0Ajn.png)
## CH7
### runtime enviroment
需要負責
1. source program中命名的對象的存儲位置的佈局和分配。
2. 目標程序用於訪問變量的機制
3. 程序之間的聯繫
4. 傳遞參數的機制
5. 操作系統接口、輸入/輸出
6. 設備和其他程序(loader / exit)。
![](https://i.imgur.com/7hFwtgd.png)
### Environment and State
![](https://i.imgur.com/Pkyg8o8.png)
### Name Binding
When an **environment** maps name x to **storage**
location s, we say **“x is BOUND to s”**
Assignments change the state, but NOT the environment:
pi := 3.14
changes the value held in the storage location for pi, **but does NOT change the location** (the binding) of pi
### Example1
![](https://i.imgur.com/tJTHpuG.png)
### Example2
![](https://i.imgur.com/01UPlCA.png)
因為char是1byte,所以offset+1 c就從1開始,int是4
![](https://i.imgur.com/UBumxsG.png)
因此struct的部分加起來是5,又前面a的部分是int,所以offset=4,E的部分從4開始
![](https://i.imgur.com/ZnpshWp.png)
d就從4+5(sturct的)開始
![](https://i.imgur.com/RlWtirI.png)
### Scope
![](https://i.imgur.com/aRsrQh5.png)
大括號代表一個區域,所以中間紅框的找不到x才會去外面找,紅框下一段的則是找原本第一個表格,而不是找紅框中的
#### Scope : Nested blocks
![](https://i.imgur.com/iOhFx2O.png)
![](https://i.imgur.com/BqgSPwA.png)
B2為最裡面那層,有w2, y2, z2那個,B1為第一行那層 B0應該是顯示的程式碼以外還有別的。
找東西是先從自己那層找,再往上去找
### Activations
==Every execution of a procedure is called an **ACTIVATION**==
#### Activation Tree
顯示The activations of procedures during the running of an entire program.
**Each node corresponds to one activation**
順序是從左到右開始看,且右要等左執行完
![](https://i.imgur.com/dh9cmEv.png)
![](https://i.imgur.com/fMzAwWR.png)
一開始呼叫read 之後呼叫qicksort,再呼叫partition以及兩個qicksort
#### Control Stack
We can use a stack to keep track of **currently active activations**
control link:指向caller的activation record
access link:定位被調用過程所需但在其他地方找到的數據e.g. in another activation record
![](https://i.imgur.com/oX75doS.png)
main還沒執行結束所以不會不見
![](https://i.imgur.com/5p3NGoS.png)
#### Example
![](https://i.imgur.com/apsA0RU.png)
![](https://i.imgur.com/dpn9oVl.png)
c的步驟因為partition最接近qicksort那層所以access link指到q
### Garbage Collection
Data that cannot be referenced is generally known as garbage.
![](https://i.imgur.com/oo6CpMr.png)
大致就是可以root可以access到的做記號,剩下沒做記號的都是垃圾
## CH8
### Basic Block
![](https://i.imgur.com/MDzhdXs.png)
![](https://i.imgur.com/M8DneQY.png)
leader到碰到下個leader之前都是一個block
![](https://i.imgur.com/YkvEFXJ.png)
接下來有可能走到就畫箭頭,此為control-flow graph(CFG)
### Next-Use Information
![](https://i.imgur.com/lFsq858.png)
![](https://i.imgur.com/0er5gzK.png)
線的區間為life range
### Finding Local Common Subexpressions
![](https://i.imgur.com/kHHQMl2.png)
b0 c0為初始值,此圖為DAG
#### 範例
![](https://i.imgur.com/F317pUA.png)
![](https://i.imgur.com/N7LuiBA.png)
#### Dead Code Elimination
![](https://i.imgur.com/iPgfdcT.png)
### Register and Address Descriptors
**Register descriptor**:
1. 每個register都有,會持續記錄暫存器中存放的是哪個變數的值
2. 一開始Register descriptor都是空的
**Address descriptor**:
1. 對於每個變數都有,會記錄變數目前的值在哪
2. The location might be a register, a memory address, a stack location
3. 資訊可以連結到symbol table中
### Code Generation Algorithm
![](https://i.imgur.com/vdNmGfU.png)
#### 範例
![](https://i.imgur.com/sQlTZZ9.png)
initial
![](https://i.imgur.com/Afom6OL.png)
![](https://i.imgur.com/BRdqHvT.png)
把t的結果放在R2,而b的R2被用走了
![](https://i.imgur.com/F0DaiAi.png)
第二道指令
![](https://i.imgur.com/Nyrn1bf.png)
R1拿去放u
![](https://i.imgur.com/hFqibP2.png)
第三道指令
![](https://i.imgur.com/Vj8PfTQ.png)
第四道指令
![](https://i.imgur.com/eRETNxJ.png)
第五道指令
![](https://i.imgur.com/SybMmuv.png)
![](https://i.imgur.com/nJ6xcQo.png)
register決定都是getReg(I)去做的
![](https://i.imgur.com/DIBjR4B.png)
如果用LOAD指令,要改變R的register descriptor、x的address descriptor要把R加進去
![](https://i.imgur.com/lSKWdBZ.png)
### Design of the Function getReg
![](https://i.imgur.com/k7jORCU.png)
即使R3拿來使用裝其他東西,b的值還是找的到(在原先b那格)
![](https://i.imgur.com/YQxMUpM.png)
![](https://i.imgur.com/7doHay4.png)
若挑R2要先把a的值存到a中
### Register Allocation
![](https://i.imgur.com/oMM39nM.png)
若暫存器不夠,先讓出R1,要用c值時再load
### Graph Coloring
![](https://i.imgur.com/G5bdCxk.png)
![](https://i.imgur.com/lXx7d9T.png)
#### Interference Graph
![](https://i.imgur.com/25cGs2q.png)
兩者的life range有重疊就連線,相鄰的不能塗同個顏色(例如ab)
也可以是這樣
![](https://i.imgur.com/6USLyvs.png)
如果有同個顏色代表可以放在同樣的register中也不會干擾,因為他們life range也沒有重疊
### Loop Construct
![](https://i.imgur.com/qmjwvmy.png)
#### Dominator
We say node d of a flow graph dominates node
n, written **d dom n**.
代表每個到n的path都會經過d
![](https://i.imgur.com/3UaeLSL.png)
an edge’s head dominates its tail. We call such edge **back edge** 假設是a -> b 則b為head a為tail。圖中的9->1也是back edge
### Data Dependence
#### Flow dependence (true dependence)
![](https://i.imgur.com/lXLFVJU.png)
表示方法:
![](https://i.imgur.com/owWi1Uf.png)
#### Anti-dependence
![](https://i.imgur.com/DsvJRO2.png)
#### Output dependence
![](https://i.imgur.com/5SU9oYz.png)
#### Example 1
![](https://i.imgur.com/ylXOa7a.png)
#### Data Dependence with Conditionals
![](https://i.imgur.com/bHZ5gxo.png)
碰到條件式要假設任何路徑都會走
![](https://i.imgur.com/qLBA4uu.png)
S4跟S6不會同時發生,所以不用看關係
![](https://i.imgur.com/Oo48r6r.png)