那么,GENERIC是什么呢?简单的讲,GENERIC就是规范的AST。一般来说,如
果一种前端语言的AST树均可以使用gcc/tree.h中所表示的树节点表示,那么该AST 就是
GENERIC AST。可以看出,GENERIC是一种规范的AST表示形式,引入GENERIC的目
的就是力求寻找一种与前端语言无关的AST统一表示,便于对各种语言的AST进行一种通
用的处理而已。从这个角度上,本书把AST和GENERIC合起来称为AST/GENERIC。实际
上,在GCC中,很多语言的前端处理并不包含AST到GENERIC的转换,而是直接将AST
转换成与语言无关的另外一种中间表示,即GIMPLE。
为了处理不同的前端语言及其相应的AST/GENERIC,GCC引入了一种与前端语言无关
的中间表示一GIMPLE。每种语言的前端处理系统都应该将该语言对应的AST/GENERIC
转换成GIMPLE,从而便于GCC在GIMPLE的基础上进行统一的中间处理和系统优化。
GIMPLE 这个词语很奇怪,笔者认为GIMPLE可以理解为GNU SIMPLE或者GCC SIMPLE。
GIMPLE是一种三地址码的中间表示形式,是McGill University McCAT编译工程中SIMPLE
中间语言的一种变化形式。GIMPLE与SIMPLE非常接近,但二者又有所不同,例如 SIMPLE
不支持 goto 语句,但GIMPLE 支持。
GIMPLE 中间形式由AST/GENERIC表达式转换而来,它们之间最主要的区别包括:
(1)AST形式与前端的编程语言是相关的,每种前端语言词法语法分析后形成的
AST是异构的,缺乏一种规范的、适合于各种语言的通用表示方法。而GIMPLE 中间表
示形式则是语言无关的,任何语言的前端处理均应按照GIMPLE的规范,将该语言前端
生成的AST/GENERIC形式转换成GIMPLE形式,从而提供给GCC进行后续语言无关的
处理。
(2)AST/GENERIC是树形结构,而GIMPLE形式从本质上讲是线性的中间表示序列,
可以更方便、更有效地进行后续的编译优化。需要注意的是,虽然GIMPLE是线性序列,但
在GIMPLE的表示中,依然使用了大量的树节点,这些节点往往作为GIMPLE语句的操作
数等元素出现。
(3)AST/GENERIC的属性节点类型非常多,而GIMPLE语句的类型相对较少。
从AST及GIMPLE的形式上来说,二者之间的主要区别是:
(1)在GIMPLE中通过引入临时变量保存中间结果,将AST表达式拆分成不超过三个
操作数的元组(Tuples)。
(2)AST中的控制结构,例如if-else、for、while等在GIMPLE表示中都被转换成条件
跳转语句。
(3)AST中的词法作用域(Lexical Scopes)在低级GIMPLE中被取消。
(4) AST中的异常区域(Exceptional Region)被转换成一个单独的异常区域树(Exception
Region Tree)。
在从AST向GIMPLE转换的过程中,GIMPLE的生成先后经历了两个阶段,分别称为高
级GIMPLE(High-Level GIMPLE)和低级GIMPLE(Low-Level GIMPLE)。在执行GIMPLE
处理过程(GCC中称为Pass,参见6.1节)pass_lower_cf(参见6.2节)之前,GIMPLE的形
式为高级GIMPLE,执行了该处理过程之后,GIMPLE就被完全转换成低级GIMPLE。高级
GIMPLE 中包含了一些例如GIMPLE_BIND等表示作用域的语句,还有一些例如GIMPLE_
TRY等嵌套的表达式等;低级GIMPLE 中就不存在GIMPLE_BIND、GIMPLE_TRY 这些语
句了。