本文以GCC-4.4.0为例,介绍GCC编译器源代码的结构,希望对家理解GCC编译器的工作原理有一定的帮助。
[root@localhost gcc-4.4.0]# ls
ABOUT-NLS COPYING3 libcpp log mkdep
boehm-gc COPYING3.LIB libdecnumber ltgcc.m4 mkinstalldirs
ChangeLog COPYING.LIB libffi ltmain.sh move-if-change
ChangeLog.tree-ssa COPYING.RUNTIME libgcc lt~obsolete.m4 NEWS
compile depcomp libgfortran ltoptions.m4 README
config fixincludes libgomp ltsugar.m4 stage_final
config.guess gcc libiberty ltversion.m4 symlink-tree
config-ml.in gnattools libjava MAINTAINERS tags
config.rpath include libmudflap maintainer-scripts ylwrap
config.sub INSTALL libobjc Makefile.def zlib
configure install-sh libssp Makefile.in
configure.ac intl libstdc++-v3 Makefile.tpl
contrib LAST_UPDATED libtool-ldflags MD5SUMS
COPYING libada libtool.m4 missing
GCC的源代码中包含了大量的目录和文件,在分析GCC代码时,需要从整体上了解代码的组织形式。一般来说,GCC源代码中的不同目录包含了不同功能的代码。
第一部分:GCC源代码典型目录介绍
1. 高级语言相关的代码
例如,在gcc/目录以下几个目录,分别处理Ada、Java、Fortran、Object-C及C++的词法分析、语法分析、语义分析等典型的语言相关的功能。这部分代码也通常称为GCC前端处理。由于C语言是GCC支持的最基础的语言,所以C语言的前端处理的部分代码在gcc目录下。
gcc/ada
gcc/java
gcc/fortran
gcc/objc
gcc/cp
2. 机器描述代码
这部分代码主要包括目标机器的机器描述文件(Machine Description File,即md文件)、目标机器相关的宏定义及函数实现等。例如在GCC/config/i386目录下,i386.md及相关md文件就是机器描述文件,i386.c及i386.h则定义了相关的函数及宏定义等。下面目录分别对应了Alpha、ARM、i386、IA64及MIPS等机器的后端处理代码。这部分代码是GCC移植到某种平台上最多涉及的部分。
gcc/config/alpha
gcc/config/arm
gcc/config/i386
gcc/config/ia64
gcc/config/mips 等
3. 语言无关且机器无关的通用代码
这部分代码也通常称为GCC的中端,主要包括GIMPLE及RTL处理部分,包括GIMPLE的生成、基于GIMPLE的编译优化、RTL生成、基于RTL的编译优化以及最后的汇编代码生成等主要代码均在gcc目录下。
gcc/
4. 机器相关的生成器代码
这一部代码主要用来提取目标机器描述文件及相关文件中的信息,并生成相关的C代码和头文件。原因可以这样解释一下:因为目标机器描述文件,即md文件主要使用RTL语言进行描述,不能直接参与编译,所以需要使用生成器代码将其内容转换生成C代码,这部分代码就反映特定机器的机器特性,从而将GCC代码适配到不同的目标机器上。
这部分代码在gcc目录下,包括了以gen开头一些c文件。例如:
[root@localhost gcc]# pwd
/root/gcc-4.4.0/gcc
[root@localhost gcc]# ls gen*
genattr.c genconditions.c gengenrtl.c genmddeps.c genpreds.c
genattrtab.c genconfig.c gengtype.c genmodes.c gen-protos.c
genautomata.c genconstants.c gengtype.h genmultilib genrecog.c
gencheck.c genemit.c gengtype-lex.c genopinit.c gensupport.c
genchecksum.c genextract.c gengtype-lex.l genoutput.c gensupport.h
gencodes.c genflags.c gengtype-parse.c genpeep.c
第二部分:GCC编译阶段简介
总体说来,GCC(编译程序通常称为cc1)的功能可以分为如下几个阶段
(1)对输入的高级语言源代码进行词法语法语义分析,构造AST
(2)AST的规范化(Genericize)
(3)将语言相关的AST转换成GIMPLE
(4)基于GIMPLE的优化
(5)RTL生成(将GIMPLE转换成RTL)
(6)基于RTL的编译优化
(7)目标机器上的汇编代码生成
第三部分:GCC编译功能与GCC源代码直接的对应关系
上图中给出了编译器各个功能阶段与源代码的对应关系,其中的关系比较清晰,只解释几个要点。
(1)GIMPLE生成及优化、RTL的通用优化这部分功能对应的“语言无关及机器无关的通用代码”。
(2)RTL的生成过程需要考虑目标机器支持的指令等信息,所以RTL的生成是与目标机器描述相关的,需要由生成器代码从机器描述代码中提取目标机器的信息,从而支持RTL的生成。
(3)机器描述部分的代码不能直接参与生成编译程序,需要由生成器代码将其转换成c语言,动态生成编译器的一部分源代码,从而指导编译器完成RTL生成以及汇编代码生成。