编译器实现之旅——第七章 编译器后端概观

在前面的旅程中,咱们已经实现了整个的编译器前端。咱们也知道,前端的目标是将源代码转变为抽象语法树,以供后端使用。从这一章开始,咱们就要前日后端世界一探究竟了,如今,就让咱们来看看编译器后端到底由哪些组件组成,其分别又是在作什么吧。前端

1. 编译器后端的结构组成

不一样于编译器前端,编译器后端并非一个严格的流水线式结构,我想,用“A服务于B”这样的形容是更为贴切的。在CMM编译器的后端中,主要包含了语义分析器和代码生成器这两个组件;此外,因为虚拟机套件和后端关系密切,故咱们这里也将其一块儿展现。请看下图:编程

+-----------+
    抽象语法树 -> | 语义分析器 | -> 符号表
        |       +-----------+     |
        |                         |
        |                         v
        |                   +-----------+              +-------+
        +-----------------> | 代码生成器 | -> 低级指令 -> | 虚拟机 |
                            +-----------+              +-------+

2. 什么是语义分析器

要回答这个问题,首先要讨论的是:什么是语义?语义,说白了就是“一句话的意思”。在平常生活中,咱们每每会听到“每一个字我都看得懂,可是我不知道这是在说什么”这样的形容,这就是语义出现了问题致使的。在编程语言中也是同样,有的代码可能彻底符合语法,但其仍然是错误的,好比:将两个不能相加的类型进行相加,就属于语义错误,由于在语法分析器看来,只要代码知足“A + B”,而不是“+ A B”、“A B +”或是什么别的错误写法,就是符合语法的。也就是说,语法分析器对代码的检查能力并不能知足编程语言中的所有要求,缺失的部分就须要由语义分析器来弥补。后端

语义分析器不单单是一个用于错误检查的组件,其还负责另外一项很是重要的工做:生成符号表。什么是符号表呢?符号表就是记录抽象语法树中任何你想额外记录下的东西的表,这主要包括变量名、函数名、数组大小等,以服务于代码生成器。数组

咱们将在语义分析器的相关章节进一步讲述语义分析器和符号表的故事。编程语言

3. 什么是代码生成器

代码生成器,顾名思义:生成代码的组件。代码生成器一手拿着前端生成的抽象语法树,一手拿着语义分析器生成的符号表,背包里还装着诸如语法定义,指令集定义等物品,最终生成了可供虚拟机执行的低级指令。代码生成器是整个编译器中实现最为复杂,须要考虑的方面最多的部分,咱们也将在代码生成器的相关章节中走过至关长的一段旅程。函数

4. 什么是虚拟机

代码生成器生成的代码多种多样:对于有的编译器实现,其代码生成器直接生成汇编语言代码;而对于包括CMM编译器在内的另外一类编译器,其代码生成器生成的是编译器做者自行设计的低级指令,这些低级指令就须要专门的虚拟机来执行。计算机执行机器指令,而虚拟机执行相似于机器指令的另外一套指令,“虚拟机”所以得名。对于一个虚拟机来讲,其自身模仿了计算机的硬件结构,也具备和管理寄存器、内存等“物理设备”。在真实的编译器设计中,虚拟机是一个高度复杂的组件,但在CMM的编译器实现中,咱们设计了一套极为精简的指令集和一个很是简单的虚拟机。设计

咱们将在虚拟机的相关章节进一步讲述指令集和虚拟机的故事。code

5. 给读者的阅读建议

不一样于编译器前端,编译器后端的各组件之间相互联系,共同完成目标。故编译器后端各章节的阅读是没有严格的顺序之分的,而更像是一种“并行阅读”。若是你对某个地方为何要这样实现,或为何须要某个东西不能理解,那就看看其余组件的相关章节吧。因为代码生成器是整个编译器后端的核心,故出于逻辑顺序考虑,本文做者将这部分章节放在了最后讲述。内存

接下来,就让咱们首先来看看语义分析器是怎么实现的,符号表又是什么样子的吧。请看下一章:《实现语义分析器》。编译器

相关文章
相关标签/搜索