GCC源码分析(二)——前端

  从这一篇开始,我们将从源代码的角度来分析GCC如何完成对C语言源文件的处理。GCC的内部构架在GCC Internals(搜“gccint.pdf”,或者见[1])里已经讲述得很详细了,但是如果你只看了gccint就来看代码,还是觉得一头雾水,无法下手,因为你很难把gccint所讲的概念同gcc代码里真实的数据结构联系起来。那么这也是我把我这半年的分析经理写下来的原因,大家可以参照gccint来看。那么gccint中已经详细讲过的概念,在这里就一笔带过,这里只研究GCC的源码。

一、源码组织

  GCC的源代码文件非常多,总数大约有好几万。但是很多都是testsuite和lib。首先我们除去所有的testsuite目录,然后lib打头的目录也可以基本上不看,那是各程序语言的gcc版标准库和专为某种语言的编译而设计的库。我们只分析C语言的话,只用看其中的libcpp,它包含了C/C++的词法分析和预处理。剩下的GCC源代码大多集中在config、gcc两个目录下。

  config目录是Makefile为各跨平台编译准备的配置目录。

  gcc目录下除去gcc/config目录外的其他文件是各个语言的编译器前端源文件,一般放在各自语言命名的目录下,例如cp(C++)、java、fortran等。唯一例外的是C语言,它的前端源文件同GCC的通用文件(包括中间表示、中间优化等)一起,散放在gcc目录下。

  gcc/config目录是gcc在各种硬件或操作系统平台下的后端源文件,负责把GCC生成的中间表示转换为各平台相关的机器码、字节码或其他目标语言。

  那我们可以从gcc的源代码组织上大致看出gcc之所以能支持众多前端和后端的原因,它将各种语言的源文件按照各自的方法分析完之后,表示为由GENERIC、GIMPLE、RTL组成的统一的中间结构,再由各种后端将统一的结构转换为各自平台对应的目标语言。

二、词法分析

  词法分析,通俗讲,就是给源文件断词。我们将源文件看作一个字符流,并交由词法分析器进行断词,词法分析器必须能够输出一个一个的词,也叫做记号(token),每个记号至少有三个属性:

1.值:即断出的那一段字符串

2.类型:关键字、标识符、文字常量、符号等

3.位置:这个记号在当前文件的第几行,用于报错。

  在《编译原理》里面,词法分析是和NFA、DFA、正则表达式联系起来的,他们属于III型语言。根据词法定义,我们手头已经有很多工具可以实现词法分析器的自动构造,这些自动构造的代码无一例外的使用了DFA的概念,即构造出来的词法分析器一定是一个DFA,里面包含了初始状态、终结状态和状态的转移,而这些状态都是自动构造中抽象出来的符号或者数字,一般人很难看出这些状态在词法定义中的位置。所以这也是自动构造的缺点——贪图构造的方便,一定带来修改的成本。

  而GCC的词法分析是手工构造的,实现在libcpp/lex.c文件中,其中最重要的那个函数是_cpp_lex_direct,他反应了GCC词法分析器的核心结构。代码很长,我只贴一点片段。

  switch (c)
    {
    case ' ': case '\t': case '\f': case '\v': case '\0':
      result->flags |= PREV_WHITE;
      skip_whitespace (pfile, c);
      goto skipped_white;

    case '\n':
      if (buffer->cur < buffer->rlimit)
	CPP_INCREMENT_LINE (pfile, 0);
      buffer->need_line = true;
      goto fresh_line;

    case '0': case '1'
  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值