【问题标题】:What jobs does a typical C++ compiler handle?典型的 C++ 编译器处理哪些工作?
【发布时间】:2015-12-05 16:53:29
【问题描述】:

在对编译器及其工作原理进行了一些研究后,我了解到该过程通常分为 4 个步骤:预处理器、编译器、汇编器和链接器。我设想这些步骤的方式是每个步骤都是它自己的单独程序。预处理程序、编译程序、汇编程序和链接程序。但是,您了解到有时创建汇编代码和生成目标文件的过程都由编译器程序处理,有时则不是。它似乎在很大程度上取决于所使用的上下文和编程语言。那么我的问题是如何分解将 C++ 源代码翻译成机器代码的典型翻译过程?

  1. 预处理器是独立于编译器的程序吗?还是该过程通常是编译器程序的一部分?
  2. 编译器通常负责什么?生成汇编代码,然后转换为机器码?
  3. 链接器是编译器完成后运行的独立程序吗?

旁注:我的问题与其他 C++ 编译器线程不同,因为我不仅要问编译器是如何工作的,还要问某些其他进程(例如链接)是否有自己的可执行程序,或者它们是否通常内置于编译器中程序。

【问题讨论】:

  • 预处理器、前端、后端(代码生成器和优化器)、链接器。今天仍然很少使用汇编程序,太慢了。实际上不再那么直截了当,编译器可以在前端停止并生成中间代码。由链接器消耗,可以启动后端实现全程序优化。
  • “今天很少使用汇编程序”很好,显然今天没有人使用 gcc。或者带有目标的 llvm,它不带有集成的汇编器。或者其他几个...
  • 请注意,该序列仅适用于一个编译/翻译单元。构建控制(例如 make)是第一步。

标签: c++ compiler-construction linker machine-translation


【解决方案1】:

所有现代编译器(至少 gcc 和 clang,但我怀疑其他编译器有很大不同)都将预处理和编译器作为一个可执行文件。这主要是因为编译器希望能够生成好的错误消息[指向正确的行和列,当涉及到宏时,可以说“从宏 FOO(x) 调用”],并了解“我们在什么文件当编译器需要查看实际的源代码而不是预处理的代码时,'re in' 会更容易。

链接器通常是一个单独的程序,而汇编器仅用于内联汇编代码[通常作为编译器的集成部分] - 否则,编译器将直接生成机器代码而不使用汇编器[至少在 LLVM 中,这是我最了解的编译器]。所以从编译器出来的是一个完整的目标文件。

如果您有正确的选项,链接器将被调用,但它是一个单独的可执行文件,它将目标文件与运行时库和“在 main”之前的开始代码(全局对象构造和类似的,如以及“准备调用 main”)。这将生成可执行文件。

使用其他选项,编译器将只生成一个目标文件,或以符号形式生成的机器代码的反汇编(-S 选项)。

编译器的后端部分负责代码生成,通常也处理优化和各种代码转换以帮助优化阶段 - 例如 Clang + LLVM 将产生“统一”循环,无论是否您使用whileforgoto 进行循环。

这有助于更高级的阶段不必识别许多不同形式的循环,并允许编译器生成“好”代码,而不管程序员如何形成循环。 [当然,如果你把它弄得足够复杂,编译器可能不会完全弄清楚你的循环是如何工作的,也不会优化得那么好,但是对于基本形式之间的直接转换,不管怎样,它都会进行相同的最终代码生成源的样子]。

【讨论】:

  • 哇,答案太棒了。正是我想要的。谢谢!
猜你喜欢
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 2017-02-25
  • 2021-12-03
  • 2021-11-14
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
相关资源
最近更新 更多