新闻中心

EEPW首页 > 探索 GCC 前端的内部结构(二)

探索 GCC 前端的内部结构(二)

——
作者:时间:2007-04-17来源:嵌入开发网收藏
Treelang 的代码框架

读者朋友们在阅读这一部分代码分析的时候,手边最好能准备上一份 GCC 3.3 的源代码。这个源代码可以从 GCC 的站点 http://gcc.gnu.org上获得。本文作者力图做到把整个情况像说故事一样娓娓道来,但是读者朋友们如果在适当的时候能够查阅一下源代码,可能更能把问题了解的清楚透彻。 

这个 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 sample {
        int 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_INITIALIZER {   
        MEMBER_INT,            
        MEMBER_STR,            
        MEMBER_FUN,            
}

 


按照上面这样的办法申明了这些关于这个 struct sample 的辅助宏定义以后,在每次要初始化一个 struct sample 数据结构的时候,只需要按照如下操作即可。除了要稍微多打一些字以外,这个方法的方便程度和以上两种方法是差不多的。 



#undef MEMBER_INT
#define MEMBER_INT 12
#undef MEMBER_STR
#define MEMBER_STR "trtr"
#undef MEMBER_FUN
#define MEMBER_FUN real_fun
struct sample inst_def = SAMPLE_INITIALIZER;

 


这样就也可以像 C99 标准或者 GCC 的扩展一样,按照成员变量的名称来初始化一个 struct 类型的数据结构了。不过话又说回来,在我们一般的软件项目中,还是应该沿着 C99 标准这个 C 语言的发展方向来走的。 

:::::注释结束 

接下来的线路很清楚,就是一个一个的分析这些个回调函数啦。 


评论


相关推荐

技术专区

关闭