作者mshockwave (夏克维夫)
看板CompilerDev
标题[分享] gross: 一个实验性的编译器作业
时间Wed Aug 5 12:38:51 2020
有版友建议可以多分享一些简单、有趣的编译器专案
本鲁就来抛砖引玉一下 来分享一下去年我修的一门课做的作业
https://github.com/mshockwave/gross
当时花了大概花了10个星期做这个专案 不算长也不算太短
虽然里面有很大一部分是实验性质、不太常见的设计,但就是因为实验性质所以没有做的
很复杂(掩面)因此只要修过研究所编译器课程 在理解上应该都没什麽太大问题
这边挑几个重点来讲一下:
-
src/Frontend
很普通的 Lexer, Parser。由於我们的输入语言是一个简单的教学用程式语言(好像就
叫做PL241 XDD),用非常简单的top-down parser就能做完。唯一跟一般 parser 不一样
的是 parser 会直接生成 IR 而不是 AST。会这样做到也不是没时间做,而是等下会提到
的实验性 IR 其中一个设计哲学就是「整个编译的流程、都尽量
用同一种资料结构」
更具体来说的话就是整个流程都用 Graph 来代表
换句话说,就是不再有
Source Code -> AST -> IR -> Native Code
而是:
Source Code -> Graph IR -> Native Code
虽说如此,整个编译器依然是阶段性地慢慢把输入的高阶程式码 一步一步的转化为低阶
机器码。其中关键就是虽然整个流程里面都是用 Graph,但其中的 vertex 在每一个阶段
的
抽象程度不一样。
例如刚从 Parser 出来的 Graph 每个节点都是非常高阶的结构像是 "While" "If-Else"
但是之後就会慢慢降成 "jump", "branch" 等等较为低阶的概念
-
src/Graph
这边放的就是前述 Graph IR 的实作。我这个资料夹的 README 花了非常多篇幅在描述
三种不同的 edge ... 有点复杂所以这边就不提了。用最简单的说法的话就是每个
edge 都代表一个dependency,而设计来能够表示三种不同的dependency的原因在於
希望能让某些优化比较好做。例如最恶名昭彰(笑)的 memory side effect,如果我们
能够在一开始就把这些 side effect 明确地表示出来(因为或许能从一些高阶资讯中
获得)、而不是等到要用的时候才在那边分析,在优化上可能会比较轻松
-
src/Graph/Reductions
虽然这个资料夹有一个酷炫的名字,但其实就是普通的优化而已XD 会取名为 reduction
单纯只是因为如果你在 Graph IR 上做优化,大部分时候都是逐渐把 Graph 简化。这边
放的优化也只有最简单的那几个:CSE, Peephole, ValuePromotion(mem2reg)
-
src/CodeGen
谢天谢地这个作业只要生成一个超简单、教学用的指令集(DLX)。所以虽然这个资料夹有
一堆档案,但真的只是一些必要的东西像是 scheduling, RA, instruction selector
值得一提的是在之前用的 Graph IR 没有 basic block 的概念(一个函式就是
一个完整的Graph),一直到最终在 scheduling 、要把这个 Graph 做 "linearlize"
转成一串instruction序列的时候才有 basic block 的概念出现
以上就是几个有趣的部分,希望大家能从这个实验性的专案里面得到一些灵感:)
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 169.234.228.227 (美国)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/CompilerDev/M.1596602334.A.CDD.html
1F:推 Lipraxde: Graph IR 与 MLIR 在设计上有异曲同工之妙 08/05 18:43
2F:推 ronin728: 常见的 Graph IR 应该都是 Click Cliff 那几篇出来的吧 01/22 19:10
3F:→ ronin728: 分好几个Pass一直简化 很像Scheme那种Partial evalution 01/22 19:12
4F:→ ronin728: 市面上跟这最像的应该就是Graal IR了 感觉是亲戚 01/22 19:14