gcc源码分析 GIMPLIFY相关
四、GIMPLIFY相关
GCC通过前端的词法/语法分析后,将高级编程语言转换成抽象的AST中间表示。为了对AST中间表示进行语言无关的处理和优化,GCC引入了GIMPLE。GENERIC就是规范的AST。一般来说,如果一种前端语言的AST树均可以使用树节点表示,那么该AST就是GENERIC/AST,GIMPLE为是了处理不同的前端语言及其相应的AST/GENERIC, GCC引入的一种与前端语言无关的中间表示。GIMPLE是一种三地址码的中间表示形式。在从AST向GIMPLE转换的过程中,GIMPLE的生成先后经历了两个阶段,分别称为高级GIMPLE(High-Level GIMPLE)和低级GIMPLE(Low-Level GIMPLE)。
4.1 gcc全局符号表与符号分析
4.1.1 全局符号表
全局符号表中的主要符号都是伴随源码解析过程中AST树的生成而生成的,在整个编译单元中所有外部声明都被解析为AST树节点后,所有的外部声明都总能对应到全局符号表中的一个函数节点或一个变量节点,在gcc中有一个全局变量symbol_table *symtab,这个变量用于记录编译过程中产生的函数和符号,symbol_table类大体结构表如下所示:
## gcc/cgraph.h
class symbol_table
{
public:
friend class symtab_node;
friend class cgraph_node;
friend class cgraph_edge;
........
int cgraph_count; /* 记录当前全局符号表中的函数节点个数*/
int cgraph_max_uid;
int cgraph_max_summary_id;
int edges_count;
int edges_max_uid;
int edges_max_summary_id;
/*
这里是一个链表,其中链接当前编译单元的所有符号节点,函数节点实际上是一个 cgraph_node结构体
*/
symtab_node* GTY(()) nodes;
asm_node* GTY(()) asmnodes;
asm_node* GTY(()) asm_last_node;
cgraph_node* GTY(()) free_nodes;
cgraph_edge * GTY(()) free_edges;
int order;
/* Set when whole unit has been analyzed so we can access global info. */
bool global_info_ready;
/* What state callgraph is in right now. */
enum symtab_state state;
};
这个symtab->nodes成员,记录了当前编译单元所有的函数和变量节点信息:对于函数而言,其节点信息通过一个cgraph_node结构体去表示;对于变量来说,其节点信息是通过一个varpoool_node结构体来表示,都是可以链接到nodes上。
在分析语法解析时,解析一个函数时(c_parser_declaration_or_fndef)会调用cgraph_node::get_create为当前函数创建一个函数节点(cgraph_node);解析到一个变量时(同样c_parser_declaration_or_fndef)会调用varpool_node::get_create为变量创建一个变量节点(varpool_node),这两种情况创建的节点都会链接到全局符号表中。
函数节点的分析,主要是对其进行gimplify(包括gimple高端化和gimple低端化),变量节点的分析,主要是对其做对齐操作
4.1.2 函数节点的gimplify
函数节点的分析,主要是对其进行gimplify,当分析完毕后,会设置symtab_node.analzed = true,代表此节点已经分析完毕,cgraph_node::analyze函数大体如下:
void
cgraph_node::analyze (void)
{
tree decl = this->decl; /*从函数节点中找到此函数的声明树节点*/
location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
if (thunk.thunk_p)
{
cgraph_node *t = cgraph_node::get (thunk.alias);
create_edge (t, NULL, 0, CGRAPH_FREQ_BASE);
callees->can_throw_external = !TREE_NOTHROW (t->decl);
/* Target code in expand_thunk may need the thunk's target
to be analyzed, so recurse here. */
if (!t->analyzed)
t->analyze ();
if (t->alias)
{
t = t->get_alias_target ();
if (!t->analyzed)
t->analyze ();
}
if (!expand_thunk (false, false))
{
thunk.alias = NULL;
return;
}
thunk.alias = NULL;
}
if (alias)
resolve_alias (cgraph_node::get (alias_target), transparent_alias);
else if (dispatcher_function)
{
cgraph_function_version_info *dispatcher_version_info
= function_version ();
if (dispatcher_version_info != NULL
&& (dispatcher_version_info->dispatcher_resolver
== NULL_TREE))
{
tree resolver = NULL_TREE;
gcc_assert (targetm.generate_version_dispatcher_body);
resolver = targetm.generate_version_dispatcher_body (this);
gcc_assert (resolver != NULL_TREE);
}
}
else
{
push_cfun (DECL_STRUCT_FUNCTION (decl)); /* 重置全局的current_function_decl到当前待分析函数 */
assign_assembler_name_if_neeeded (decl); /* 为此函数设置汇编名 */
if (!gimple_has_body_p (decl)) /* 若当前函数节点尚未做过gimple 高端化,则对其进行gimple 高端化 */
gimplify_function_tree (decl);
/* Lower the function. */
if (!lowered) /* 若当前函数节点尚未做过giomple低端化,则对其进行gimple 低端化 */
{
if (nested)
lower_nested_functions (decl);
gcc_assert (!nested);
gimple_register_cfg_hooks ();
bitmap_obstack_initialize (NULL);
execute_pass_list (cfun, g->get_passes ()->all_lowering_passes);/* gimple低端化并不是执行某个具体的函数,而是执行 all_lowering_passes链表中的所有pass,这些pass执行完毕则代表gimple低端化完成 */
free_dominance_info (CDI_POST_DOMINATORS);
free_dominance_info (CDI_DOMINATORS);
compact_blocks ();
bitmap_obstack_release (NULL);
lowered = true; /* 整个all_lowering_passes中所有pass都执行完毕,则在函数节点中标记gimple低端化结束 */
}
pop_cfun (); /* 恢复之前的cfunc / current_function_decl */
}
analyzed = true; /*标记分析完毕*/
input_location = saved_loc;
}
由上面的函数节点分析基本上就是gimple高端化+gimple低端化,其中:gimple高端化通过函数gimplify_function_tree完成,gimple低端化通过all_lowering_passes中的一系列pass完成,这些pass如下:
## gcc/passes.def
## 这里展示的所有all_lowering_passes可能被执行的pass,是否被执行,取决于gcc的编译选项和被编译代码的编译选项。
INSERT_PASSES_AFTER (all_lowering_passes)
NEXT_PASS
标签:node,decl,gcc,GIMPLIFY,cgraph,源码,gimple,节点,函数
From: https://blog.csdn.net/swh547/article/details/139194889