GIMPLE为一个三地址表示,通过将GENERIC表达式分解成不超过3个操作数(有些情况例外,比如函数调用)的元组。GIMPLE在很大程度上受McGill大学的McCAT编译器项目中使用的SIMPLE IL的影响。我们也做了一些改变,例如SIMPLE不支持(GIMPLE支持的)goto
。
临时对象被引入,用来存放计算复杂表达式所需要的中间值。另外,GENERIC中所有的控制结构被下降为条件跳转,词法作用域被移除,异常区域被转换成一个异常区域tree。
将GENERIC转换成GIMPLE的编译器过程,被称作‘gimplifier’。‘gimplifier’按递归的方式进行工作,从原始的GENERIC表达式生成GIMPLE元组。
早期用于GIMPLE表示的实现策略为,使用与前端表示解析树相同的内部数据结构。这会简化实现,因为我们可以利用现存的功能和接口。然而,与抽象语法树(AST)相比,GIMPLE是一个更加严格的表示,因此其不需要tree数据结构所提供的完整复杂的结构。
函数的GENERIC表示被存放在所关联的FUNCTION_DECL
tree结点的DECL_SAVED_TREE
域。其通过调用gimplify_function_tree
来转换成GIMPLE。
如果前端想在tree表示中包含语言特定的tree代码,并提供给后端,则其必须提供一个LANG_HOOKS_GIMPLIFY_EXPR
的定义,其知道如果将前端的tree转换成GIMPLE。通常这样的钩子会涉及许多相同的代码,用来将前端tree扩展成RTL。该函数可以返回被完全下降的GIMPLE,或者可以返回GENERIC tree并让主gimplifier将它们下降;这通常会更简单些。没有被完全下降的GIMPLE被称为“High GIMPLE”,由pass_lower_cf
过程之前的IL组成。High GIMPLE包含一些容器语句,例如词法作用域(由GIMPLE_BIND
来表示),以及嵌套表达式(例如,GIMPLE_TRY
)。而“Low GIMPLE”将所有隐式的控制跳转或者异常表达式都直接暴露成IL和EH区域tree。
C和C++前端目前直接从前端tree转换成GIMPLE,并将其交给后端,而不是首先转换成GENERIC。它们的gimplifier钩子知道所有的_STMT
结点,以及如何将它们转成GENERIC形式。在genericization过程中有一些工作,应该首先被运行,但是STMT_EXPR
的存在意味着,为了将所有的C语句转换成GENERIC,则需要遍历整个tree,所以一起下降会更简单些。如果有人写了一个优化过程,其在更高级别的tree上会工作的更好,则这在将来可能会有改变,但是目前所有的优化都是在GIMPLE上进行的。
你可以使用选项-fdump-tree-gimple来转储一个类C的GIMPLE表示形式。