我就记得之前看到过这个问题但是找了好久才找出来…
占个坑来记点笔记。慢慢更
线下课不知道能不能去蹭一个…再怎么说住在湾区离学校那么近…
这里只能笔记一下Coursera线上课的内容:
Stanford Compilers - Alex Aiken | Coursera(现在Coursera这门课没开课,所以点链接只能看到一个“preview”链接,那个页面里只有视频的列表;请用上面没“preview”的链接,可以看到投影片和做作业用的VirtualBox虚拟机映像。
看到VirtualBox虚拟机映像不知道咋搞的同学,Windows用户可以参考这个笔记
How to install classroom object oriented language (cool) programming in your windows computer?)
这门Coursera编译原理课对应的斯坦福课程是CS143的简化版。
从线上课的内容看,Alexander Aiken教授把编译器的基本概念都讲得很清楚,所以这门课入门是个好选择。如果刚开始学编译原理,干啃龙书卡壳了的话,来上上这门课,听听老师的讲解,或许能助初学者脱离困境。
这门课的课程安排跟许多其它本科的编译原理入门课一样,讲解parsing相关的部分比较多,讲得很详细;而讲解后端的部分比较少,讲得比较简略:先就运行时环境和代码生成讲解了一些基本知识以便能完成编译器后端,然后非常简单的介绍了代码优化、垃圾回收和Java等扩展话题。
——所以肯定有人会觉得parsing侧重得太多,浪费时间,应该多讲讲语义分析和优化等话题更实用;毕竟parser generator很普及,手写递归下降parser也“不需要”那么多理论——
我觉得对初学者来说,这还算是个不错的平衡点——parsing是编译原理的大入口,源码经过parse才可以进一步被编译器的其它部分理解和处理,在这方面有所侧重也挺好,打好基础;在此基础上安排了足够课程内容让学生能完成一个功能完整的、能生成汇编的编译器,让学生能走完编译的整个流程,不失完整性。
实际上斯坦福的编译原理课程里,
CS143只是第一门课;后面还有两门。
第二门
CS243讲编译器的中间表现(Intermediate Representation)、代码分析与优化。<- 龙书作者教你如何做优化。课程作业中居然有一部分是用
Joeq,简直赞!
最后一门
CS343讲一些专门话题。把三门课结合起来看作一个整体,这安排就非常合理了。
课程作业的Cool语言编译器是个亮点,不做这个作业的话这门课的效果会大打折扣。
作业有配套的代码框架,Cool Support Code。这也是我喜欢(也不喜欢)这个课程的原因之一。有一套完善的代码框架(skeleton code + support code)有利于学生集中精力解决当前作业所关注的问题,而不必为一些不相关的枝末细节烦恼,容易有成就感。
(但是不喜欢它的原因是它的代码风格跟我喜欢的风格不一样…不过总比要自己写一大堆麻烦的代码好。)
本科的时候我帮在国外读书的同学做过些他们的作业,也是像这样有很好的代码框架,当时就让我羡慕不已。
作业可以用C++或Java完成;用其它语言也可以,不过那就无法利用作业配套的代码框架,要多写很多基础设施的实现。
作业分为4部分:
- 词法分析:用Flex(C++)/ JLex(Java)实现
- 语法分析:用bison(C++)/ CUP(Java)实现
- 语义检查
- 代码生成
Cool语言的运行时环境用到的分代式GC,在做代码生成时还要注意插入write-barrier(_GenGC_Assign)的调用。这有助于学生感受编译器与GC之间的交互。
按照课程安排,Cool编译器的工作流程如下:
Cool源码
-> [词法分析] -> token流
-> [语法分析] -> AST
-> [语义分析] -> 标注过的AST
-> [代码生成] -> MIPS汇编其中代码生成的部分使用模拟stack machine的方式,不经过其它IR、不做优化,直接从AST生成汇编。
如果要做更完整的、更接近产品中的编译器实现,那么工作流程会是:
Cool源码
-> [词法分析] -> token流
-> [语法分析] -> AST
-> [语义分析] -> 标注过的AST
-> [高层中间代码生成] -> 高层IR
-> [平台无关优化] -> 高层IR
-> [低层中间代码生成] -> 低层IR
-> [平台相关优化|指令选择|指令调度|寄存器分配] -> 低层IR
-> [代码生成] -> MIPS汇编
要想做到这个程度,就得在上完这门课之后继续上后续课程 / 再去找别的资料学习。
在线下的CS143的课程作业里,有一个“extra credit”项目就是实现在Cool编译器里实现优化;这是个开放性作业,做多少优化都行,多多益善。挺好奇现实中学生们会做到什么程度,因为光靠课上教的内容不太够用…
回想我自己在本科上的编译原理课,开头花了非常多的时间教词法分析、语法分析、自动机,感觉后面刚讲了点简单的语义分析就草草收尾了,最后讲没讲最基本的代码生成我都没印象了…(咳咳
而且我们在本科只有这么一门编译原理课,想学后面的优化全得靠自己。
下面按Coursera版课程的章节做点笔记:
02 The Cool Programming Language
02-01 - 02-03这三节都在介绍Cool语言的基本特性和使用方式。
Cool语言的官网:
Cool: The Classroom Object-Oriented LanguageCool语言手册:
Cool ManualCool项目的目标平台是MIPS32。相信大多数学生手边都没有能方便的运行通用程序的MIPS硬件,所以Cool项目推荐配套使用一个MIPS32模拟器,
SPIM MIPS Simulator。"spim"就是MIPS反过来写喔 >_<
(可能有很多同学都有
PSP,那上面确实有一颗
MIPS R4000CPU,但是在上面跑作业还是算了…)
12-01 Code Generation
这里教的代码生成思路是1 top-of-stack caching。简称1-TOSCA。
12-06 Object Layout
Cool语言采用的对象模型跟C++的单继承部分的对象模型相似,外加要支持Cool runtime的GC。
为此,对象头有3个word:
- Class Tag
- Object Size
- Dispatch Table Pointer
这个“dispatch table pointer”就是C++程序员们耳闻能详的vptr,dispatch table就是vtable。
14-01 Intermediate Code
这里介绍的中间代码形式是三地址代码(Named Three-Address Code)。课程把它当作“高级汇编”来讲解,可以用无限数量的虚拟寄存器,但代码形式只允许双目运算或单目运算,如:
x := y op z
x := op y连续的运算得拆解为一个个双目或单目运算,每个中间结果都要赋值给变量。
课程并没有介绍如何从AST生成中间代码,只是简单带过说生成中间代码跟生成汇编代码过程相似:前者可以用无限量的虚拟寄存器,而后者只能用目标平台支持的固定数量的寄存器。
16 Register Allocation
这里介绍的是经典的基于图着色(Graph Coloring)的寄存器分配算法。
这可能是最正统的课程安排方式,不过入门的话我觉得要是能与时俱进换成讲线性扫描寄存器分配(Linear-Scan Register Allocation)算法更好,更容易理解和实现。