GCC passes分析(一)
来源:互联网 发布:同花顺龙虎榜数据 编辑:程序博客网 时间:2024/06/05 02:04
遍(passes)是GCC编译器源代码中的一个重要概念,对它们的理解是了解GCC源代码的架构的基础。本系列文章打算以此为契机,对GCC编译器源代码做一个概要性的分析,分析对象为GCC 4.9.1版本。
源代码中,与Pass相关的文件有:
1. passes.c
2. passes.def
3. pass_manager.h
另外,安装编译器的过程中,还会生成一个与pass相关的中间文件pass-instances.def,是源码下面的脚本文件gen-pass-instances.awk读取passes.def文件而生成的。
1)文件passes.def
本文件使用了4个宏:
INSERT_PASSES_AFTER;PUSH_INSERT_PASSES_WITHIN;NEXT_PASSTERMINATE_PASS_LIST2)文件passes-instances.def
本文件是由文件passes.def生成,内容与passes.def相似,只是增加了对每个pass出现(成为实例,instance)的统计。例如
NEXT_PASS (pass_forwprop)
在passes.def中出现了4次,则该宏在pass-instance.def中的出现形式为
NEXT_PASS (pass_forwprop, 1)NEXT_PASS (pass_forwprop, 2)NEXT_PASS (pass_forwprop, 3)NEXT_PASS (pass_forwprop, 4)3)各种宏的使用(pass_manger.h, passes.c)
在pass_manager.h文件中,使用方式如下。
#define INSERT_PASSES_AFTER(PASS)#define PUSH_INSERT_PASSES_WITHIN(PASS)#define POP_INSERT_PASSES()#define NEXT_PASS(PASS, NUM) opt_pass *PASS ## _ ## NUM#define TERMINATE_PASS_LIST()#include "pass-instances.def"
实际此文件只在pass_manager类的定义中,使用了一个宏”NEXT_PASS”,并把类的名称与实例编号连接起来。例如对于宏pass_forwprop,生成形如:
opt_pass *pass_forwprop_1;......opt_pass *pass_forwprop_4;</span>的几个定义,也即所有的类实例作为pass_manager类的成员变量。而其他几个宏,都被定义为空。
这些宏在passes.c中的使用略为复杂。首先需要解析其他一些相关的宏,主要包括GCC_PASS_LISTS和DEF_PASS_LIST,而它们在不同文件中的定义不一样。在pass_manager.h中,对它们的定义和使用如下所示。
#define GCC_PASS_LISTS \ DEF_PASS_LIST (all_lowering_passes) \ DEF_PASS_LIST (all_small_ipa_passes) \ DEF_PASS_LIST (all_regular_ipa_passes) \ DEF_PASS_LIST (all_passes)#define DEF_PASS_LIST(LIST) PASS_LIST_NO_##LIST,enum pass_list{ GCC_PASS_LISTS PASS_LIST_NUM};#undef DEF_PASS_LIST
其作用就是定义了一个枚举数据类型pass_list,把宏展开后,可知其包含5个元素,等价于下述代码段。
enum pass_list{ PASS_LIST_NO_all_lowering_passes, PASS_LIST_NO_all_small_ipa_passes, PASS_LIST_NO_all_regular_ipa_passes, PASS_LIST_NO_all_passes, PASS_LIST_NUM}
而在passes.c中,是pass_manager的构造函数pass_manager::pass_manager使用了GCC_PASS_LISTS、DEF_PASS_LIST以及passes.def文件中的4个宏。代码
#define DEF_PASS_LIST(LIST) pass_lists[PASS_LIST_NO_##LIST] = &LIST; GCC_PASS_LISTS#undef DEF_PASS_LIST
的作用是给几个数组赋初值,实际对应于下述语句序列:
pass[PASS_LIST_NO_all_lowering_passes] = &all_lowering_passes;pass[PASS_LIST_NO_all_small_ipa_passes] = &all_small_ipa_passes;pass[PASS_LIST_NO_all_regular_ipa_passes] = &all_regular_ipa_passes;pass[PASS_LIST_NO_all_passes] = &all_passes;
而用来赋值的4个数值all_lowering_passes,是构造函数的形式参数。
passes.c文件中对于passes.def中所使用到的四个针对宏的操作,也是采用先定义宏,在把def文件include进来的做法。定义宏的语句如下:
#define INSERT_PASSES_AFTER(PASS) \ p = &(PASS);#define PUSH_INSERT_PASSES_WITHIN(PASS) \ { \ opt_pass **p = &(PASS ## _1)->sub;#define POP_INSERT_PASSES() \ }#define NEXT_PASS(PASS, NUM) \ do { \ gcc_assert (NULL == PASS ## _ ## NUM); \ if ((NUM) == 1) \ PASS ## _1 = make_##PASS (m_ctxt); \ else \ { \ gcc_assert (PASS ## _1); \ PASS ## _ ## NUM = PASS ## _1->clone (); \ } \ p = next_pass_1 (p, PASS ## _ ## NUM, PASS ## _1); \ } while (0)#define TERMINATE_PASS_LIST() \ *p = NULL;
include进来的文件是pass-instances.def,以该文件开头的少量定义为例子,则上述定义实际上产生的语句序列为:
p = &(all_lowering_passes);do{ gcc_assert(NULL == pass_warn_unused_result_1); if(1 == 1) pass_warn_unused_result_1 = make_pass_warn_unused_result(m_ctxt); else { gcc_assert(pass_warn_unused_result_1); pass_warn_unused_result_1 = pass_warn_unused_result_1->clone(); } p = next_pass_1(p, pass_warn_unused_result_1, pass_warn_unused_result_1);}while(0)*p == NULL;
从以上的代码分析来看,NEXT_PASS的功能就是利用opt_pass的next域来建立一个链表,链表的头是有名字的opt_pass,也即all_lowering_passes、all_small_ipa_passes、all_regular_ipa_passes和all_passes之一。
INSERT_PASSES_AFTER(PASS)的使得当前类型为opt_pass **类型的指针p指向PASS,PASS在文件pass.def中对应于5种pass实例,分别是all_lowering_passes、all_small_ipa_passes、all_regular_ipa_passes、all_late_ipa_passes和all_passes。而这5个实例也是文件pass_manager.h中定义的类pass_manager的5个public类型的成员变量。next_pass_1的代码如下:
static opt_pass **next_pass_1 (opt_pass **list, opt_pass *pass, opt_pass *initial_pass){ /* Every pass should have a name so that plugins can refer to them. */ gcc_assert (pass->name != NULL); add_pass_instance (pass, false, initial_pass); *list = pass; return &(*list)->next;}
此函数执行前后的效果如下图所示。
也即NEXT_PASS是建立一个opt_pass的链表,表头为all_lowering_passes等5个变量之一。
而宏POP_INSERT_PASSES则是和 POP_INSERT_PASSES成对出现,同样是建立链表,但是改成使用opt_pass的sub域。
- GCC passes分析(一)
- GCC源码分析(一)——介绍与安装
- GCC源码分析(一)——介绍与安装
- gcc学习心得(一)
- gcc学习(一)
- gcc编译器(一)
- GCC 中文手册(一)
- GCC使用入门(一)
- GCC使用入门(一)
- GCC使用入门(一)
- gcc与Makefile(一)
- (一)GCC Makefile熟悉
- gcc和makefile(一)
- coding passes ->扫雷
- GCC源代码分析(1): GCC中的树
- GCC源代码分析(1): GCC中的树
- GCC源代码分析(1): GCC中的树
- gcc研究笔记(一)tree是什么
- [剑指offer-1516]调整数组顺序使奇数位于偶数前面
- 数据结构--顺序表
- 邮件同步已禁用问题解决方法
- 各种优化方法总结比较(sgd/momentum/Nesterov/adagrad/adadelta)
- LeetCode Largest Number 贪心
- GCC passes分析(一)
- 几点建议
- 在CentOS环境下mysql如何远程连接
- 1001. 害死人不偿命的(3n+1)猜想 (15)
- 首次使用
- 什么是持久化
- 1002. 写出这个数 (20)
- 我的CSDN
- android 中的Cursor