编译器的基础
⑴ 编译器概述
编译器概述
编译器是一种重要的系统软件,其核心功能是将高级语言编写的程序转换成等价的低级语言(目标语言)编写的程序。以下是对编译器的详细概述:
一、编译器的基本概念
编译器负责将高级语言(如C/C++、java、Python等)编写的源代码转换成低级语言(如汇编、字节码或机器码)的程序。这种转换过程确保了高级语言的抽象性和可读性能够被转换成计算机能够直接执行或解释执行的代码。
- 高级语言:包括C/C++、Java、Python等,这些语言提供了丰富的语法和语义,使得程序员能够用更抽象的方式表达计算过程。
- 低级语言:
汇编:一种低级的、人类编程语言,使用助记符和符号来表示计算机的指令集。
机器码:计算机能够直接在硬件上执行的二进制代码,由0和1组成,代表着特定的CPU指令含义。
字节码:一种中间代码表示形式,通常不直接在硬件上执行,而是在虚拟机或解释器上运行。
从广义上看,编译器也可以被定义为将一种语言构造的程序翻译为等价的另一种语言构造的程序,例如将Java语言程序翻译成C语言程序,或将C语言程序翻译成Rust语言程序。
二、编译器的历史发展
- 1946年:世界上第一台计算机诞生,随之第一代编程语言诞生,即二进制语言。
- 1946~1950年:第二代编程语言(汇编语言)诞生,随之诞生了汇编器,从广义上来说,这也算是一种编译器。
- 1956~1957年:第三代编程语言(高级语言)诞生,1957年第一个商用编译器“Fortran编译器”诞生。
- 20世纪60年代:诞生了许多新的编程语言,如Pascal、Cobol、Algol、PL/I等,编译器得到了迅速的发展。
- 20世纪70年代:Dennis Ritchie开发了C编程语言,随之第一个C语言编译器发布,这个编译器将C代码编译成PDP-11计算机上的机器代码。
- 20世纪80年代:编译器技术进一步演进,包括了对编译器优化的研究,以提高程序的性能。
- 从20世纪80年代末到21世纪:众多现代高级编程语言出现,如C++、Java、Python、Ruby等,编译器再一次得到了迅猛的发展,出现了类似如JIT等编译技术。
- 现代编译器:随着硬件和编程语言的不断发展,编译器技术也不断演进,以支持多核处理器、并行计算、GPU编程等新兴技术。近几年,随着深度学习、机器学习的发展,AI编译器也得到了快速的发展。
三、编译器的基本结构
编译器的基本结构可以分为前端、中端和后端。
前端:主要负责理解程序的语法形式和内容,即程序的语法和语义。前端会检查源程序代码是否符合正确的语法和语义,如果检查通过,它会给该程序建立一个中间表示代码。前端一般可分为词法分析、语法分析、语义分析和中间代码生成四个阶段。
中端:现代编译器引入的结构,主要使用合适的优化来提高代码质量,并将优化后的程序输出给后端进行进一步编译。这里的“提高”可以有多种含义,通常指执行速度更快、运行时耗费资源较少、占用的内存空间较小等。中端优化并不是越多越好,可能会出现互斥的情况,如优化执行速度有可能会导致占用的内存空间变大,所以优化需要根据具体目标进行优化。
引入中端的目的主要有两个:一是前端和后端解耦,即多个语言的前端都可以生成公共的中端代码,而中端代码又可以进一步生成不同目标机器的代码;二是实现通用优化,在中端上可设计并实现与语言以及目标机器无关的程序优化算法,对程序的性能、规模或其它指标进行通用优化。
后端:主要任务是读入程序中间表示形式,并生成目标机器的指令代码。后端一般可分为指令选择、指令调度、寄存器分配以及代码发射四个阶段。
四、编译器框架
现代主流开源的编译器框架主要有GCC和LLVM。
GCC:经过多年的开发和测试,GCC已经成为一个成熟且稳定的编译器。它支持多种编程语言,如C、C++等,并在各种平台上得到了广泛的验证和使用。GCC的架构相对一体化,代码之间的耦合度较高,因此扩展难度相对较大。
LLVM:LLVM是一个高度模块化的编译器框架,成为了许多编程语言的首选编译器基础设施。与GCC相比,LLVM的架构更加灵活,扩展难度相对较小。然而,LLVM的文档更新速度相对较慢,在某些方面相对于GCC的成熟度较低。
以下是GCC和LLVM的架构图:
在编译器框架中,除了编译器本身外,还包括预处理器、汇编器、链接器和加载器等组件。这些组件共同协作,完成从源代码到可执行程序的整个编译过程。
- 预处理器:负责将源程序聚合在一起,并处理头文件包含和宏等工作。
- 汇编器:将编译器生成的汇编语言程序进行处理,生成可重定位的机器代码。
- 链接器:将多个可重定位的机器代码文件以及库文件链接到一起,形成真正能在机器上运行的二进制代码。
- 加载器:负责将可执行程序从存储介质加载到计算机的内存中,以便执行程序。
五、总结
编译器是计算机系统中不可或缺的重要组件,它负责将高级语言编写的程序转换成计算机能够直接执行或解释执行的代码。随着硬件和编程语言的不断发展,编译器技术也在不断演进,以支持更多的特性和优化。了解编译器的基本概念、历史发展、基本结构和编译器框架,有助于我们更好地理解计算机系统的运作原理,并优化我们的程序代码。
⑵ java编译器由什么语言编写
Java编译器主要是由Java语言编写的。这种做法在编程语言实现中较为常见,被称为“自己编译自己”,也称作“编译器循环”(bootstrap compilation)。以下是对Java编译器编写语言的详细说明:
一、Java编译器的主要编写语言
- Java语言:Java编译器的大部分代码是用Java自身编写的。这意味着Java编译器在编译Java源代码时,实际上是在用已经编译好的Java编译器部分来编译尚未编译的部分,形成了一个循环编译的过程。
二、Java编译器的组成部分
前端(Front-end):虽然未直接提及前端是用什么语言编写的,但通常前端负责词法分析、语法分析,并生成抽象语法树(AST)。这部分代码很可能也是用Java编写的,因为它需要与编译器的其他部分紧密协作。
中间表示(Middle-end):这部分将前端生成的AST转换成中间表示形式,如Java字节码。这一步骤是编译器优化和代码生成的重要基础,同样很可能是用Java编写的。
后端(Back-end):后端负责将中间表示转换成目标机器代码或进一步优化成更高效的字节码。虽然不同编译器的后端实现可能有所不同,但Java编译器的后端很可能也是用Java编写的,或者至少是与Java编写的部分紧密集成的。
综上所述,Java编译器主要是由Java语言编写的,这体现了Java语言的强大和灵活性,使其能够用于实现自身的编译器。同时,这种“自己编译自己”的方式也简化了编译器的开发和维护过程。