最近在Mac OS X Mountain Lion下用Xcode进行开发,发如今编译选项里有以下所示的这两种编译器:一个是Apple LLVM compiler 4.2,另一个是LLVM GCC 4.2。html
近几年一直听人说LLVM比GCC好,可是我一直没有时间研究这两者的差异。由此问题出发,我又给本身抛出了不少疑问:前端
接下来让咱们一块儿补补历史课。算法
Unix诞生以后,不少公司都开发了本身的Unix系统而且使用了本身专门的编译器。这样就致使在不一样的Unix系统上,想编译C语言代码就须要使用不一样的命令。因而POSIX标准Commands and Utilities中就规定了将CC做为不一样编译器的统一命令接口,而且也规定了CC命令须要提供哪些必须的参数。后端
随着后续ISO C标准的肯定,POSIX标准又规定分别将C89、C99做为ISO C的接口,而CC则继续做为非标准C的接口。但实际上后续大多数C语言编译器都实现了ISO C标准,因此POSIX标准规定后续应将CC这一历史遗留的命令取消。架构
随着开源运动的兴起,自由软件基金会开发了本身的开源免费的C语言编译器GNU C Compiler,简称GCC。GCC中提供了C Preprocessor这个C语言的预处理器,简称CPP。后来GCC又加入了对C++等其它语言的支持,因此他的名字也改成GNU Compiler Collection。G++则是专门用来处理C++语言的。在GNU的官方手册中,有一个章节叫作G++ and GCC介绍了这两者的区别。G++是GCC编译器集合的一个前端。关于前端、后端的概念下面有更详细的介绍。而GPP呢,这个名字比较特殊,若是你用的是Linux系统,可能并无这个命令。可是在某些特殊的系统下,例如DOS,是没法建立G++这样带有特殊符号的文件名的。因此按照DJGPP编译器的作法,GPP其实就是G++。post
回顾GCC的历史,虽然它取得了巨大的成功,但开发GCC的初衷是提供一款免费的开源的编译器,仅此而已。可后来随着GCC支持了愈来愈多的语言,GCC架构的问题也逐渐暴露出来。但GCC到底有什么问题呢?咱们一块儿看看这篇文章:The Architecture of Open Source Applications: LLVM。LLVM的优势也正是GCC的缺点。性能
传统编译器的工做原理基本上都是三段式的,能够分为前端(Frontend)、优化器(Optimizer)、后端(Backend)。前端负责解析源代码,检查语法错误,并将其翻译为抽象的语法树(Abstract Syntax Tree)。优化器对这一中间代码进行优化,试图使代码更高效。后端则负责将优化器优化后的中间代码转换为目标机器的代码,这一过程后端会最大化的利用目标机器的特殊指令,以提升代码的性能。优化
事实上,不光静态语言如此,动态语言也符合上面这个模型,例如Java。Java Virtual Machine也利用上面这个模型,将Java代码翻译为Java bytecode。翻译
这一模型的好处是,当咱们要支持多种语言时,只须要添加多个前端就能够了。当须要支持多种目标机器时,只须要添加多个后端就能够了。对于中间的优化器,咱们可使用通用的中间代码。code
这种三段式的结构还有一个好处,开发前端的人只须要知道如何将源代码转换为优化器可以理解的中间代码就能够了,他不须要知道优化器的工做原理,也不须要了解目标机器的知识。这大大下降了编译器的开发难度,使更多的开发人员能够参与进来。
虽然这种三段式的编译器有不少有点,而且被写到了教科书上,可是在实际中这一结构却历来没有被完美实现过。作的比较好的应该属Java和.NET虚拟机。虚拟机能够将目标语言翻译为bytecode,因此理论上讲咱们能够将任何语言翻译为bytecode,而后输入虚拟机中运行。可是这一动态语言的模型并不太适合C语言,因此硬将C语言翻译为bytecode并实现垃圾回收机制的效率是很是低的。
GCC也将三段式作的比较好,而且实现了不少前端,支持了不少语言。可是上述这些编译器的致命缺陷是,他们是一个完整的可执行文件,没有给其它语言的开发者提供代码重用的接口。即便GCC是开源的,可是源代码重用的难度也比较大。
LLVM最初是Low Level Virtual Machine的缩写,定位是一个虚拟机,可是是比较底层的虚拟机。它的出现正是为了解决编译器代码重用的问题,LLVM一上来就站在比较高的角度,制定了LLVM IR这一中间代码表示语言。LLVM IR充分考虑了各类应用场景,例如在IDE中调用LLVM进行实时的代码语法检查,对静态语言、动态语言的编译、优化等。
从上面这个图中咱们发现LLVM与GCC在三段式架构上并无本质区别。LLVM与其它编译器最大的差异是,它不只仅是Compiler Collection,也是Libraries Collection。举个例子,假如说我要写一个XYZ语言的优化器,我本身实现了PassXYZ算法,用以处理XYZ语言与其它语言差异最大的地方。而LLVM优化器提供的PassA和PassB算法则提供了XYZ语言与其它语言共性的优化算法。那么我能够选择XYZ优化器在连接的时候把LLVM提供的算法连接进来。LLVM不只仅是编译器,也是一个SDK。
如今咱们能够回答本文最前面我遇到的那个问题了。Apple LLVM compiler 4.2是一个真正的LLVM编译器,前端使用的是Clang,基于最新的LLVM 3.2编译的。LLVM GCC 4.2编译器的核心仍然是LLVM,可是前端使用的是GCC 4.2编译器。从LLVM的下载页面能够看出,LLVM从1.0到2.5使用的都是GCC做为前端,直到2.6开始才提供了Clang前端。
http://www.cnblogs.com/zuopeng/p/4141467.html