这篇文章会讲解 Visual C++(www.cppentry.com) 编译器的数据流――首先会以一段C++(www.cppentry.com)源程序开始,以对应的二进制程序结束。这篇文章很简单――一切才刚刚开始。
首先我们来看看从命令行开始,编译一个单一文件的程序 APP.cpp 时会发生什么(如果你想从Vistual Studio 来启动编译,下图还必须包含一些高层软件,然而,结束时,它们会给出一些很特别的命令,我后面会讲到)。
假设我们刚才键入了: CL/02 App.cpp
CL代表‘编译和链接’,02告诉编译器优化速度―-生成一些执行速度尽可能快的机器码。该命令启动一个进程去运行CL.EXE程序―- 一个调用了其他软件的驱动器:连接到一起时,他们会处理APP.cpp里的文本,最终生产一个二进制文件,成为App.exe。 执行时,该二进制文件会执行我们源代码里的操作。

我们浏览下上个图表,看看发生了什么。
CL.EXE 解析我们的命令行,并检查它是否有意义。然后调用位于C1XX.DLL的 C++(www.cppentry.com)‘前端’(“CXX”是指C++(www.cppentry.com),因为以前‘+’不能用于文件名。)前端是用于理解C++(www.cppentry.com)语言的一条链。它扫描,解析并将APP.cpp文件转换为 一颗等价树,通过五个临时文件传递给下一个组件。这五个文件被称为CIL,意为C中间语言。不要把它跟托管语言,例如C#生产的中间代码混淆。有时,也成 为MSIL,但是不幸的是,在ECMA-335标准里,它被命名为CIL。
接下来,CL.EXE会调用 所谓的‘后端’,位于C2.DLL。我们把后端成为‘UTC’,意思为‘通用元组编译器’,但是这个名字并没有出现在Visual Studio所包含的的任何二进制文件里。后端先将信息从前端转换为元组― 一个二进制流的指令。显示出来会看到它们看上去就像是一种高级汇编语言。感觉 上很高级:
操作是通用的,例如,一个分支(LE)指令,以及它最终如何被翻译成64位的机器码CMP指令。
操作数是象征性的,例如,一个由编译器生成的临时变量t66和一个运行时保存其值得64位寄存器eax。
因为我们要求编译器优化速度,通过/02开关,优化部分后端,分析元组并将其转化为另一种形式,使其运行得更快,但是语义上来讲,却是等价的,和原来的元组产生的同样的结果。完成这步后,元组就会被传给后端的CodeGen部分,最终会决定二进制码的产生。
CodeGen模块会在磁盘上生成APP.obj文件,最后,链接器会利用该文件,并分析所有的引用库,生成最终的二进制文件App.exe。