传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd)。在编译过程中:
前端主要负责词法和语法分析,将源代码转化为抽象语法树;
优化器则是在前端的基础上,对得到的中间代码进行优化,使代码更加高效;
后端则是将已经优化的中间代码转化为针对各自平台的机器代码。Clang则是以LLVM为后端的一款高效易用,并且与IDE结合很好的编译前端。
先来看看 C 标准是怎么规定一个 C Compiler 在翻译过程中应该完成哪些步骤的(主要参考自ISO/IEC 9899(俗称C99)标准 "5.1.1.2 Translation phases") 第一阶段:对字符集进行转换;三并字(Trigraph sequences)被替换为单个字符。
第二阶段:行末的反斜杠 \ 被删除,实现行连接。
第三阶段:整个源文件被识别为一系列的预处理记号(preprocessing tokens)和空白字符(含注释);一块注释替换为一个空格;换行符被保留。
第四阶段:预处理指令被执行,宏调用展开,_Pragma 一元运算符表达式执行;#include 预处理指令所涉及的文件,也被按照当前所描述的阶段一至阶段四进行处理,且处理过程是递归的;以上完毕后,预处理指令被删除。
第五阶段:字符常量(character constants)和字符串字面量(string literals)中的字符集成员和转义序列被转换。
第六阶段:连接毗邻的字符串字面量记号。
第七阶段:预处理记号(preprocessing tokens)转换为一般记号(token);并对转换后的一般记号进行语法及语义上的分析,然后转换为翻译单元(translation unit)。
第八阶段:解析对外部对象和函数的引用;链接库组件(library components),获得可执行的程序映像文件(program image)。 上面八个阶段中,前六个阶段至第七阶段的前半部分,大体上对应了大多数程序员熟知的“预处理过程”,而第七个阶段的后半部分则是“编译过程”(实则涵盖了文法分析、语义分析、等许多细分阶段),最后的第八阶段则是“链接过程”。