传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd)。
传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd)。在编译过程中,前端主要负责词法和语法分析,将源代码转化为抽象语法树;优化器则是在前端的基础上,对得到的中间代码进行优化,使代码更加高效;后端则是将已经优化的中间代码转化为针对各自平台的机器代码。
GCC(GNU Compiler Collection,GNU编译器套装),是一套由 GNU 开发的编程语言编译器。GCC 原名为 GNU C 语言编译器,因为它原本只能处理 C语言。GCC 快速演进,变得可处理 C++、Fortran、Pascal、Objective-C、Java, 以及 Ada 等他语言。
LLVM (Low Level Virtual Machine,底层虚拟机) 提供了与编译器相关的支持,能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。简而言之,可以作为多种编译器的后台来使用。
苹果公司一直使用 GCC 作为官方的编译器。GCC 作为一款开源的编译器,一直做得不错,但 Apple 对编译工具会提出更高的要求。原因主要有以下两点:
其一,是 Apple 对 Objective-C 语言(包括后来对C语言)新增很多特性,但 GCC 开发者并不买Apple的账——不给实现,因此索性后来两者分成两条分支分别开发,这也造成 Apple 的编译器版本远落后于 GCC 的官方版本。其二,GCC 的代码耦合度太高,很难独立,而且越是后期的版本,代码质量越差,但 Apple 想做的很多功能(比如更好的 IDE 支持),需要模块化的方式来调用 GCC,但 GCC一直不给做。
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 代码。
Apple 吸收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++ 在后来也得到了支持。
速度快:通过编译 OS X 上几乎包含了所有 C 头文件的 carbon.h 的测试,包括预处理 (Preprocess),语法 (lex),解析 (parse),语义分析 (Semantic Analysis),抽象语法树生成 (Abstract Syntax Tree) 的时间,Clang 比 GCC 快2倍多。
内存占用小:Clang 内存占用是源码的 130%,Apple GCC 则超过 10 倍。
诊断信息可读性强:其中错误的语法不但有源码提示,还会在错误的调用和相关上下文的下方有~~~~~和^的提示,相比之下 GCC 的提示很天书。
兼容性好:Clang 从一开始就被设计为一个API,允许它被源代码分析工具和 IDE 集成。GCC 被构建成一个单一的静态编译器,这使得它非常难以被作为 API 并集成到其他工具中。
Clang有静态分析,GCC没有。
Clang使用BSD许可证,GCC使用GPL许可证。
支持 JAVA/ADA/FORTRAN
GCC 支持更多平台
GCC 更流行,广泛使用,支持完备
GCC 基于 C,不需要 C++ 编译器即可编译
目前不推荐使用老的GCC4.2,因为苹果不会维持它了,而且LLVM-GCC看起来会更好。在项目中途改编译选项可是一个大变动,需要慎重。
对新的项目而言,LLVM-GCC 看起來应该是个安全的选择,苹果公司认为它够稳定够成熟,所以才把它当做Xcode 4的预设选项。而且,既然选项使用的是GCC parser,向后兼容性应该没问题。
LLVM-GCC是个安全的选项,但并不是指Clang/LLVM比较不安全,只是成熟度还沒那么高效了。
回顾GCC的历史,虽然它取得了巨大的成功,但开发GCC的初衷是提供一款免费的开源编译器,仅此而已。可后来随着GCC支持了越来越多的语言,GCC架构的问题也逐渐暴露出来。但GCC到底有什么问题呢?LLVM的优点也正是GCC的缺点。传统编译器工作的时候前端负责解析源代码,检查语法错误,并将其翻译为抽象的语法树(Abstract Syntax Tree)。优化器对这一中间代码进行优化,试图使代码更高效。后端则负责将优化器优化后的中间代码转换为目标机器的代码,这一过程后端会最大化的利用目标机器的特殊指令,以提高代码的性能。事实上,不光静态语言如此,动态语言也符合上面这个模型,例如Java。JVM也利用上面这个模型,将Java代码翻译为Java bytecode。这一模型的好处是,当我们要支持多种语言时,只需要添加多个前端就可以了。当需要支持多种目标机器时,只需要添加多个后端就可以了。对于中间的优化器,我们可以使用通用的中间代码。这种三段式的结构还有一个好处,开发前端的人只需要知道如何将源代码转换为优化器能够理解的中间代码就可以了,他不需要知道优化器的工作原理,也不需要了解目标机器的知识。这大大降低了编译器的开发难度,使更多的开发人员可以参与进来。虽然这种三段式的编译器有很多优点,并且被写到了教科书上,但是在实际中这一结构却从来没有被完美实现过。做的比较好的应该属Java和.NET虚拟机。虚拟机可以将目标语言翻译为bytecode,所以理论上讲我们可以将任何语言翻译为bytecode,然后输入虚拟机中运行。但是这一动态语言的模型并不太适合C语言,所以硬将C语言翻译为bytecode并实现垃圾回收机制的效率是非常低的。GCC也将三段式做的比较好,并且实现了很多前端,支持了很多语言。但是上述这些编译器的致命缺陷是,他们是一个完整的可执行文件,没有给其它语言的开发者提供代码重用的接口。即使GCC是开源的,但是源代码重用的难度也比较大。
LLVM最初的定位是比较底层的虚拟机。它的出现正是为了解决编译器代码重用的问题,LLVM一上来就站在比较高的角度,制定了LLVM IR这一中间代码表示语言。LLVM IR充分考虑了各种应用场景,例如在IDE中调用LLVM进行实时的代码语法检查,对静态语言、动态语言的编译、优化等。从上面这个图中我们发现LLVM与GCC在三段式架构上并没有本质区别。LLVM与其它编译器最大的差别是,它不仅仅是Compiler Collection,也是Libraries Collection。举个例子,假如说我要写一个X语言的优化器,我自己实现了PassX算法,用以处理X语言与其它语言差别最大的地方。而LLVM优化器提供的PassA和PassB算法则提供了X语言与其它语言共性的优化算法。那么我可以选择X优化器在链接的时候把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前端。
如果你下载 LLVM 的代码,那么它就是一个IR到ARM/机器码的编译器。比如bin/opt就是对IR的优化器,bin/llc就是IR->ASM的翻译,bin/llvm-mc就是汇编器。如果你再从http://llvm.org下载Clang,那么就有了C->IR的翻译以及完整的编译器Driver。GDB是GNU的调试器。只要编译器支持DWARF格式,就可以用GDB调试。
文章浏览阅读6.7k次。MATLAB自带函数实现经验模态分解MATLAB从2018a开始给出了内置函数来实现经验模式分解(EMD)与希尔伯特-黄变换(HHT),函数名分别是emd与hht,用户可以直接调用两个函数来实现经验模式分解以及与希尔伯特-黄变换。Syntax(语法)[imf,residual] = emd(X) returns intrinsic mode functions imf and residual signal residual corresponding to the empirical mode_([imf,residual,info] = emd(x,'interpolation','pchip');)报错
文章浏览阅读7.8k次。#define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \ ((PERIPH) == USART2) || \ _c语言一句话分两段写 连接符号是什么
文章浏览阅读551次。@PostMapping("/upload-file") public R<FileResponseDTO uploadImageForSummerNote(@RequestPart("file") MultipartFile file, @RequestParam("fileInfo") String fileInfo){ InputStream fileStream =file.getInputStream() if("89504E47".startsWith(fileTypePrefix_java读取bin文件 十六进制
文章浏览阅读1.3k次。前言Instant-run是Android Studio 2.0开始引入的新特性,它的作用是使开发者在开发时的改动可以很快地被应用,节省开发者的时间。当改动了代码之后,不需要进行完整的构建过程生成新的apk并且重新安装,只是把涉及到改动的部分push到设备上,某些情况下甚至都不需要重启当前Activity,马上就可以看到改动。牛逼啊,简直黑科技。hotfix(热更新)的使用场景类似instan..._instant run
文章浏览阅读721次。引言今天我们不说数组,说一说字符串的操作。PHP因为历史包袱,工具库内存在了各个时期的各种类型的 array_* 数组操作函数,和 str_* 字符串操作函数。参数位置,返回类型,函数名称等等并不相同。我们摘取一个小的需求,说一说如何连接两个字符串。学习时间原始字符串是这样的:$data1 = "the color is";$data2 = "red";想要获得下面的结果:$result = "t..._使用php写两个链接
文章浏览阅读1.9k次。http://blog.csdn.net/linuxdrivers/archive/2010/10/01/5917478.aspx我们在 浅谈Linux PCI设备驱动(一)中(以下简称 浅谈(一) )介绍了PCI的配置寄存器组,而Linux PCI初始化就是使用了这些寄存器来进行的。后面我们会举个例子来说明Linux PCI设备驱动的主要工作内容(不是全部内容),这里只做文字性的介绍而不_浅谈linux pci设备驱动
文章浏览阅读607次。1.简单查询2.聚合函数查询3.子查询4.内外连接5.三大范式6.事务7.视图8.索引9.补充内容简单查询1.查询所有字段 查询需要查的字段select * from where 2.取别名3.条件查询4.逻辑运算符 and / or / not5.去重 distinct 按字段去重查询 from 表名6.模糊查询 like %:任意个字符 _:有且仅有一个字符7.between and ._mysql left关联时候指定索引语法
文章浏览阅读367次。混合移动应用,在native中嵌入了一些html页面,这样可以将app里面的一些ui显示的图片什么的,可以快速进行更新,而不需要担心各大app商店审核的时间,也不需要用户再自行再去更新软件app,,用户只需在打开app的时候,后台就会自动更新页面,可以使app更快的响应变化,面对一些节日活动时,可以很快更新,,弊端就是,因为后台需要去占用资源更新,自然会使app使用时变得延迟高、用户交互响应慢等,所以不应在一款app内大量使用,随着移动终端的普及,手机应用越来越多,也越来越重要。_app自动化测试
文章浏览阅读425次。3.读取媒体的部分数据包以获取码流信息avformat_find_stream_info。4.2 定位文件avformat_seek_file或av_seek_frame。2.根据url打开本地文件或网络流avformat_open_input。1.分配解复用器上下文avformat_alloc_context。4.1 从文件中读取数据包av_read_frame。5.关闭解复用器avformat_close_input。4.读取码流信息:循环处理。_解复用 解封装
文章浏览阅读5.4k次,点赞2次,收藏5次。两者的区别在于如果选择insert 那么所有的字段都会添加一遍即使没有值 <insert id="insert" parameterType="com.ego.pojo.TbContentCategory" >insert into tb_content_category (id, parent_id, name,status, sort_order, is..._mybatis insert inserselective
文章浏览阅读3.4k次。Google breakpad是一个非常实用的跨平台崩溃转储和分析模块,支持Windows,Linux和Mac和Solaris多个平台。由于它本身跨平台,所以很大的减少我们在平台移植时的工作,毕竟崩溃转储,每个平台下都不同,使用起来很难统一,而Google breakpad就帮我们做到了这一点,不管是哪个平台下的崩溃,都能够进行统一的分析。现在很多工程都在使用它,比如Chrome,Firefox,..._谷歌 breakpad 能否商用
文章浏览阅读5.5k次,点赞9次,收藏29次。前言最近写项目,有一块功能需要使用双图进行联动的展示,左边折线图,鼠标移动折线图焦点,能把每个点的数据情况展示到饼图上,这里记录一下,希望对大家有帮助实现的效果:实现步骤:首先先实现折线图的部分:option = { color: ['#c6e8ad', '#00DDFF', '#37A2FF', '#FFBF00', '#f3a19e'], legend: {}, tooltip: { trigger: 'axis', showContent: _vue echarts联动