编译器家族GCC内部探密探索GCC前端的.doc_第1页
编译器家族GCC内部探密探索GCC前端的.doc_第2页
编译器家族GCC内部探密探索GCC前端的.doc_第3页
编译器家族GCC内部探密探索GCC前端的.doc_第4页
编译器家族GCC内部探密探索GCC前端的.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

编译器家族 GCC 内部探密 探索 GCC 前端的GNU编译器家族GCC内部探密:探索GCC前端的内部结构2010年06月03日星期四下午09:28GNU编译器家族GCC内部探密:探索GCC前端的内部结构screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/未显示需要javascript的文档选项screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/赵蔚),Linux和自由软件技术独立顾问2003年7月10日我们在本文中说明GCC源码包中的例子编程语言Treelang的实现细节。主要目的在于辑此说明所谓GCC前端的编程方法。限于篇幅,本文只能略略讲一下GCC前端的内部结构的框架部分。本文中所涉及到的源程序均位于GCC源码包中的gcc/目录和gcc/treelang/目录下。本文的代码分析基于GCC CVS中的最新(2003年六月)的开发版本。GNU编译器家族GCC介绍作为自由软件的旗舰项目,Richard Stallman在十多年前刚开始写作GCC的时候,还只是把它当作仅仅一个C程序语言的编译器;GCC的意思也只是GNU CCompiler而已。经过了这么多年的发展,GCC已经不仅仅能支持C语言;它现在还支持Ada语言,C+语言,Java语言,Objective C语言,Pascal语言,COBOL语言,以及支持函数式编程和逻辑编程的Mercury语言,等等。而GCC也不再单只是GNU C语言编译器的意思了,而是变成了GNU Compiler Collection也即是GNU编译器家族的意思了。另一方面,说到GCC对于各种硬件平台的支持,概括起来就是一句话:无所不在。几乎所有有点实际用途的硬件平台,甚至包括有些不那么有实际用途的硬件平台,比如Don Knuth设计的MMIX计算机,GCC都提供了完善的支持。我们在这篇文章中要弄清楚的就是GCC是如何做到能够支持这么多种程序语言的。所谓的GCC的程序语言前端到底是怎么回事。如果我们要设计实现自己的编程语言的话,应该从何入手。回答这些问题的第一步,就是分析清楚GCC源码包中,为了说明GCC的程序语言前端的编写方法,而写作的Treelang编程语言在GCC中的实现细节。如果把我们自己的程序语言的实现建立于GCC之上,也立刻使得我们的程序语言的实现版本可以运行在几乎所有有用的硬件平台之上。这对于程序语言的作者来说,也是一个确实的有极大诱惑力的好处。screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/回页首关于代码分析在这一小节里面我们着重说明两个问题:第一、为什么要阅读源代码;第二、代码分析应该怎么写。阅读源代码对提高自己的编程水平是非常有帮助的。这个帮助至少体现在两个方面。第一个方面是学会大型软件项目设计的模式。这样的模式是真实可靠的第一手资料,这样学来的模式要比从书本上,用日常语言陈述的模式,更能深入到你的脑海中去。而且它的真实性和可靠性都是有保证的。并且这样的模式还非常的具体。我曾经看到计算机系的同学推荐去读亚历山大的建筑学方面的经典著作;个人以为这是走的太远了。与其去读建筑学的书,不如去分析一下成功的自由软件项目的源代码。具体的用代码说明的模式,无论如何要比虚无飘渺的美学概念,或者模棱两可的工程纪律,都要更加容易学习吧?阅读源代码的第二个好处,是增加自己的自信心。就象学习英语,要和别人谈话,要看看别人的文章,不能只是看教科书上的简单的例子。教科书上的例子限于篇幅,不可能做到像真实、完整的英文小说那样,把一个完整的设计呈现在你的面前。只有当你硬着头皮,抛开字典,把一本英文小说生生啃下来之后,你才能有把握说:我的确能做到。类似的,只有当我们看过大型软件项目的源代码,作过修改,摸爬滚打之后,我们才能有把握的说:我也能写出来。上面说了阅读源代码至少有这么两个好处。那么在阅读源代码的时候,我们必然要做代码分析笔记。这个代码分析笔记如何写,这就是我们关心的一个问题了。在这里,我提出一些我自己的也许不太成熟的看法,也请读者朋友们不吝指教。我总觉得,与其作一行一行的代码注释,说明每一行代码的作用;不如设计一个故事,把代码的框架说清楚。这也是我前面提到的,所谓模式一说。因为阅读源代码,最关键的是要了解大型软件项目设计的模式,而不是要把每一次读者分析每一行代码细节的乐趣从此剥夺掉。另一方面,代码分析的写作风格,可以是参考手册似的;也可以是航海日志似的。我个人觉得参考手册似的代码分析是比较乏味的,读起来乏味,写起来也不免乏味,虽然它可能更有用。对于一个急着要快点结束加班工作的软件工程师来说,也许参考手册更加实用。但是对于一个想要了解这一份成功的软件背后的工作奥秘的探索者来说,一个航海日志似的代码分析,也许读起来更有味道,更能让一个程序员在键盘与屏幕之间,体会到那地理大发现的激动与乐趣。本文后面的代码分析,就是希望能写成这样的风格。可是作者笔力有限,如有不足之处,还请读者朋友们不吝指教。screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/回页首Treelang的代码框架读者朋友们在阅读这一部分代码分析的时候,手边最好能准备上一份GCC 3.3的源代码。这个源代码可以从GCC的站点上获得。本文作者力图做到把整个情况像说故事一样娓娓道来,但是读者朋友们如果在适当的时候能够查阅一下源代码,可能更能把问题了解的清楚透彻。这个treelang语言的实现,主要有两个C语言文件,把整个代码框架分成两个部分。第一部分以tree1.c为主,带上parse.y这个YACC源程序,组成了和GCC前端的接口;第二部分以treetree.c为主,组成了和GCC后端的接口。这里首先说明一下tree1.c这个文件。它和上级目录中的GCC框架文件toplev.c交互作用,实现tree1这个执行程序的主体部分。这个tree1就相当于GCC的C语言前端中的cc1执行程序,该程序是C语言编译器前端的主体。我们首先试图说明从toplev.c到tree1.c的路径。这样我们就注意到toplev.c中这个引人注目的lang_hooks变量。当然,接下来就注意到在toplev.c同一目录下的langhooks.c这个文件。我们希望在其中发现一点有趣的东西。这一共是三个文件:langhooks.ch和langhooks-def.h其中在langhooks.h中定义了一堆各式各样的struct lang_hooks_for_xxx结构,以及最后还有一个struct lang_hooks结构把前面的那些for_xxx的结构都总括了起来。这每一个结构都是若干个至少看上去像是回调函数的函数指针。看来这就是我们要寻找的东西。那么大概就是这样了,编译器前端向GCC主体部分注册自己的lang_hooks来完成各样的任务。接下来一个自然的问题就是这个注册是如何进行的;另外一个问题就是要对这些回调函数指针进行分析了。这个langhooks.h文件中关于struct lang_hooks结构字段的注释很详细,这里我们暂时先跳过去。等到treelang中具体的注册回调函数出现的时候,我们根据需要再做仔细说明。在langhooks-def.h文件中定义了一些这个struct lang_hooks结构的默认值。现在我们进入treelang目录下的treetree.c这个文件。来察看一下在treelang中对struct lang_hooks这个结构的初始化过程。这个过程不是按照我们通常所熟悉的C语言的C99标准或者是GCC扩展语法来进行的。而是采用了大量的#define和#undef并结合上层目录中的langhooks-def.h来进行。细想一下,这是理所当然的事情,因为这是在编译C语言编译器本身嘛。当然就不好用到C语言的新的东西或者是自己做的扩展的东西。注释开始:我们以初始化如下定义的struct sample结构为例。struct sampleint member_int;char*member_str;void(*member_fun)(void);在C99中,初始化一个struct结构数据,使用下面这样的语法。struct sample inst_c99=.member_int=78,.member_str=iloveqhq,.member_fun=real_fun,;在C99标准出现之前,GCC定义了自己的扩展,下面的例子就是按照这个GCC对C语言的扩展,来初始化一个struct结构数据。struct sample inst_gcc=member_int:76,member_str:zhaoway,member_fun:real_fun,;在GCC的源代码中没有使用上面的两种办法,而是大量使用了宏定义。这个办法首先要申明一份辅助的宏定义。这些个辅助的宏定义,在一个软件项目里面,针对一个struct结构,只需要一份即可。#define MEMBER_INT 0#define MEMBER_STR#define MEMBER_FUN NULL#define SAMPLE_INITIALIZERMEMBER_INT,MEMBER_STR,MEMBER_FUN,按照上面这样的办法申明了这些关于这个struct sample的辅助宏定义以后,在每次要初始化一个struct sample数据结构的时候,只需要按照如下操作即可。除了要稍微多打一些字以外,这个方法的方便程度和以上两种方法是差不多的。#undef MEMBER_INT#define MEMBER_INT 12#undef MEMBER_STR#define MEMBER_STRtrtr#undef MEMBER_FUN#define MEMBER_FUN real_fun struct sample inst_def=SAMPLE_INITIALIZER;这样就也可以像C99标准或者GCC的扩展一样,按照成员变量的名称来初始化一个struct类型的数据结构了。不过话又说回来,在我们一般的软件项目中,还是应该沿着C99标准这个C语言的发展方向来走的。:注释结束接下来的线路很清楚,就是一个一个的分析这些个回调函数啦。screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onclick=if(!this.resized)return true;elsewindow.open(onmousewheel=return imgzoom(this);alt=/screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.alt=Click here to open new windownCTRL+Mouse wheel to zoom in/out;onmouseover=if(this.width screen.width*0.7)this.resized=true;this.width=screen.width*0.7;this.style.cursor=hand

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论