详解三大编译器:gcc、llvm 和 clang

编译器一般构成传统的编译器通常分为三个部分 , 前端(frontEnd) , 优化器(Optimizer)和后端(backEnd) 。 在编译过程中 , 前端主要负责词法和语法分析 , 将源代码转化为抽象语法树;优化器则是在前端的基础上 , 对得到的中间代码进行优化 , 使代码更加高效;后端则是将已经优化的中间代码转化为针对各自平台的机器代码 。
GCCGCC(GNU Compiler Collection , GNU编译器套装) , 是一套由 GNU 开发的编程语言编译器 。 GCC 原名为 GNU C 语言编译器 , 因为它原本只能处理 C语言 。 GCC 快速演进 , 变得可处理 C++、Fortran、Pascal、Objective-C、Java, 以及 Ada 等他语言 。
详解三大编译器:gcc、llvm 和 clang文章插图
LLVMLLVM (Low Level Virtual Machine , 底层虚拟机) 提供了与编译器相关的支持 , 能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成 。 简而言之 , 可以作为多种编译器的后台来使用 。
苹果公司一直使用 GCC 作为官方的编译器 。 GCC 作为一款开源的编译器 , 一直做得不错 , 但 Apple 对编译工具会提出更高的要求 。 原因主要有以下两点:
其一 , 是 Apple 对 Objective-C 语言(包括后来对C语言)新增很多特性 , 但 GCC 开发者并不买Apple的账——不给实现 , 因此索性后来两者分成两条分支分别开发 , 这也造成 Apple 的编译器版本远落后于 GCC 的官方版本 。 其二 , GCC 的代码耦合度太高 , 很难独立 , 而且越是后期的版本 , 代码质量越差 , 但 Apple 想做的很多功能(比如更好的 IDE 支持) , 需要模块化的方式来调用 GCC , 但 GCC一直不给做 。
编译器大神 Chris Lattner 横空出世2000年 , 本科毕业的 Chris Lattner 像中国多数大学生一样 , 按部就班地考了GRE , 最终前往UIUC(伊利诺伊大学厄巴纳香槟分校) , 开始了艰苦读计算机硕士和博士的生涯 。 在这阶段 , 他不仅周游美国各大景点 , 更是翻烂了《Compilers: Principles, Techniques, and Tools》 , 成了GPA满分(4.0) 牛人 , 并不断地研究探索关于编译器的未知领域 , 发表了一篇又一篇的论文 ,。 他在硕士毕业论文里提出了一套完整的在编译时、链接时、运行时甚至是在闲置时优化程序的编译思想 , 直接奠定了LLVM 的基础 。 LLVM 在他念博士时更加成熟 , 使用GCC 作为前端来对用户程序进行语义分析产生IF(Intermidiate Format) , 然后 LLVM 使用分析结果完成代码优化和生成 。 这项研究让他在2005年毕业时就成为了业界小有名气的编译器专家 , 他也因此早早地被Apple 盯上 , 最终成为其编译器项目的骨干 。
刚进入 Apple , Chris Lattner 就大展身手:首先在 OpenGL 小组做代码优化 , 把 LLVM运行时的编译架在 OpenGL 栈上 , 这样OpenGL 栈能够产出更高效率的图形代码 。 如果显卡足够高级 , 这些代码会直接扔入GPU 执行 。 但对于一些不支持全部OpenGL特性的显卡(比如当时的Intel GMA卡) , LLVM 则能够把这些指令优化成高效的 CPU指令 , 使程序依然能够正常运行 。 这个强大的 OpenGL 实现被用在了后来发布的Mac OS X 10.5上 。 同时 , LLVM的链接优化被直接加入到 Apple 的代码链接器上 , 而 LLVM-GCC也被同步到使用 GCC4.0 代码 。
详解三大编译器:gcc、llvm 和 clang文章插图
LLVM2.0 - ClangApple 吸收Chris Lattner的目的要比改进GCC代码更具野心 -- Apple 打算从零开始写 C、C++、Objective-C语言的前端 Clang , 完全替代掉GCC 。
Clang 是LLVM的前端 , 可以用来编译C , C++ , ObjectiveC等语言 。 Clang则是以LLVM为后端的一款高效易用 , 并且与IDE 结合很好的编译前端 。
Clang 只支持C , C++和Objective-C三种语言 。 2007年开始开发 , C编译器最早完成 , 而由于Objective-C 只是C语言的一个简单扩展 , 相对简单 , 很多情况下甚至可以等价地改写为C语言对Objective-C运行库的函数调用 , 因此在2009年时 , 已经完全可以用于生产环境 。 C++ 在后来也得到了支持 。
详解三大编译器:gcc、llvm 和 clang文章插图
GCC 和 Clang 对比

  • Clang特性
速度快:通过编译 OS X 上几乎包含了所有 C 头文件的 carbon.h 的测试 , 包括预处理 (Preprocess) , 语法 (lex) , 解析 (parse) , 语义分析 (Semantic Analysis) , 抽象语法树生成 (Abstract Syntax Tree) 的时间 , Clang 比 GCC 快2倍多 。
内存占用小:Clang 内存占用是源码的 130% , Apple GCC 则超过 10 倍 。
诊断信息可读性强:其中错误的语法不但有源码提示 , 还会在错误的调用和相关上下文的下方有~~~~~和^的提示 , 相比之下 GCC 的提示很天书 。