(二) GNU GCC 编译器及其编译流程概述_gcc 的编译过程分为那几个阶段,每个阶段都做了些什么 (1)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

GCC编译器的前端非常强大,经过多年的发展,GCC 编译器前端已经变得相当成熟,它能编译现在计算机界主流的高级编程语言,前端支持多种编程语言,如 C、Fortran、Pascal、Objective-C、Java、Ada、Go等,同样支持这些语言的标准库libstdc++、 libgcj 等。

GCC编译的前端将不同的高级编程语言经过词法分析、语法分析转化为与前端语言无关的统一的中间表示。有了与前端无关的中间表示,GCC的前端将不同的高级编程语言转换成这种中间表示,这就是GCC处理器支持多种编程语言的根本原因。

后端

编译器分为前端和后端,在GCC的组成结构中,后端负责将RTL表示的中间形式进行优化并最终生成对应平台的汇编代码。GCC后端是在RTL的中间形式上进行的,在RTL上做大量的优化,包括机器有关的优化和机器无关的优化。

RTL是从特定机器平台中抽象出的模型表示的,实际上它是一种抽象出来的机器模型。和所有实际存在的平台一样,这个抽象出来的机器模型也有它自己的“指令系统”。机器模型的“指令系统”在GCC中定义为标准指令模板的一系列指令,这些指令是GCC内部使用的。GCC的后端为不同的平台提供了描述这些指令模板的接口文件,这些指令模板在不同平台上的描述将GCC映射到不同的平台上去,这样就可以把GCC的后端移植到不同的平台上去。通过机器描述支持多种体系结构,机器描述文件给出机器各种参数的宏定义和指令集。这使得GCC移植非常方便,针对目前广泛使用的目标机器的体系结构提供了大部分的支持,后端支持的平台有x86、mips、Alpha、ARM、AVR、IA-64、SPARC、PowerPC等30多种平台。

gcc编译器------前后端的纽带:遍(pass)管理器

GCC编译器的前端将高级语言源码经过词法分析、语法分析生成与高级语言无关的低级中间层表示,后端负责将RTL表示的中间形式进行优化并最终生成对应平台的汇编代码。GCC的前端到后端一共用了三种中间表示,GCC用遍管理器将其连成一个整体。GCC在编译和优化中,对编译对象(一般以函数或文件为处理对象)的一次编译处理,称为pass(遍)。GCC的整个编译处理过程组成了pass_list,这个pass_list包含的所有遍就是整个GCC编译时所经过的过程。遍管理器在GCC编译流程中的作用如下图所示:

GCC编译器前端将源语言进行词法分析、语法分析后得到抽象语法树(AST),该过程为GENERIC。GENERIC之后简化为GIMPLE的中间表示,在GIMPLE层上加入控制流程图(CFG),在这个中间表示层上进行一系列的前期优化(例如,过程间优化IPO,静态单一化赋值SSA等),再将GIMPLE转换成RTL中间表示,同样在RTL上进行一系列的优化,最终生成汇编代码,整个过程在图1中用带箭头的实线表示。从GENERIC到GIMPLE再到RTL,在GCC中是用一系列的遍(pass)连起来的(在图1中用带箭头的虚线表示)形成一个 pass_list。

gcc编译器----中间表示

中间表示( intermediate representation, IR) 指编译器对于源程序进行扫描后生成的内部表示,代表源程序的语义和语法结构,编译器的各个阶段都在IR上进行分析或优化变换,因而它对编译器的整体结构、效率和健壮性都有着极大的影响[38]。中间表示对提高编译器的可移植性以及代码生成起到关键作用,在编译器的研究中,应该设计一种结构良好的中间表示,这种中间表示应在适当的抽象层次上,向上能支持多语言的映射,向下能适应多平台转换且易于进行各种优化。

对于现代编译器来说,编译器前端和后端分别指分析输入源语言和生成目标平台汇编代码的两编译阶段,大部分现代编译器在前端和后端之间会有个中间表示层。有了一个设计良好的中间表示,有m种前端编程语言(C\C++、Fortran、Ada、Java等)和n种后端平台(x86、MIPS、Sparc、ARM等)的编译器设计,这样就减少了为了设计m中语言和n个平台从而设计m*n个编译器设计。

中间语言的使用可以大大减低开发各个语言和各个平台所需编译器的工作量。支持多种编程语言和多种后端平台的编译器可以通过使用一种中间表示来实现。总的来说,中间表示层在减低编译器开发方面的开销和复杂度上功不可没。有些中间表示语言的设计是专门为了支持一种特定的语言,例如Jvm的设计仅仅是为了支持java语言,而大多数中间表示语言的设计是用来将不同的前端语言和后端平台连接起来。

GCC编译器有三种中间表示语言,一种AST/GENERIC比较完善的表示了前端语言的信息,一种GIMPLE用来在相对比较高的层次来表示源语言程序。而另外一种rtl用来高度抽象的表示从特定平台抽象出来的机器指令。

一、GENERIC形式与前端的编程语言是相关的,每种前端语言词法语法分析后形成的AST/GENERIC是异构的,GENERIC包含了前端语言所有的信息。

GCC编译器的前端将高级语言源码经过词法分析、语法分析生成GENERIC。GENERIC是一棵抽象语法树(Abstract Syntax Tree,AST),用数据结构中的树(tree)结构表示。GCC编译器的抽象语法树是源程序的一种中间表示形式,比较直观的表示出源程序的语法结构,并含有源程序结构显示所需要的全部静态信息。GCC 格式的 AST 文件是 GCC 编译源程序时产生的,以文本方式记录源程序抽象语法树的文件。

C语言源码和对应的GENERIC表示如下所示:

C语言源码:

int sum(int a,int b)
{
    int c;
    c=a+b;
    return c;
}

GENERIC表示(部分):

GCC的前端将源语言解析生成GENERIC。不同的前端高级编程语言,GCC前端生成的GENERIC形式不尽相同。每种前端语言词法语法分析后形成的AST/GENERIC是异构的,需要转换成一种统一的中间形式进行后续的处理,这种统一的中间表示形式就是GIMPLE形式。
(关于 GIMPLE 命名是从编译器 SIMPLE IL 改造合成而来)

二、中间表示GIMPLE:GIMPLE是一种三地址码的中间表示形式。

GIMPLE中间形式由GENERIC表达式变换而来,与GENERIC相比,主要有如下的转换:

(1)、通过引入临时变量保存中间结果,并将GENERIC表达式拆分成不超过三个操作数的元组(tuples)。

(2)、GENERIC中的控制结构,例如if-else,for,while等也被转换成条件转移。

(3)、词法作用域(lexical scopes)被取消了。

(4)、异常区域(lexical scopes)被转换成一个单独的异常区域树(exception region tree)。

GIMPLE是通过简化GENERIC得来的,这样做的好处通过下面的例子比较来说明。

xxx@localhost$ cat compare_generic_to_gimple.c

int func(int j, int k) 
{
	int i;
	for (i=0;i>=10;i++) 
	{
		j = i + 1;
		 
		k = j + i + 5;
	}
	return k;
}

int func(int j, int k) 
{
	int i;
	for (i=0;i>=10;i++) 
	{
		j = i + 1;
		 
		    k = j + i + 5;
	}
	return k;
}

使用如下命令进行编译,其中-fdump-tree-gimple选项打印出GCC处理的中间过程,包括列出GENERIC的中间形式和GIMPLE中间形式。

xxx@localhost$ paag-linux-gcc -fdump-tree-gimple -S -o compare_generic_to_gimple.s compare_generic_to_gimple.c
 xxx@localhost$ paag-linux-gcc -fdump-tree-gimple -S -o compare_generic_to_gimple.s compare_generic_to_gimple.c

下表分别给出其GENERIC形式和GIMPLE表示,并进行对比分析。

从上图可以看出,GIMPLE相比较GENERIC而言的优势,也就是为什么要进行GENERIC形式到GIMPLE形式的转化,主要有以下几个方面的原因:

(1) GENERIC是树结构表示和存储的,对于分析和处理非常不便。

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值