编译器发展及其相关介绍

  1. 编译器的发展:

上世纪50年代,IBM的John Backus带领一个研究小组对FORTRAN语言及其编译器进行开发。但由于当时人们对编译理论了解不多,开发工作变得既复杂又艰苦。与此同时,Noam Chomsky开始了他对自然语言结构的研究。他的发现最终使得编译器的结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法的难易程度以及识别它们所需要的算法来对语言分类。正如现在所称的Chomsky架构(Chomsky Hierarchy),它包括了文法的四个层次:0型文法、1型文法、2型文法和3型文法,且其中的每一个都是其前者的特殊情况。2型文法(或上下文无关文法)被证明是程序设计语言中最有用的,而且今天它已代表着程序设计语言结构的标准方式。分析问题(parsing problem,用于上下文无关文法识别的有效算法)的研究是在60年代和70年代,它相当完善的解决了这个问题。现在它已是编译原理中的一个标准部分。

有限状态自动机(Finite Automaton)和正则表达式(Regular Expression)同上下文无关文法紧密相关,它们与Chomsky的3型文法相对应。对它们的研究与Chomsky的研究几乎同时开始,并且引出了表示程序设计语言的单词的符号方式。

人们接着又深化了生成有效目标代码的方法,这就是最初的编译器,它们被一直使用至今。人们通常将其称为优化技术(Optimization Technique),但因其从未真正地得到过被优化了的目标代码而仅仅改进了它的有效性,因此实际上应称作代码改进技术(Code Improvement Technique)。

当分析问题变得好懂起来时,人们就在开发程序上花费了很大的功夫来研究这一部分的编译器自动构造。这些程序最初被称为编译器的编译器(Compiler-compiler),但更确切地应称为分析程序生成器(Parser Generator),这是因为它们仅仅能够自动处理编译的一部分。这些程序中最著名的是Yacc(Yet Another Compiler-compiler),它是由Steve Johnson在1975年为Unix系统编写的。类似的,有限状态自动机的研究也发展了一种称为扫描程序生成器(Scanner Generator)的工具,Lex(与Yacc同时,由Mike Lesk为Unix系统开发)是这其中的佼佼者。

在70年代后期和80年代早期,大量的项目都贯注于编译器其它部分的生成自动化,这其中就包括了代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。

编译器设计最近的发展包括:首先,编译器包括了更加复杂算法的应用程序它用于推断或简化程序中的信息;这又与更为复杂的程序设计语言的发展结合在一起。其中典型的有用于函数语言编译的Hindley-Milner类型检查的统一算法。其次,编译器已越来越成为基于窗口的交互开发环境(Interactive Development Environment,IDE)的一部分,它包括了编辑器、连接程序、调试程序以及项目管理程序。这样的IDE标准并没有多少,但是对标准的窗口环境进行开发已成为方向。另一方面,尽管近年来在编译原理领域进行了大量的研究,但是基本的编译器设计原理在近20年中都没有多大的改变,它现在正迅速地成为计算机科学课程中的中心环节。

在九十年代,作为GNU项目或其它开放源代码项目标一部分,许多免费编译器和编译器开发工具被开发出来。这些工具可用来编译所有的计算机程序语言。它们中的一些项目被认为是高质量的,而且对现代编译理论感兴趣的人可以很容易的得到它们的免费源代码。

大约在1999年,SGI公布了他们的一个工业化的并行化优化编译器Pro64的源代码,后被全世界多个编译器研究小组用来做研究平台,并命名为Open64。Open64的设计结构好,分析优化全面,是编译器高级研究的理想平台。

 

(2) C编译器介绍

Visual C++:Windows平台上最流行的编译器,和VS集成的很好,编译效率和编译后的代码效率都不错,但是,除了比较好用之外,好象没有特别突出的...而且,支持的硬件平台好象只有X86的

GCC/G++:开源的,Linux/Unix平台上的首选,而且支持N种件平台,如果想进行跨平台编译的话,这是一个不错的选择。编译效率和编译后的代码效率都不错。据说Linux内核的开发者都用2.95版的,这个版本编译出来的C代码应该是效率最好的。

Intel C++:收费的,Intel做的,号称在是X86上最好的编译器,安腾上也是。Intel自家的编译器,对自家硬件的支持当然是不用说了。Windows和Linux上都可以用,一般用于一些对性能要求极高的领域,比如内核、游戏等等。缺点是文档不多,尤其是中文的,不是很流行,有一定的门槛。

不过随着多核的日益普及,要在Intel的平台上做出好的应用,Intel C++编译器应该是不错的选择,尤其是刚发布的10.0版,直接纳入了对多核编程的支持,值得学习。

Borland C++:不少C++ Builder fans的最爱,和Visual C++有种既生瑜何生亮的感觉。说实话,这真是不错的编译器,Borland的都是一帮牛人啊!只可惜,唉....

 

(3) intel编译器    

 Intel C++ Compiler (也称为 icc 或 icl)是美国 Intel 公司开发的 C/C++ 编译器,适用于 Linux、Microsoft Windows 和 Mac OS X 操作系统。

  Intel 编译支持 IA-32、Intel 64、Itanium 2、Intel Atom 处理器和某些非 Intel 的兼容处理器(例如某些 AMD 处理器)。开发人员应当检查系统需求。适用于 IA-32 和 Intel 64 的 Intel C++ 编译器的主要特点是自动向量化器,它能够生成 SSE、SSE2 和 SSE3 的 SIMD 指令及其适用于 Intel 无线 MMX 和 MMX 2 的嵌入式变种。

  Intel C++ Compiler 进一步支持 OpenMP 3.0 和适用于对称多处理的自动并行化。借助于 Cluster OpenMP 的附加能力,编译器还可为分布存储多处理根据 OpenMP 指示自动生成消息传递接口调用。

  Intel C++ Compiler 可通过四种方式获得,它分别是 Intel Parallel Studio、Intel C++ Compiler 专业版、Intel 编译器套装和 Intel Cluster Toolkit 编译器版的一部分。该编译器的最新发布是 Intel C++ Compiler 11.0 版本.

 

(4)交叉编译器

  在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,我们就称这种编译器支持交叉编译。这个编译过程就叫交叉编译。简单地说,就是在一个平台上生成另一个平台上的可执行代码。这里需要注意的是所谓平台,实际上包含两个概念:体系结构(Architecture)、操作系统(Operating System)。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行。举例来说,我们常说的x86 Linux平台实际上是Intel x86体系结构和Linux for x86操作系统的统称;而x86 WinNT平台实际上是Intel x86体系结构和Windows NT for x86操作系统的简称。

  有时是因为目的平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。

  交叉编译这个概念的出现和流行是和嵌入式系统的广泛发展同步的。我们常用的计算机软件,都需要通过编译的方式,把使用高级计算机语言编写的代码(比如C代码)编译(compile)成计算机可以识别和执行的二进制代码。比如,我们在Windows平台上,可使用Visual C++开发环境,编写程序并编译成可执行程序。这种方式下,我们使用PC平台上的Windows工具开发针对Windows本身的可执行程序,这种编译过程称为native compilation,中文可理解为本机编译。然而,在进行嵌入式系统的开发时,运行程序的目标平台通常具有有限的存储空间和运算能力,比如常见的 ARM 平台,其一般的静态存储空间大概是16到32MB,而CPU的主频大概在100MHz到500MHz之间。这种情况下,在ARM平台上进行本机编译就不太可能了,这是因为一般的编译工具链(compilation tool chain)需要很大的存储空间,并需要很强的CPU运算能力。为了解决这个问题,交叉编译工具就应运而生了。通过交叉编译工具,我们就可以在CPU能力很强、存储控件足够的主机平台上(比如PC上)编译出针对其他平台的可执行程序。

  要进行交叉编译,我们需要在主机平台上安装对应的交叉编译工具链(cross compilation tool chain),然后用这个交叉编译工具链编译我们的源代码,最终生成可在目标平台上运行的代码。常见的交叉编译例子如下:

  • 在Windows PC上,利用ADS(ARM 开发环境),使用armcc编译器,则可编译出针对ARM CPU的可执行代码。
  • 在Linux PC上,利用arm-linux-gcc编译器,可编译出针对Linux ARM平台的可执行代码。
  • 在Windows PC上,利用cygwin环境,运行arm-elf-gcc编译器,可编译出针对ARM CPU的可执行代码。

(5) 编译器的自展:

不知道读了之前的内容,你有没有这样一个疑问:既然编译器本身是一段代码,那么如果想编译一个编译器,就需要更早的编译器来进行编译操作。而编译这个更早的编译器还需要更更早的编译器——长此以往,第一个编译器是怎么产生的呢?难道是直接用机器语言书写的?

如果能这么想,那么你就猜对了。第一个编译器一定是用机器语言写出的。实际上,很久以前的程序员还在纸带上打孔编程呢,他们也照样乐在其中。机器语言只是很难书写,并不是不能书写。

但是,毕竟用这么难书写的语言写一个C++编译器,谁都不会愿意去干。所以,第一个编译器的功能一定是很简单的。而人们会用这很简单的编译器的语言,去写一个稍微复杂一些的编译器;然后再用这个新的编译器,去写一个更复杂的编译器;最终得到一个很复杂的编译器,比如C++编译器——好了,如果能够理解这个过程,那么你实际上几乎就理解了自展。

所谓自展,实际上就是用一个功能不太完善的编译器支持的语言写代码,然后放到这个编译器上去编译,产生一个比自己更完善的编译器的过程。用一个不太恰当的例子来描述,就是我们已经有了一个C语言的编译器,然后我们用C语言写一个C++的编译器代码,并用C语言编译器编译这个代码生成可以运行的C++编译器(之所以不太恰当,是因为C语言不是C++语言的严格子集)。

也就是说,我们有一个编译器A(C –> A),现在写一个编译器C(C++ –> A),将后者放入前者中进行编译,即A(C(C++ –> A) –> A),得到一个可以执行的编译器A(C++ –> A)。

以上几段的关键点是:

自展过程,实际上就是用低级语言先实现一个简单的编译器,然后用这个编译器的语言再去编写一个更高级的编译器——这个新编译器是旧编译器的扩展——的过程。

 

(6) 编译程序的开发

构造编译程序,可以:

  • 使用机器语言或汇编语言作工具构造
  • 使用高级语言作工具构造
  • 使用机器语言或汇编语言构造编译程序的核心部分,使用高级语言构造编译程序的扩充部分
  • 使用编译程序自动生成工具构造

使用高级语言作工具构造编译程序可以大大节省程序设计的时间,并且编译程序易于阅读、维护和移植。常用的的编译程序开发技术主要包括:自编译、交叉编译、自展、移植技术和自动生成工具。

  • 自编译方式

用某种高级语言书写自己的编译程序称为自编译。

例如,假定A机器上已有一个PASCAL语言可以运行(即已有PASCAL语言编译程序),则可以用该PASCAL语言编写出一个功能更强的PASCAL语言编译程序(源程序),然后借助原有的PASCAL编译程序对新编写的PASCAL编译程序(源程序)进行编译,从而在编译后即得到一个能够在A机器上运行的功能更强的PASCAL语言编译程序。

  • 交叉编译

交叉编译是指用A机器上的编译程序来产生可在B机器上运行的目标代码。

  • 3. 自展技术

欲设计语言L的编译程序T。先对语言的核心部分L0构造一个小小的编译程序T0(可用低级语言实现),再以T0为工具构造一个能够编译更多语言成分L1的较大编译程序T1。如此扩展下去,就像滚雪球一样,越滚越大,最后形成人们所期望的整个编译程序。

这种通过一系列的自展途径而形成编译程序的过程叫做编译程序的自展技术。

  • 4. 编译程序自动生成工具

词法分析器的自动生成程序LEX

语法分析器的自动生成程序YACC

 ==================================================

C++编译器列表:

 

Some compilers that can be downloaded for free (do check their conditions/licenses before attempting commercial use):

Some compilers that require payment (some allow free downloads for trial periods):

 

 

posted @ 2012-03-27 21:01  Mr.Rico  阅读(4092)  评论(0编辑  收藏  举报