下一页 上一页 目录

4. GCC 前端

GCC (GNU 编译器套件) 本质上分为前端和后端。这种划分的主要原因是提供代码可重用性。众所周知,GCC 支持多种语言。这包括 C、C++、Java 等。

如果您想在 GCC 中引入一种新语言,您可以做到。您唯一需要做的就是为该语言创建一个新的前端。

后端对于所有语言都是相同的。不同的前端用于不同的语言。因此,在 GCC 中创建一个编译器意味着创建一个新的前端。让我们尝试实验性地在 GCC 中引入一种新语言。

在引入一种语言之前,我们必须牢记某些事项。首先,我们正在向一个庞大的代码添加一个片段。为了完美的工作,我们必须添加一些例程,声明一些变量等等,这些可能是其他代码段所需要的。其次,我们产生的某些错误可能会使后端进入不一致的状态。关于错误的信息将很少提供给我们。因此,我们必须一遍又一遍地检查我们的代码,并了解哪里出了问题。有时,这只能通过试错法来完成。

4.1 树和 rtl

让我对树结构和 rtl 做一个大致的介绍。根据我的经验,开发新的小型前端的人员不需要对树结构和 rtl 有深入的了解。但是您应该对这些有一个大致的了解。

树是 gcc 前端的中心数据结构。它非常适合编译器开发。一个树节点能够容纳整数、实数、复数、字符串等。实际上,树是一种指针类型。但是它指向的对象可能会有所不同。如果我们只是以树的整数节点为例,它是一个结构,包含一个整数值、一些标志和一些 rtl 的空间(这些标志是所有节点通用的)。有很多标志。其中一些标志指示节点是否是只读的,是否是无符号类型等等。关于树的完整信息可以从文件 tree.c、tree.h 和 tree.def 中获得。但是为了我们的需求,GCC 提供了大量的函数和宏,这有助于我们操作树。在我们的程序中,我们不会直接处理树。相反,我们使用函数调用。

RTL 代表寄存器传输语言。它是 GCC 处理的中间代码。我们正在构建的每个树结构都必须更改为 rtl,以便后端可以完美地使用它。我并没有试图以任何方式解释 rtl。建议感兴趣的读者参阅 GCC 手册。与树一样,GCC 为我们提供了许多函数来从树生成 rtl 代码。因此,在我们的编译器中,我们尝试构建树并将程序的每一行转换为 rtl。大多数 rtl 例程都将树作为参数并发出 rtl 语句。

所以我希望您对我们要做的事情有一个模糊的概念。树的构建和 rtl 的生成可以被认为是两个不同的阶段。但它们是混合在一起的,不能单独考虑。前端还需要完成一个阶段。它是初步优化阶段。它包括常量折叠、算术简化等技术,我们可以在前端处理。但我完全忽略了那个阶段,以简化我们的前端。我们的优化完全依赖于后端。我也假设您是完美的程序员。这是为了避免来自前端的错误例程。所有步骤都旨在尽可能简化代码。

从现在开始,我们的编译器只有三个阶段 - 词法、语法和中间代码生成。其余的是后端的头痛事。


下一页 上一页 目录