翻译自:http://clang.llvm.org/features.html#performance
这篇文章详细地描述了<code>Clang</code>的功能和目标,并提供了更广泛的解释。这些功能如下:
~快速编译和低内存使用
~表现良好的诊断机制
~兼容<code>GCC</code>
实用工具和应用:
~基础架构模块库
~可满足多样的客户需求
~允许集成到各种IDE中
~使用<code>LLVM'BSD'</code>协议
内部设计与实现:
~一个现实世界生产质量的编译器
~一个简单可移植的代码库
~一个为C语言、Objective-C、C++、Objective-C++设计的通用的语法解析器
~与C/C++/Objective-C及它们的衍生语言具有高度一致性
终端用户功能
快速编译和低内存使用
我们在<code>clang</code>上的工作主要关注使得它快速、轻量化、易扩展。<code>clang</code>的基础架构模块库使得它在时间和堆栈每层的介绍成本,以及传输大量执行分析的选择。许多详细基准可以在网上找到。
编译时间性能是非常重要的,但是当将<code>clang</code>作为一个<code>API</code>使用时内存使用经常是更加重要的部分:代码使用更少的内存,更多的代码可以同一时间塞进内存中(例如,对整个程序分析工具是很有用的)。
此外,为了在成批处理方式上正面对抗<code>GCC</code>时更有效率,<code>clang</code>构建了基础架构模块库,这使得它相对容易适配,并在其中构建新工具。这意味着它总有可能在很多方面提供开箱即用的思路和改善汇编的新颖技术。
表现良好的诊断机制
此外,为了快速和功能化,我们的目标是使得<code>clang</code>极度用户友好。就命令行编译器运行来说,它基本说穿了就是使得由编译器生成的诊断机制(错误和警告信息)尽可能的有用。这有几种我们可以处理的方式,但是最重要的是准确地描述程序中的错误,高亮相关信息使得容易立马理解,描述措辞尽可能清晰。
下面是一个简单的例子,说明了典型的<code>GCC</code>和<code>clang</code>诊断机制之间的不同:
<pre>
clang -fsyntax-only t.c
t.c:7:39: error: invalid operands to binary expression ('int' and 'struct A')
return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);
~~~~~~~~~~~~~~ ^ ~~~~~
</pre>
通过<code>clang</code>的错误信息可以发现甚至不需要看源代码去理解为什么错误:因为<code>clang</code>打印了插入符号,这样就可以知道究竟解释的是哪个加号。距离信息高亮了加号左边和右边,这使得编译器要表述的立马明显,这是对解决优先问题和其他情况最有用的。
<code>clang</code>诊断机制很优良并且有很多功能。更多信息和例子可以查阅《表现良好的诊断机制》文章。
兼容<code>GCC</code>
<code>GCC</code>是目前实际上标准开源编译器,并且通常编译巨大容量代码。<code>GCC</code>支持巨大数量的延伸和特性(许多还是未文档化的),大量代码和头文件依靠这些特性才能编译。
然而对它好的是可能有能力忽略这些延伸和集中对字符实现语言标准,语言学集中支持<code>GCC</code>延伸性可以看到更大有用性。很多使用者想他们的代码编译,他们不关心去争论它是不是卖弄学问的<code>C99</code>。
如上所述,所有延伸性都被如此明确意识到,并标记为延伸诊断机制。这样就可以映射警告、错误还是忽略。
实用工具和应用
基础架构模块库
<code>clang</code>的主要设计概念是基础架构模块库的使用。在这个设计中,大量前端部分可以清晰地分为独立库,它们可以根据不同的需要和使用混合在一起。此外,基础库方法鼓励好的交互,并且使得新开发者更容易参与进来(因为他们仅仅需要理解大图上的一小块)。
<pre>
“世界需要更好的编译器工具,工具作为库构建。这个设计点允许工具在新的和新奇的方式重用。然而,建立作为库的工具是不够的:它们必须有清晰的尽可能相互分离的API,可以很容易被修改/扩展。这需要清晰的分层,合适的设计,并保持独立于任何特定客户端的库。”
</pre>
目前,<code>clang</code>被分成如下库和工具:
~<code>libsupport</code>-来自<code>LLVM</code>的基本支持库。
~<code>libsystem</code>-来自<code>LLVM</code>的系统抽象库。
~<code>libbasic</code>-为输入源文件的诊断机制,源代码定位,源代码缓存抽象,系统文件缓存。
~<code>libast</code>-提供展示<code>C AST</code>,<code>C</code>类型系统,内联函数和大量分析和控制<code>AST</code>(访问者,漂亮打印者诸如此类)帮助者。
~<code>liblex</code>-<code>Lexing</code>和预处理,识别哈希表,编译指示处理,令牌和宏扩展。
~<code>libparse</code>-分析。这个库调用了由客户端提供的设计粗粒度<code>‘Actions’</code>(例如<code>libsema</code>构建了<code>AST</code>),但是不知道任何关于<code>AST</code>或者客户端明确的数据结构。
~<code>libsema</code>-语义分析。它提供了一系列为程序构建标准AST的语法行为。
~<code>libcodegen</code>-为<code>LLVM</code>中间语言降低<code>AST</code>,目的是为了优化器和代码生成器。
~<code>librewrite</code>-编辑文档缓存(对代码重写转换相当重要,例如重构)。
~<code>libanalysis</code>-支持静态分析。
~<code>clang</code>-驱动程序,在很多层次的客户端库。
作为基于库设计能力的一个例子……如果构建一个预处理器,可以使用基本<code>Lexer</code>库。如果想要一个索引,你会使用前两并添加解析器库和一些操作的索引。如果想要一个重构,静态分析,或源代码编译工具,你需要加入<code>AST</code>构建和语义分析器的库。
关于更多各种<code>clang</code>库的底层实现细节的信息,请参见clang内部手册。
可满足多样的客户需求
<code>clang</code>设计和构建了许多如何使用它的宏伟规划。驱动力是日常使用的<code>C</code>和<code>C++</code>的实际情况和由于缺乏良好的工具导致的痛苦。事实是,<code>C</code>和<code>C++</code>工具的生态系统已经明显受到难以解析和代表这些语言源代码的限制,我们的目标是在<code>clang</code>纠正这些问题。
这个问题的目标是不同的客户有非常不同的需求。考虑代码生成器,例如:一个简单的前端代码生成器解析要分析代码有效性和在一些传递给一个优化器或后端中间形式上释放代码。因为有效性分析和代码生成在很大程度上是匆忙完成的,没有硬性要求前端真正构建一个完整的适合所有表达式和语句的<code>AST</code>代码。<code>TCC</code>和<code>GCC</code>编译器的例子可以构建没有实际的<code>AST</code>(前一种例子中)或建立一个精简化的<code>AST</code>(在后一种情况下),因为它们主要集中在代码生成。
在范围的另一方面,一些客户端(如重构)需要非常详细关于原始的源代码的信息,想要一个完整描述的<code>AST</code>。重构要宏展开的信息,每一个父表达<code> ‘(((x)))’</code> 与<code>‘X’</code>的位置,全方位信息,甚至更多。此外,重构要贯穿整个程序,以确保它是否安全转换。为了使这个效率和正确获得这个,需要大量明确的工程和算法工作,但是在一个简单的静态编译器中根本是不必要。
<code>clang</code>方法的优点是不限制如何使用。特别是,它可能使用clang的预处理器和解析器构建一个非常快速,轻量级的匆忙的代码生成器(类似于<code>TCC</code>),压根没有建立一个<code>AST</code>。作为一个中间步骤,<code>clang</code>支持使用当前的<code>AST</code>生成器和语义分析和释放代码生成之后每个函数的<code>AST</code>的代码生成客户端。最后,<code>clang</code>提供了构建和保持完全成熟的<code>AST</code>,甚至支持写到磁盘。
用简洁明了的<code>API</code>设计的库允许在客户端中确定这些高层次的政策定义,而不是迫使“一个真正的方式”实施这些库中任何一个。很难使得这个正确,我们不总是第一次能正确得到它,但当意识到犯了一个错误时可以解决任何问题。
允许集成到各种<code>IDE</code>中
集成开发环境(<code>IDE</code>)是集中各种开发难题的好方法,旨在使<code>clang</code>在这样环境下运行好。一个<code>IDE</code>的主要优势是它们通常有贯穿整个项目的能见度和长期存活过程,而独立编译工具通常调用的每个项目中的文件,那个有限制的范围。
这种差异有很多含义,但重要的是解决效率和缓存:在一个项目的不同文件间共享地址空间,这意味着可以使用智能缓存和其他技术大量减少分析/编译时间。
<code>IDE</code>和批处理编译器的更大区别是,它们往往对前端有非常不同的需求:它们依赖于高性能以便提供了一个“敏捷”经验,从而真正想要像“增量编译”,“模糊分析”等技术。最后,<code>IDE</code>往往比代码生成器有更多不同的需求,通常所需信息是仅生成代码的前端可以扔掉。<code>clang</code>是专门设计和构建用于捕捉这个信息的。
使用<code>LLVM'BSD'</code>协议
我们积极准备将<code>clang</code>(这个整体包含了<code>LLVM</code>)用于商业项目,不仅作为一个独立的编译器,还可以作为嵌入在一个专有的应用程序的库。<code>BSD</code>许可证是允许这个最简单方法。这个许可证鼓励贡献者拿出源码,并开发它。可以确信的是如果不想永远保持一个叉(复杂合并是耗时和昂贵的)这些个人和组织将有助于他们的工作。此外,这些天没有人靠编译器赚钱,但许多人都需要它们实现更大的目标:每个人一起工作是有道理的。
关于<code>LLVM</code> /<code>clang</code>许可的更多信息,请参见LLVM许可描述。
内部设计与实现
一个现实世界生产质量的编译器
<code>clang</code>是由经验丰富的编译器开发者设计和构建的,他们对现有的开源编译器的越来越问题沮丧了。<code>clang</code>是为提供新一代<code>C</code>/<code>C++</code>/<code>Objective-C</code>开发工具的基础上经过认真和深思熟虑的设计和构,并为其生产质量准备的。
成为具有生产质量的编译器意味着许多东西:意味着高性能,是可靠的和(相对)无缺陷,意味着最终取决于广泛程度的是否使用。虽然我们仍然在早期的发展阶段,但是坚信,这将成为一个现实。
一个简单可移植的代码库
我们目标是使得对编译器有基本了解和有<code>C</code>/<code>C++</code>/<code>objc</code>语言知识的人理解和扩展<code>clang</code>源代码变得可能。我们决定的绝大部分是使<code>AST</code>尽可能贴近反映语言:你有友好的<code>if</code>语句,<code>for</code>语句,括号表达、结构、组件等等,这些都代表了一个简单的和明确的方式。
除了上面的简单设计,我们的工作还要使源代码能方便提交,包括对适当语言标准的引用,并设计简单代码。除此之外,<code>clang</code>提供一组<code>AST</code>垃圾回收,打印和可视化工具。这样就可以很容易处理代码,并看到如何表示。
一个为C语言、Objective-C、C++、Objective-C++设计的通用的语法解析器
<code>clang</code>是“<code>C</code>语言家族的前端”,这意味着我们打算支持<code>C</code>家族中最受欢迎的成员。我们相信,这类语言的正确分析技术是一个手动建立的递归下降解析器。因为它是纯<code>C++</code>代码,递归下降使得新手更容易理解代码,它还很容易支持<code>ad-hoc</code>的规则和其他需要<code>C</code>/<code>C++</code>的奇怪黑客。使得它直接实现良好诊断和错误恢复。
我们相信在一个统一的解析器中实现<code>C</code>/<code>C++</code>/<code>objc</code>会使得最终的结果比维护一个必须需要<code>bugfixed</code>的单独<code>C</code>和<code>C++</code>分析器更容易维护和设计,并保持相互独立。
与C/C++/Objective-C及它们的衍生语言具有高度一致性
当你开始使用一种语言的时候,你会发现语言运行方式和大多数人理解是有很大的差距的。这种差距是一个正常的程序员和一个(可怕的区别?超自然?)“语言的律师”,谁知道语言的底细,并轻松获得<code>standardese</code>。
在实践中,保持一致的语言,意味着最终目标是支持完整语言,包括黑暗灰尘的角落(如三字母,预处理器的奥秘,<code>C99 VLA</code>等等)。我们支持扩展超出标准的正式允许,努力显式调用此守则并发出警告说它(这是默认情况下禁用,但可以被映射到任何警告或错误),让您在“严格”的模式,如果你希望使用<code>clang</code>。
我们还打算支持这些语言的“方言”,比如<code>C89</code>,<code>K&R C</code>,<code>C++ '03</code>,<code>Objective-C 2</code>等等。
本文转载请注明原作者呆萌院长,如果你对这篇文章有更好的见解可以通过微信联系我。利益相关:本篇文章所有涉及到的软件均为笔者日常所用工具,无任何广告费用。