编译器设计笔记

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

B站硬核课程:
https://www.bilibili.com/video/BV1Bp4y1t7Cw?vd_source=e0b3cb923dbb83260e674c055a5ec68f

对应课本:编译器设计


一、overview

结构和组件

front end

symbolic information(变量名) ----front end----> abstract syntax tree
debug时候需要保留symbolic information

  • scanner。
    把一个string解析成一个一个的token。
    判断一个token结束的方法:用正则的方式定义variable name的规则,
  • parser
    把token构成一句statement 。检验grammar
  • semantic analysis
    保证statement meaningful。
    在symbol table里找对应的type,来判断是否meaningful。

Optimizer

理想上应该是backend通用的。

  • Common subexpression elimination(CSE)
x = a + b + c;
y = d / (a + b);
----->
t = a + b;
x = t + c;
y = d / t;

这种不一定能优化,t如果是在memory(t定义后面有很多code才到使用的地方),那就增加了读写操作;t如果在register里,t需要在寄存器里待很久,其他变量可用寄存器就变少了。

但是实际上,并不是独立于backend的。

Backend

取决于machine。
ILOC

Instruction selection

从AST到basic assembly,决定machine Instruction顺序或者策略。
比如,可以load a 到r1,或者直接从memory中读a。
AST,depth first。
此处的register是虚拟的,并认为是无穷的。

Instruction Scheduling

例子:x = a * b + c / d;
假设:
load 时延3cycle
mul 时延2 cycle
div 时延 5 cycle
store 时延2 cycle
add 时延1cycle

start cycleend cyclelive register
1load a -> r113r1
2load b -> r224r1,r2
3mul r1, r2 -> r356r3取决于1 和2
4load c -> r468r3,r4
5load d -> r579r3,r4,r5
6div r4, r5 -> r61014r3,r6取决于4和5
7add r3, r6 -> r71515r7取决于6和3
8store r7 -> x1617none

例子总时延:17cycle。需要3个寄存器。
instruction level parallelism (ILP),把独立的long latency的放在前面:

start cycleend cyclelive register
1load a -> r113r1
2load b -> r224r1,r2
3load c -> r435r1,r2,r4
4load d -> r546r1,r2,r4,r5
5mul r1, r2 -> r356r3,r4,r5取决于1 和2
6div r4, r5 -> r6711r3,r6取决于3和4
7add r3, r6 -> r71212r7取决于5和6
8store r7 -> x1314

14 cycle。需要4个寄存器。
NP-complete problem,具体怎么优化需要取决于backend。

  • out-of-order processor,processor会自动做parallel,此时compile的目标是减少寄存器,减少spill。
  • processor的限制,只能看到reorder buffer里面的指令。compiler可以看到更多scheduling reign的指令
Register Allocation

把basic assembling里面涉及的虚拟register,映射到物理寄存器。
register不够用的时候,额外做临时不用值的store和load到堆,叫做spill。minimize spilling为主要任务。

二、Scanner

识别regular language的工具。

deterministic finite automater(DFA)和NFA

DFA:在字母表里,每一个symbol有且只有一个transition。

  1. 例子:目标找101的字符串的DFA
    在这里插入图片描述
    包含101子串的NFA:
    在这里插入图片描述
  2. 例子2:包含101或111子串

在这里插入图片描述
scanning会先构一个DFA,transition table,固定的swich case就可以了。但是NFA可以更好的表达RE。
Thompston Construction,把正则转NFA

正则RE

例子:

  1. unsigned integer的RE:[1-9][0-9]* U 0
    在这里插入图片描述

  2. floating point number with an optional decimal point
    ([1-9][0-9]* U 0 )((.[0-9]*) U ε)

  3. 变量名命名
    (_U[a-Z])([a-Z] U [0-9]U_)*

RE 转 NFA

Thompson contruction

regular operation(NFA的拼接操作,改变accept state):union,concatenation,star(重复0或多次)。
star的NFA:
在这里插入图片描述
例子,a(b U c)*的NFA:
在这里插入图片描述

NFA 转 DFA

例子,包含11或者101的子串:
在这里插入图片描述
按照NFA写的trace:
在这里插入图片描述
有D0, D1, D2, D3, D4 set of states,下一步需要把set of states改写成DFA。

例子1,将下面这个NFA改成DFA:
在这里插入图片描述
第一步:
在这里插入图片描述
此时,n1的是unreachable的,简化后的DFA:
在这里插入图片描述

例子2:
接上面a(b U c)*的NFA转DFA:
在这里插入图片描述
把n?组成有可能性的state组合:

在这里插入图片描述
用state改写的DFA:
在这里插入图片描述

三、Parsing

scanning是定位word,parsing是定位statement的。

Parsing Tree

context-free grammar
grammar包括(V, T, P, S),分别是variables,terminals,productions,start variable。
context-free grammar,指的是,左边的是一个单独的variable

例子1:

下面例子将一个grammar改写成derivation tree:
语法定义
根据这个语法写的例子aabbbb,有两种解析方法:

S->S1S2
S1->aS1b|ε
S2->bS2|b (因为m>n)

在这里插入图片描述

方法二:

S->aSb|B
B->bB|b(因为m>n,所以不能为空)

在这里插入图片描述

例子2:

classic expression grammar

Assign -> ident = Expr
Expr -> Expr + Term | Expr - Term | Term
Term -> Term * Factor | Term / Factor | Factor
 Factor -> ident | num | (Expr)

x = (a + b) * c - d的derivation tree:
在这里插入图片描述

左循环的grammar:X -> Xa | b,等价于右循环 X -> b X', X' -> aX' | ε

// TODO 很多parse的算法

把parsing tree转成AST

syntax-directed translation

例子

x = a * 3 + b
构建AST
在这里插入图片描述

改写的AST,从叶子节点开始,只保留真正的Operation:
在这里插入图片描述
grammar和对应的action:
YACC notation,parser generator,只需要写grammar和action,会自动生成AST。左边的用两个$$,右边用一个$。$符号指的是一个node。叶子节点,不link其他node,用token表示。
在这里插入图片描述

其中,$$ = MakeMulNode($1, $2),拆开来看含义是:

MakeMulNode(Node *n1, Node *n2)
create new node with ptr n
n->left = n1
n->right = n2
return n

reduce

在这里插入图片描述

估计运算cost

每个operation的运算时间:
在这里插入图片描述
再根据parsing tree,从叶子节点开始往根节点推导。


总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值