Mini C 编译器的设计与实现
(讲义)
电子科技大学计算机学院
《编译原理》课程组
2008 年
1
目录
第一章 Mini C 语言编译器简介......................................................................................................... 4
第二章 理论基础 ..................................................................................................................................7
2.1 编译系统概述.........................................................................................................................7
2.1.1 什么是编译器 ..............................................................................................................7
2.1.2 编译器的产生 ..............................................................................................................7
2.2 编译器的结构.........................................................................................................................8
2.3 编译器的组织.......................................................................................................................10
2.3.1 编译的分遍 ................................................................................................................10
2.3.2 分遍的设计 ................................................................................................................11
2.4 编译器中的主要数据结构...................................................................................................11
2.5 编译程序的开发...................................................................................................................12
2.5.1 历史与发展 ................................................................................................................12
2.5.2 开发注意事项 ............................................................................................................12
2.5.3 编译技术和软件工具 ................................................................................................12
第三章 MINI C 语言和 MINI C 编译器........................................................................................... 14
3.1 MINI C 编译器的开发背景和意义 ......................................................................................14
3.2 MINI C 语言的基本描述 ......................................................................................................14
3.3 MINI C 编译器的功能 ..........................................................................................................15
3.4 MINI C 编译器的程序结构 ..................................................................................................16
3.4.1 MINI C 编译器的核心模块.......................................................................................16
3.4.2 MINI C 编译器的文件组成.......................................................................................16
3.4.3 MINI C 编译器的分遍...............................................................................................17
3.5 MINI C 编译器中的主要数据结构 ......................................................................................17
第四章 MINI C 编译器的实现 ..........................................................................................................19
4.1 词法分析阶段.......................................................................................................................19
4.1.1 概述 ............................................................................................................................19
4.1.2 MINI C 词法分析程序的实现...................................................................................20
4.1.3 关键字与标识符的识别 ............................................................................................21
4.1.4 为标识符分配空间 ....................................................................................................21
4.2 语法分析阶段.......................................................................................................................22
4.2.1 概述 ............................................................................................................................22
2
4.2.2 MINI C 语言的语法...................................................................................................22
4.2.3 MINI C 语法分析程序的实现...................................................................................23
4.3 语义分析阶段.......................................................................................................................24
4.3.1 概述 ............................................................................................................................24
4.3.2 MINI C 语言的语义...................................................................................................24
4.3.3 MINI C 的符号表.......................................................................................................25
4.3.4 MINI C 语义分析程序的实现...................................................................................25
4.4 MINI C 运行时环境 ..............................................................................................................26
4.4.1 概述 ............................................................................................................................26
4.4.2 MINI C 的运行时环境...............................................................................................26
4.5 代码生成阶段.......................................................................................................................28
4.5.1 概述 ............................................................................................................................28
4.5.2 目标机器——Mini Machine.....................................................................................29
4.5.3 MINI C 代码生成器的实现.......................................................................................31
4.5.3.1 MINI C 代码生成器的 MM 接口...................................................................31
4.5.3.2 MINI C 代码生成器 ........................................................................................33
4.6.1 将临时变量放入寄存器 ............................................................................................35
4.6.2 在寄存器中保存变量 ................................................................................................36
4.6.3 优化测试表达式 ........................................................................................................36
4.7 MINI C 编译器的使用方法 ..................................................................................................37
3
第一章 Mini C 语言编译器简介
随着计算机科学技术的飞速发展,计算机技术被应用在了越来越广泛的领域,
实现各种各样功能的计算机程序被大量地开发出来,应用在我们的生活、学习和
工作当中。相应地,也产生了许多用以编写这些计算机程序的高级程序设计语言。
程序编制者通过特定语言的编译器将自己编写的源程序翻译为特定机器上的目标
程序,从而能够最终达到程序执行的目的。
从 20 世纪 60 年代以来,编译器设计就一直是计算机研究发展和开发领域中
的一个活跃主题。虽然编译器设计已有很长的历史,并且也是一门相对成熟的计
算机技术,但编译器毕竟是一种实现由高级语言源程序至机器或汇编指令的高效
映射工具,随着计算机软、硬件水平的飞速发展,使得计算机应用日新月异,程
序语言的设计在不断地变化,目标机体系结构也在不断地改进,软件越来越复杂,
其规模也越来越大。尽管编译器设计问题在高级层次上没有变化(或变化很小),
但当我们深入其内部研究时就会发现,编译器的内部构造其实也一直在变化。此
外,由于我们能够提供给编译器本身使用的计算资源也在不断增加。因此,现代
编译器可以采用比以前更耗费时间和空间的算法。当然,编译技术研究人员也在
继续努力开发新的、更好的技术来解决传统编译器的一些设计性问题[1]。
编译器是一种相当复杂的系统程序,其代码的长度可从几千行到几百万行不
等,所以编写甚至读懂这样的一个程序都不是一件容易的事。绝大多数的计算机
专业人员从来没有编写过一个完整的编译器,但是,几乎所有形式的计算均要用
到编译器,而且任何一个与计算机打交道的专业人员都应该掌握编译器的基本结
构和操作。除此之外,计算机应用程序中经常遇到的一个任务就是有关命令解释
程序和界面程序的开发,这比编译器的开发规模要小,但使用的却是很类似的技
术。因此,掌握编译器的开发技术具有非常重大的实际意义。
编译器的设计从本质上来说是一种工程活动,它所使用的方法必须很好地解
决现实中出现的各种翻译问题(即用真实的语言编制且在真实的机器上能够执行
的真实的程序)。大多数情况下,开发编译器的人必须接受他们面对的语言和机器,
很少能够去影响或改善这两者的设计。在开发过程中做什么样的分析和转换,以
及什么时候去做,这些都是工程上的选择,但正是这些选择决定了一个编译器的
性能高低。本实验就建立在一个自主开发的名为 MINI C 的微型编译器基础之上,
该编译器虽然功能弱于像 Turbo C 或 Borland Pascal 这样的经典编译器,但也已经
4
完全具备了一个编译器应有的所有特征。
在编译器技术的发展过程中,如何提高编译的效率一直是核心研究目标之一,
编译效率主要是根据该编译器所生成的目标代码在执行过程中的时间指标和空间
指标来衡量的,所以编译优化也必定围绕时间和空间这两个方面来实施。在编译
过程中针对代码优化的技术有很多,它们通常是通过搜集源代码或中间代码的特
定信息,然后利用这些信息对代码中的数据结构或算法操作实施等价的改进变换,
从而力求在时间效率和空间效率上达到一个最佳平衡点。编译器的开发者们总是
希望能够将各种代码优化技术充分地运用在自己的编译器设计中,但往往事与愿
违,毕竟优化操作本身也是需要付出开销的。在 MINI C 编译器的开发过程中,虽
然没有运用到太复杂的代码优化技术,但通过本实验的研究,在现有开发的 MINI
C 编译器基础之上,能够在后续相关项目的开发中有效地提高程序代码的编译质
量,对于自己以后的研究和发展方向将起到非常大的推动作用。这正是本实验的
研究意义所在。
本实验是以 MINI C 微型编译器的项目开发为基础,该项目的开发目标是自定
义一种 MINI C 高级语言,然后编码实现出 MINI C 语言的编译器(称为 MINI C
编译器),完成将 MINI C 语言源程序翻译为基于 MM 机(Mini Machine)的目标
代码的任务,这是本实验的实际应用背景。
编译器的开发具有极高的实用价值和意义,高级语言编译器的性能决定了基
于该语言平台所开发出的软件的质量。所以国内外很多大学的科研和技术人员也
在积极地开展这方面的技术探索和项目实践。他们大多是以特定的软件项目为背
景来进行一些与编译器开发相关或类似的研究分析,他们的研究目标大多是基于
某种实验型高级语言的编译器开发和优化改进,然后把有价值的研究成果移植或
运用到产品级的编译器开发中(比如.NET 平台编译器)。
最近十年以来,国外关于编译器设计的发展动态主要体现在:首先,编译器
采用了大量的更加复杂的算法,主要用于推断或简化程序中的信息,这又与更为
复杂的程序设计语言的发展结合在一起,其中典型的有用于函数语言编译的
Hindley-Milner 类型检查的统一算法[2]。其次,编译器已越来越成为基于窗口的可
视化交互开发环境(Interactive Development Environment,IDE)的一部分,该环
境还包括了智能编辑器、连接程序、调试程序以及项目管理程序等,已经成为了
事实上的编译器行业标准。另一方面,尽管国内外的专家学者们近年来在编译原
理领域进行了大量的研究,但是基本的编译器设计原理在近 20 年中都没有多大的
改变,它现在正迅速地成为计算机科学课程中的中心环节之一。
5
在九十年代,作为 GNU 项目或其它开放源代码项目的一部分,许多免费的编
译器或编译器构造工具被开发出来。这些工具可用来编译数种程序设计语言的源
程序(典型的就是 GCC)。它们中的一些项目被认为是高质量的,而且对现代编译
理论感兴趣的人都可以较容易地得到它们的免费源代码。典型的是在 1999 年,SGI
公布了他们的一个工业化的并行优化编译器 Pro64 的源代码,随后被全世界多个编
译器研究小组用做研究平台,并命名为 Open64。Open64 的设计结构好,分析优化
全面,是编译器高级研究的理想平台。
反观国内,现阶段对于编译技术的相关研究,基本上都是着眼于特定编译器
的特定部分来展开的,而本实验将研究和分析的重点主要集中于一个完整的微型
编译器的构造的讨论。
6
第二章 理论基础
2.1 编译系统概述
2.1.1 什么是编译器
编译器,是将便于人类编写、阅读、维护的计算机高级语言程序翻译为机器
能够识别、运行的计算机低级语言程序的一种系统软件。编译器将源程序(Source
Program)作为输入,翻译产生使用目标语言的等价目标程序((Target Program)。
其中,源程序一般为高级语言(High-level language),如 Pascal,C++等,而目标
语言则是汇编语言或目标机器的机器语言[3]。编译器的这一作用如图 2-1 所示:
图 2-1 编译器的作用
2.1.2 编译器的产生
本世纪四十年代,由于冯·诺依曼在存储程序计算机方面的先锋作用,使得编
写一串代码或程序已成为可能和必要,这样计算机就可以执行所需的计算。在初
期,这些程序都是用机器语言编写,编写或维护这样的代码是非常枯燥乏味且效
率低下的,所以机器语言很快就被汇编语言代替了。汇编语言大大提高了程序编
写速度和准确度,但它也有许多缺点。于是发展编程技术的下一个重要革新就是
以一个更加类似于数学定义或自然语言的简洁形式来编写程序的功能操作,它应
与任何机器都无关,而且也可由一个程序翻译为可执行的代码。
随着对形式语言和自动机理论的研究,人们对高级程序设计语言的认识越来
越深,对编译器结构的设计也越来越清晰。人们通过对形式语言文法规则的研究,
相当完善地解决了分析问题。当分析问题变得相对成熟时,设计者们又花费了很
多的精力来研究这一部分的编译器的自动构造,这就是分析程序生成器(parser
generator)最初的雏形。类似地,对有穷自动机的研究也促进了一种称为扫描程序
生成器(scanner generator)工具的发展。接着,人们又深化了生成有效目标代码
的方法,这些就构成了传统的编译器,在这个过程中运用到的技术被一直使用至
7
今。
2.2 编译器的结构
严格地说,编译器是一个将高级语言源程序转换成能在一台计算机上执行的
等价目标代码或机器语言程序的软件系统。这个定义可扩展到包含将一个高级语
言程序转换成汇编语言程序的系统,将一个高级语言程序转换成另一种高级语言
程序的系统,从一个机器语言程序转换成另一种机器语言程序的系统,从一种高
级语言程序转换成一种中间语言程序的系统,等等。
在通常情况下,一个编译器应由一系列的阶段组成,这些阶段从要编译的源
程序的字符序列开始,依次对一个给定形式的程序进行分析,并得到一种新的表
示形式,在大多数情况下最终产生一个可以与其他目标代码链接,并装入一台机
器的存储器中执行的可重定位目标模块。这一编译过程一般由如下 6 个阶段构成,
它们执行不同的逻辑操作如图 2-2 所示[4]:
(1) 扫描程序(scanner)
图 2-2 编译器的阶段示意图
8