LLVM和GCC的区别(LLVM提供了模块化的编译模块,非常有利于重用,以前的编译器都没有做到这一点)
最近在Mac OS X Mountain Lion下用Xcode进行开发,发现在编译选项里有如下所示的这两种编译器:一个是Apple LLVM compiler 4.2,另外一个是LLVM GCC 4.2。
近几年一直听人说LLVM比GCC好,但是我一直没有时间研究这二者的差别。由此问题出发,我又给自己抛出了很多疑问:
- cc, c89, c99是什么?有何区别?
- gcc, g++, cpp, gpp又是什么?
- LLVM与GCC区别大吗?
- Apple LLVM compiler 4.2和LLVM GCC 4.2有何区别?
- LLVM GCC 4.2到底是LLVM还是GCC?
接下来让我们一起补补历史课。
CC, C89, C99
Unix诞生之后,很多公司都开发了自己的Unix系统并且使用了自己专门的编译器。这样就导致在不同的Unix系统上,想编译C语言代码就需要使用不同的命令。于是POSIX标准Commands and Utilities中就规定了将CC作为不同编译器的统一命令接口,并且也规定了CC命令需要提供哪些必须的参数。
随着后续ISO C标准的确定,POSIX标准又规定分别将C89、C99作为ISO C的接口,而CC则继续作为非标准C的接口。但实际上后续大多数C语言编译器都实现了ISO C标准,所以POSIX标准规定后续应将CC这一历史遗留的命令取消。
GCC, G++, CPP, GPP
随着开源运动的兴起,自由软件基金会开发了自己的开源免费的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++。
LLVM与GCC
回顾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。
这一模型的好处是,当我们要支持多种语言时,只需要添加多个前端就可以了。当需要支持多种目标机器时,只需要添加多个后端就可以了。对于中间的优化器,我们可以使用通用的中间代码。
这种三段式的结构还有一个好处,开发前端的人只需要知道如何将源代码转换为优化器能够理解的中间代码就可以了,他不需要知道优化器的工作原理,也不需要了解目标机器的知识。这大大降低了编译器的开发难度,使更多的开发人员可以参与进来。
虽然这种三段式的编译器有很多有点,并且被写到了教科书上,但是在实际中这一结构却从来没有被完美实现过。做的比较好的应该属Java和.NET虚拟机。虚拟机可以将目标语言翻译为bytecode,所以理论上讲我们可以将任何语言翻译为bytecode,然后输入虚拟机中运行。但是这一动态语言的模型并不太适合C语言,所以硬将C语言翻译为bytecode并实现垃圾回收机制的效率是非常低的。
GCC也将三段式做的比较好,并且实现了很多前端,支持了很多语言。但是上述这些编译器的致命缺陷是,他们是一个完整的可执行文件,没有给其它语言的开发者提供代码重用的接口。即使GCC是开源的,但是源代码重用的难度也比较大。
LLVM
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 GCC 4.2
现在我们可以回答本文最前面我遇到的那个问题了。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
LLVM和GCC的区别(LLVM提供了模块化的编译模块,非常有利于重用,以前的编译器都没有做到这一点)的更多相关文章
- LLVM和GCC的区别
最近在Mac OS X Mountain Lion下用Xcode进行开发,发现在编译选项里有如下所示的这两种编译器:一个是Apple LLVM compiler 4.2,另外一个是LLVM GCC 4 ...
- linux下Clang和gcc的区别
Clang 比 GCC 编译器的优势: 编译速度更快 编译产出更小 出错提示更友 好,比如 clang 在编译过程可以直接指出相对简单的出错位置以及它 “ 认为 ” 正确的方式 . 内置有静态分析工具 ...
- [llvm] LLVM 核心类简明示例 : llvm::Value && llvm::Type && llvm::Constant
LLVM 核心类简明示例 : llvm::Value && llvm::Type && llvm::Constant llvm核心类位于 include/llvm/IR ...
- gcc,g++,extern “C” :一些编译错误的缘由
正好是我们代码中遇到的问题,之前不求甚解,只用g++编译没有错误就不管了,现在要跨平台到windows下就遇到了问题.全文转载自:http://user.qzone.qq.com/75172588/b ...
- LLVM 笔记(五)—— LLVM IR
ilocker:关注 Android 安全(新手) QQ: 2597294287 LLVM 的 IR (Intermediate Representation) 是其设计中的最重要的部分.优化器在进行 ...
- 【LLVM笔记】0x00 初识LLVM 链接类型
模块结构 LLVM程序是由若干的模块(Module)组成,每个模块中包含有一些函数.全局变量和符号表. 这些模块可能由LLVM的连接器组合在一起,组合的过程将会整合这些函数和全局变量的定义,整合他们的 ...
- [转]G++与GCC的区别
转自http://www.52pojie.cn/thread-58109-1-1.html 误区一:gcc只能编译c代码,g++只能编译c++代码两者都可以,但是请注意:1.后缀为.c的,gcc把它当 ...
- ACM提交,C++,G++,C,GCC的区别
今天做了一道水题,POJ-1004,水题一个,12个double类型的数求平均数 但是, #include <iostream> #include <cstdio> using ...
- 详解C/C++ 编译 g++ gcc 的区别
我们在编译c/c++代码的时候,有人用gcc,有人用g++,于是各种说法都来了,譬如c代码用gcc,而c++代码用g++, 或者说编译用gcc,链 接用g++,一时也不知哪个说法正确,如果再遇上个ex ...
随机推荐
- htmlunit 模拟登录 数字验证码
使用htmlunit的好处有两点,相比httpclient,htmlunit是对浏览器的模拟,比如你定位一个按钮,就可以执行click()方法,此外不需要象在httpclient中一样编写复杂的代码, ...
- JavaCPP 技术使用经验总结
本文是对 JNI 技术的一个补充方法,提出了替换 JNI.JNA 的一种开源技术.首先对 JavaCPP 技术进行简单介绍及对应于其他现有方案的介绍.对比.接下来,通过一个简单的示例让大家了解 Jav ...
- 自定义adapter 的getView方法被重复执行了n次的解决方法
1. getView执行的次数和你的getCount没有直接的关系 ,getCount和你listView里面的条目数量(行数量)有关系 ,getView方法执行次数取决于你屏幕上显示几个条目,比 ...
- git commit 报错 There was a problem with the editor 'vi'
今天提交代码git commit -a的时候出现了这个错误 上网查了一下,说是Vim的返回值出错了,出错的原因还在翻译英文, 先贴出解决方案吧 git config --global core.ed ...
- jQuery分离构造器
http://www.imooc.com/code/3401 通过new操作符构建一个对象,一般经过四步: A.创建一个新对象 B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象) ...
- python实现简易采集爬虫
#!/usr/bin/python #-*-coding:utf-8-*- # 简易采集爬虫 # 1.采集Yahoo!Answers,parseData函数修改一下,可以采集任何网站 # 2.需要sq ...
- C++ string的那些坑,C++ string功能补充(类型互转,分割,合并,瘦身) ,c++ string的内存本质(简单明了的一个测试)
1. size_type find_first_of( const basic_string &str, size_type index = 0 ); 查找在字符串中第一个与str中的某个字符 ...
- C#中将字符串转换成Md5值的方法
原文:C#中将字符串转换成Md5值的方法 版权声明:有问题可联系博主QQ:15577969,大家一起相互交流和学习. https://blog.csdn.net/qq15577969/article/ ...
- crawler_正则表达式零宽断言
在使用正则表达式时,有时我们需要捕获的内容前后必须是特定内容,但又不捕获这些特定内容的时候,零宽断言就起到作用了. (?=exp):零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp. ...
- Java之"Mozilla Rhino"引擎(二)
在Java中使用Rhino, 能让你使用类似Groovy, ECMAScript...等等之类的不同动态脚本语言, 其中值得推荐的是ECMAScript, 它是Rhino的默认实现, 同时也在JDK1 ...