cdn网站加速,小程序模板怎么导入,网站开发属于哪个大学专业,深圳找做兼职女上班的网站大约4年前#xff0c;我加入了GDNT - 北电网络在中国的合资企业#xff0c;参与3G UMTS无线接入网的研发工作。与GCC有了第一次亲密的接触#xff08;之前使用的是MS的VC#xff09;。彼时#xff0c;北电在其诸如#xff0c;UMTS、CDMA、及自行开发的众多工具等项目中我加入了GDNT - 北电网络在中国的合资企业参与3G UMTS无线接入网的研发工作。与GCC有了第一次亲密的接触之前使用的是MS的VC。彼时北电在其诸如UMTS、CDMA、及自行开发的众多工具等项目中此后在4G项目,Wimax及Lte中将GCC作为标准编译器来使用。每周我都需要进行数次的loadbuild编译出load文件进行测试以验证我对一些bug的修正代码。每次loadbuild编译的文件数以千计最后的执行文件可至百兆的尺寸。而GCC的运行令人惊异地稳定。这些年来我只碰到过2次GCC的崩溃其中一次还是因为我为了达到模板分离编译separate compilation of template的效果GCC至今未支持这一特性。据我所知目前只有EDG的前端能做到。而且在C标准稳定下来之前【ISO-IEC - 14882-1998】EDG的前端是实际的标准。在http://www.edg.com/可以找到有关EDG的情况使用了奇怪的代码含有错误的C代码而导致生成错误的中间树代码很遗憾GCC未能检出语法错误。从而触发了GCC内部的断言。因此GCC虽然退出但给出了详细的错误转储。还算退出得比较体面。 这个神奇的工具令人称奇虽然以前我也学过编译原理但是面对GCC我觉得对它知之甚少。多亏GCC是开源的使我得以窥探其神秘面纱后的容颜。这些年虽然自觉对GCC已有相当的了解但远还未到究竟。借此博客我将和大家分享这些年来学习GCC的笔记所关注的GCC为3.4.6版C前端运行平台x86/Linux目标机器x86/Linux。而这个笔记还在增长中还远未结束。 参考文献 [1] Programming language pragmatics, 2nd edition [2] gccint, version 3.4.6 [3] ISO-IEC-14882-2003 [4] The C Preprocessor April 2001, for GCC V3 [5] cppinternals [6] Using the GNU Compiler Collection [7] Inside The C Object Model, by Stanley B.Lippman [8] GCC Complete Reference [9] The design and evolution of C, by Bjarne Stroustrup [10] Linkers Loaders, by John R. Levine [11] Efficient Instruction Scheduling Using Finite State Automata, by Vasanth Bala, Norman Rubin [12] Compilers: Principles, Techniques, and Tools, 2nd edition 其中[2]和[5]保存在目录“YOUR-GCC-SOURCE-DIR/gcc/doc”下。[1][7][9][10]和[12]给出了一些有用的背景知识。 准备工作 一些重要的GCC源码是由GCC自带工具生成的。在深入看代码前我们首先需要编译GCC生成这些源码。至于如何下载源代码http://gcc.gnu.org/mirrors.html是官方的下载地址编译前配置及编译网上有丰富的资料在此略过注如果已经装有GCC使用g -###可查看GCC的配置命令。 GCC的架构 GCC可简单地分为2部分前端和后端。预处理器如果存在、词法分析器和语法分析器在前端实现前端的作用是将源语言写的程序转换成与语言无关的中间形式。因此理论上引入对新语言的支持只需要实现预处理器、词法分析器和语法分析器。但实际上一般的我们还需要写一些代码以确立运行时环境。 在GCC 3.4.6这个通用的中间语言是RTLregister transfer language。RTL是一种简单的语言很容易就能翻译成汇编代码。因此直接将源语言转换为RTL不太合适。事实上前端首先会将代码转换成中间树并进行大量的处理然后再进一步变换为RTL并送入后端。 后端的作用则是生成汇编代码。作为广泛使用的编译器GCC可以支持各种流行的平台。为了实现这个目的GCC采用了机器描述文件对目标机器的指令集、流水线结构、甚至架构本身带来的优化机会进行描述。对于目标机器配置GCC时需指定这些描述文件将被多个工具处理生成相应的源代码然后用于编译GCC。因此引入新机器的主要工作在于提供机器描述文件一般而言还需要定义一些处理函数提供必要的处理逻辑。 在以下地址http://www.ibm.com/developerworks/cn/linux/l-gcc4/?cadwcn-newsletter-linux可以找到关于GCC较新版本的信息。 前端 当我们调用 ”gcc –o xxx xxx.c” 时事实上我们的请求会转交给一个shell这个shell会解析这个调用命令并根据它所能认识的命令行选项在所运行的平台上进行相应的准备。然后根据源文件的后缀调用相匹配的编译器并将其不能识别的命令行选项一并传入。这里我们不关心这个shell我们专注于真正的编译器。 1. 概览 前端读入源程序进行语法分析然后将其转换为语言无关形式。理论上每个前端可以使用独特的形式。不过在GCC中为了尽可能地重用代码不同前端生成的中间树都使用同一组树节点。显然这组节点需要足够的多样性以满足不同语言的要求。这组树节点对于C/C前端的意义非同寻常我们首先需要对其着手。 1.1. 前端中树的表达形式 为了支持已经存在及以后将会加入的前端GCC定义了数十种的树节点不是所有节点都能作为叶子节点。所有的节点在其结构体定义中以下面的结构作为第一个成员。 129 struct tree_common GTY(()) in tree.h 130 { 131 tree chain; 132 tree type; 133 134 ENUM_BITFIELD(tree_code) code : 8; 135 136 unsigned side_effects_flag : 1; 137 unsigned constant_flag : 1; 138 unsigned addressable_flag : 1; 139 unsigned volatile_flag : 1; 140 unsigned readonly_flag : 1; 141 unsigned unsigned_flag : 1; 142 unsigned asm_written_flag: 1; 143 unsigned unused_0 : 1; 144 145 unsigned used_flag : 1; 146 unsigned nothrow_flag : 1; 147 unsigned static_flag : 1; 148 unsigned public_flag : 1; 149 unsigned private_flag : 1; 150 unsigned protected_flag : 1; 151 unsigned deprecated_flag : 1; 152 unsigned unused_1 : 1; 153 154 unsigned lang_flag_0 : 1; 155 unsigned lang_flag_1 : 1; 156 unsigned lang_flag_2 : 1; 157 unsigned lang_flag_3 : 1; 158 unsigned lang_flag_4 : 1; 159 unsigned lang_flag_5 : 1; 160 unsigned lang_flag_6 : 1; 161 unsigned unused_2 : 1; 162 }; 上面在134行在3.4.6版ENUM_BITFIELD将被扩展为”__extension__ enum”, 131行的chain如果需要能将该节点链入树。 下面给出了结构体中部分的标识域的含义及访问它们的宏定义红字部分。 Ø TREE_TYPE ((NODE)-common.type) 用于所有表示表达式的节点代表该表达式的数据类型。 ² 在POINTER_TYPE节点中代表该指针指向的类型。 ² 在ARRAY_TYPE节点中代表数组元素的类型。 ² 在VECTOR_TYPE节点中代表vector元素的类型某些芯片的寄存器足够大足以存放多个标量这一组标量称为vector类型。 Ø TREE_ADDRESSABLE((NODE)-common.addressable_flag) ² 在VAR_DECL节点中非零值表示该节点代表的变量的地址在程序的其他地方被使用不能产生将该变量置入寄存器的代码。 ² 在FUNCTION_DECL节点中非零值表示该节点代表的函数的地址在程序的其他地方被使用。该函数必须被编译出来即便它是内联函数在被调用的地方内联函数被展开为函数体故不需要单独编译出来。 ² 在FIELD_DECL节点中非零值表示该节点代表的成员的地址允许被程序员设定。彼时该标识用于别名识别参见函数record_component_aliases。 ² 在CONSTRUCTOR节点中非零值表示该构造函数必须在内存中创建对象而不是在寄存器中。 ² 在LABEL_DECL节点中非零值表示一条目标为该lable的goto语句出现在所有执行跳转到该label的goto语句需要恢复栈的绑定域外。 ² 在所有*_TYPE节点中非零值表示该类型的所有对象必须是完全取址的。这意味着例如这些对象任何一部分都不能放入寄存器中。 ² 在IDENTIFIER_NODE节点中非零值表示某些同名的外部声明的地址已被引用。这关系到内联函数。 Ø TREE_STATIC ((NODE)-common.static_flag) ² 在VAR_DECL节点中非零值表示该变量为静态类型。 ² 在FUNCTION_DECL节点中非零值表示该函数已被定义。 ² In a CONSTRUCTOR, nonzero means allocate static storage. Ø TREE_VIA_VIRTUAL ((NODE)-common.static_flag) ² 在TREE_LIST或TREE_VEC节点中非零值表示所对应的类其派生关系为虚继承virtual。 Ø TREE_CONSTANT_OVERFLOW ((NODE)-common.static_flag) ² 在INTEGER_CSTREAL_CSTCOMPLEX_CST或 VECTOR_CST节点中非零值表示在常量折叠中发生溢出。它与TREE_OVERFLOW的区别在于如果常量表达式发生溢出ANSI C要求给出诊断信息。 Ø TREE_SYMBOL_REFERENCED (IDENTIFIER_NODE_CHECK (NODE)-common.static_flag) ² 在IDENTIFIER_NODE节点中非零值表示该字串作为参数调用了函数assemble_name。 Ø CLEANUP_EH_ONLY ((NODE)-common.static_flag) ² 在TARGET_EXPRWITH_CLEANUP_EXPRCLEANUP_STMT节点或块block的清理cleanup链的节点中非零值表示相关的清理只在异常抛出时执行而在正常退出时不需要执行。 Ø TREE_OVERFLOW ((NODE)-common.public_flag) ² 在INTEGER_CSTREAL_CSTCOMPLEX_CST或VECTOR_CST节点中非零值表示在常量折叠中发生溢出并且这部分的警告还没有发出。TREE_OVERFLOW同时意味着TREE_CONSTANT_OVERFLOW但反之不成立。 Ø TREE_PUBLIC((NODE)-common.public_flag) ² 在VAR_DECL或FUNCTION_DECL节点中非零值表示该名字可从模块module外访问。在IDENTIFIER_NODE节点中非零值表示在域内inner scope已有该名字所代表的能从模块module外访问的外部链接性的声明external declaration。 Ø TREE_PRIVATE ((NODE)-common.private_flag) ² 在C里在类中使用。 Ø CALL_EXPR_HAS_RETURN_SLOT_ADDR ((NODE)-common.private_flag) ² 在CALL_EXPR节点中非零值表示返回值的地址是参数链的一部分。 Ø TREE_PROTECTED ((NODE)-common.protected_flag) ² 在C中用于类。在BLOCK节点中这是个BLOCK_HANDLER_BLOCK节点。 Ø CALL_FROM_THUNK_P ((NODE)-common.protected_flag) ² 在CALL_EXPR节点中非零值表示该函数调用是从thunk到thunk目标函数的跳转。 Ø TREE_SIDE_EFFECTS ((NODE)-common.side_effects_flag) ² 在所有的表达式中非零值表示该表达式含有副作用side effects或者对其每次求值reevaluation of the whole expression将产生不同的值。如果其子表达式是一个函数调用、对一个volatile变量的引用或含有副作用这个标识符将被设置。 ² In a *_DECL, this is set only if the declaration said volatile. Ø TREE_THIS_VOLATILE ((NODE)-common.volatile_flag) ² 非零值表示该表达式在C的含义下in the C sense是volatile它的地址应该是类型volatile WHATEVER *。换而言之所声明的项item是volatile修饰的volatile qualified。该标识符用于*_DECL和*_REF节点中。 ² 在*_TYPE节点中非零值表示其对应的类型为volatile修饰的volatile-qualified。不过如果节点代表一个类型应该使用TYPE_VOLATILE而不是这个宏。因为以后这2个宏会访问不同的位现在是相同的见下一条。如果这个位被设上TREE_SIDE_EFFECTS也应该同时被设上。 Ø TYPE_VOLATILE (TYPE_CHECK (NODE)-common.volatile_flag) ² 非零值表示该类型作为整体是volatile的。 Ø TREE_READONLY ((NODE)-common.readonly_flag) ² 在VAR_DECLPARM_DECL或者FIELD_DECL或者所有*_REF类型节点中非零值表示它不能作为左值the lhs of an assignment。 ² 在*_TYPE节点中非零值表示其对应的类型为常量const-qualified类型但是如果节点表示类型则应该使用宏TYPE_READONLY。 Ø TYPE_READONLY (TYPE_CHECK (NODE)-common.readonly_flag) ² 非零值表示该节点代表的类型为常量类型。 Ø TREE_CONSTANT ((NODE)-common.constant_flag) ² 非零值表示表达式的值为常量。在所有的*_CST节点中设置。也可能出现在数学表达式中ADDR_EXPR或者CONSTRUCTOR节点中如果它们的值为常量。 Ø TREE_UNSIGNED ((NODE)-common.unsigned_flag) ² 在INTEGER_TYPE或者ENUMERAL_TYPE节点中非零值表示其对应类型为无符号类型。在FIELD_DECL节点中则表示为无符号域unsigned bit field。 Ø TREE_ASM_WRITTEN ((NODE)-common.asm_written_flag) ² 在VAR_DECL节点中表示汇编代码也被写入。 ² 在FUNCTION_DECL节点中表示该函数已被编译。在内联函数中这个位很有意义因为内联函数可能不需要独立编译(作为函数)。 ² 在RECORD_TYPEUNION_TYPEQUAL_UNION_TYPE或者ENUMERAL_TYPE节点中表示有关类型的sdb调试信息已经写入。 ² 在BLOCK节点中非零值表示在这个分段block内reorder_block节点已发现。 Ø TREE_USED ((NODE)-common.used_flag) ² 在*_DECL节点中表示在其作用域中相应的名字被引用is used in its scope。 ² 在表达式节点中表示如果其值未被使用不发出警告。 ² 在IDENTIFIER_NODE节点中表示同名的外部声明已被引用was used。 Ø TREE_NOTHROW ((NODE)-common.nothrow_flag) ² 在FUNCTION_DECL节点中表示该函数不会抛出异常。在CALL_EXPR节点中则表示该次调用不会抛出异常。 Ø TYPE_ALIGN_OK (TYPE_CHECK (NODE)-common.nothrow_flag) ² 用在表示类型的节点中非零值表示所有该类型的对象由语言或前端保证被正确地对齐。因此我们可以得知该类型的MEM节点RTL节点的对齐量不少于该类型的对齐量尽管它可能看起来不是这样。在面向对象语言中这种情况发生在一个要求更多对齐量量的变种类型的对象上in object-oriented languages where a tag field may show this is an object of a more-aligned variant of the more generic type。 Ø TREE_DEPRECATED ((NODE)-common.deprecated_flag) ² 在IDENTIFIER_NODE节点中该名字的使用是被__attribute__((deprecated))所不推荐的。 列表 1tree_common中的标识符 1.1.1. 树节点的定义 以下是中间树的节点的定义。 45 typedef union tree_node *tree; in coretypes.h 1772 union tree_node GTY ((ptr_alias (union lang_tree_node), intree.h 1773 desc (tree_node_structure (%h)))) 1774 { 1775 struct tree_common GTY ((tag (TS_COMMON))) common; 1776 struct tree_int_cst GTY ((tag (TS_INT_CST))) int_cst; 1777 struct tree_real_cst GTY ((tag (TS_REAL_CST))) real_cst; 1778 struct tree_vector GTY ((tag (TS_VECTOR))) vector; 1779 struct tree_string GTY ((tag (TS_STRING))) string; 1780 struct tree_complex GTY ((tag (TS_COMPLEX))) complex; 1781 struct tree_identifier GTY ((tag (TS_IDENTIFIER))) identifier; 1782 struct tree_decl GTY ((tag (TS_DECL))) decl; 1783 struct tree_type GTY ((tag (TS_TYPE))) type; 1784 struct tree_list GTY ((tag (TS_LIST))) list; 1785 struct tree_vec GTY ((tag (TS_VEC))) vec; 1786 struct tree_exp GTY ((tag (TS_EXP))) exp; 1787 struct tree_block GTY ((tag (TS_BLOCK))) block; 1788 }; 显然这个节点需要定义为union。注意第1772行的ptr_alias它告诉GTY GCC的废料回收系统garbage collection service我们暂时不理会它指向tree_node的指针实际上指向lang_tree_node这个节点由前端通过tree_node追加额外的特定于语言的成员来定义因此它可被视为tree_node。在C前端中lang_tree_node有如下定义 472 union lang_tree_node GTY((desc (cp_tree_node_structure (%h)), incp-tree.h 473 chain_next ((union lang_tree_node *)TREE_CHAIN (%h.generic)))) 474 { 475 union tree_node GTY ((tag (TS_CP_GENERIC), 476 desc (tree_node_structure (%h)))) generic; 477 struct template_parm_index_s GTY ((tag (TS_CP_TPI))) tpi; 478 struct ptrmem_cst GTY ((tag (TS_CP_PTRMEM))) ptrmem; 479 struct tree_overload GTY ((tag (TS_CP_OVERLOAD))) overload; 480 struct tree_baselink GTY ((tag (TS_CP_BASELINK))) baselink; 481 struct tree_wrapper GTY ((tag (TS_CP_WRAPPER))) wrapper; 482 struct tree_default_arg GTY ((tag (TS_CP_DEFAULT_ARG))) default_arg; 483 struct lang_identifier GTY ((tag (TS_CP_IDENTIFIER))) identifier; 484 };