LLVM

LLVM Logo

简述

LLVM

一个开源编译器架构,目前Xcode采用的就是LLVM架构。

Clang

由苹果赞助支持开发的LLVM的编译器前端,目前支持C,C++,Object-C和Object-C++.相对于GCC,Clang快,占用内存小,易于IDE集成,与GCC兼容,诊断可读性强和易拓展等。

GCC

GNU的编译器套装,原本只处理C语言,后来拓展可处理Fortran、Pascal、Objective-C、Java、Ada,Go等。许多操作系统,包括许多类Unix系统,如Linux及BSD家族都采用GCC作为标准编译器。苹果计算机预装的Mac OS X操作系统也采用这个编译器。

GNU

GNU是一个自由的操作系统,但其具有完备功能的内核尚未被开发成功。GNU的内核,称为Hurd,其发展尚未成熟。在实际使用上,多半使用Linux内核、FreeBSD等替代方案,作为系统核心,其中主要的操作系统是Linux的发行版。

在Xcode上使用GCC

Xcode在C和C++上是支持使用GCC的,如下:

具体参数的使用请参考:stackoverflow:Xcode上的GNU GCC

更多

概念

LLVM

全名:
Low Level Virtual Machine 直译:底层虚拟机
/loʊ ˈlɛvəl ˈvɜrʧuəl məˈʃin/

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Despite its name, LLVM has little to do with traditional virtual machines. The name “LLVM” itself is not an acronym; it is the full name of the project.
- 来自LLVM官网的介绍 LLVM官网

LLVM项目是模块化和可重用的编译器和工具链技术的集合。尽管名称如此,但LLVM与传统虚拟机几乎没有关系。“LLVM”不是首字母缩略词而是项目的全名。

LLVM是一个自由软件项目,它是一种编译器基础设施,以C++写成。它是为了任意一种编程语言而写成的程序,利用虚拟技术创造出编译时期、链接时期、运行时期以及“闲置时期”的最优化。它最早以C/C++为实现对象,而目前它已支持包括ActionScript、Ada、D语言、Fortran、GLSL、Haskell、Java字节码、Objective-C、Swift、Python、Ruby、Rust、Scala以及C#等语言。
- 来自维基百科 LLVM on wiki

简单来说

LLVM是一个开源的编译器架构而不是编译器。是一套用于开发编译器、解释器等程序语言相关工具的库,主要聚焦于编译器后端功能,如代码生成、代码优化、JIT等。
编译器是Clang,GCC,ICC,VC++等。

Xcode和LLVM

Xcode3之前,用的是GCC
Xcode3,GCC仍然保留,但是也推出了LLVM,苹果推荐LLVM-GCC混合编译器,但还不是默认编译器
Xcode4,LLVM-GCC成为默认编译器,但GCC仍保留
Xcode4.2,LLVM3.0成为默认编译器,纯用GCC不复可能
Xcode4.6,LLVM升级到4.2版本
Xcode5,LLVM-GCC被遗弃,新的编译器是LLVM5.0,从GCC过渡到LLVM的时代正式完成

Clang

Clang /ˈklæŋ/ 是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。它采用了底层虚拟机(LLVM)作为其后端,而且由LLVM2.6开始,一起发布新版本。它的目标是提供一个GNU编译器套装(GCC)的替代品,支持了GNU编译器大多数的编译设置以及非官方语言的扩展。作者是克里斯·拉特纳(Chris Lattner),在苹果公司的赞助支持下进行开发,而源代码许可是使用类BSD的伊利诺伊大学厄巴纳-香槟分校开源码许可。
Clang项目包括Clang前端和Clang静态分析器等。
- 来自维基百科 Clang on wiki

GCC

GCC官网
GNU编译器套装(英语:GNU Compiler Collection,缩写为GCC),指一套编程语言编译器,以GPL及LGPL许可证所发行的自由软件,也是GNU项目的关键部分,也是GNU工具链的主要组成部分之一。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。1985年由理查德·马修·斯托曼开始发展,现在由自由软件基金会负责维护工作。

原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC在发布后很快地得到扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,Go与其他语言。

许多操作系统,包括许多类Unix系统,如Linux及BSD家族都采用GCC作为标准编译器。苹果计算机预装的Mac OS X操作系统也采用这个编译器。

GCC原本用C开发,后来因为LLVM、Clang的崛起,它更快地将开发语言转换为C++。许多C的爱好者在对C++一知半解的情况下主观认定C++的性能一定会输给C,但是Ian Lance Taylor给出了不同的意见,并表明C++不但性能不输给C,而且能设计出更好,更容易维护的程序。
- 来自维基百科 GCC on wiki

GNU

GNU官网
GNU是一个自由的操作系统,其内容软件完全以GPL方式发布。这个操作系统是GNU计划的主要目标,名称来自GNU’s Not Unix!的递归缩写,因为GNU的设计类似Unix,但它不包含具著作权的Unix代码。GNU的创始人,理查德·马修·斯托曼,将GNU视为“达成社会目的技术方法”。

作为操作系统,GNU的发展仍未完成,其中最大的问题是具有完备功能的内核尚未被开发成功。GNU的内核,称为Hurd,是自由软件基金会发展的重点,但是其发展尚未成熟。在实际使用上,多半使用Linux内核、FreeBSD等替代方案,作为系统核心,其中主要的操作系统是Linux的发行版。Linux操作系统包涵了Linux内核与其他自由软件项目中的GNU组件和软件,可以被称为GNU/Linux。
- 来自维基百科 GNU on wiki

LLDB

LLDB是一种软件调试器。它构建为一组可重用的组件,被LLVM项目的现有库广泛使用,例如Clang表达式解析器和LLVM 反汇编程序。
尽管LLDB处于早期开发阶段,但它已经足够成熟,可以支持用C,Objective-C,C ++和Swift编写的程序的基本调试。
LLDB可以在macOS,Linux,FreeBSD和Windows上运行,并支持i386,x86-64和ARM 指令集。它用作Xcode 5及更高版本的默认调试器。

GDB

GNU Debugger 顾名思义
支持编程语言有C、C++、Pascal以及FORTRAN
在许多的类UNIX操作系统上都可以使用

词法分析

lexical analysis /ˈlɛksɪkəl/
词法分析阶段是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。词法分析程序实现这个任务。词法分析程序可以使用lex等工具自动生成。

语法分析

syntactic analysis,也叫 parsing
/sɪnˈtæktɪk əˈnæləsəs/ /ˈpɑːzɪŋ/
语法分析是编译过程的一个逻辑阶段。语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述.

语法分析器

parser
通常是作为编译器或解释器的组件出现的,它的作用是进行语法检查、并构建由输入的单词组成的数据结构(一般是语法分析树、抽象语法树等层次化的数据结构)。语法分析器通常使用一个独立的词法分析器从输入字符流中分离出一个个的“单词”,并将单词流作为其输入。实际开发中,语法分析器可以手工编写,也可以使用工具(半)自动生成。

源语言&源程序

Source language&Source program
被编译程序翻译的程序称为源程序,书写该程序的语言称为源语言。

目标语言&目标程序

Object language or Target language & Object program or Target program
编译程序翻译源程序而得到的结果程序称为目标程序, 书写该程序的语言称为目标语言。

中间语言(中间表示)

Intermediate language(representation)
在进行了语法分析和语义分析阶段的工作之后,有的编译程序将源程序变成一种内部表示形式,这种内部表示形式叫做中间语言或中间表示或中间代码。所谓“中间代码”是一种结构简单、含义明确的记号系统,这种记号系统复杂性介于源程序语言和机器语言之间,容易将它翻译成目标代码。另外,还可以在中间代码一级进行与机器无关的优化。

文法

Grammars
/ˈgræməz/
文法是用于描述语言的语法结构的形式规则。

token

是一个字符串,是构成源代码的最小单位。从输入字符流中生成标记的过程叫作标记化(tokenization),在这个过程中,词法分析器还会对标记进行分类。
词法分析器通常不会关心标记之间的关系(属于语法分析的范畴),举例来说:词法分析器能够将括号识别为标记,但并不保证括号是否匹配。

抽象语法树

abstract syntax tree或者缩写为AST
/ˈæbstrækt ˈsɪnˌtæks tri/
抽象语法树,或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码。和抽象语法树相对的是具体语法树(concrete syntaxtree),通常称作分析树(parse tree)。一般的,在源代码的翻译和编译过程中,语法分析器创建出分析树。一旦AST被创建出来,在后续的处理过程中,比如语义分析阶段,会添加一些信息。

具体

CMD+B

Objective-C与swift都采用Clang作为编译器前端,编译器前端主要进行语法分析,语义分析,生成中间代码,在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。
编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化,根据不同的系统架构生成不同的机器码。
C++,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码。

在使用Xcode按下cmd+B后,会经过以下流程:

预处理(Pre-process):他的主要工作就是将宏替换,删除注释展开头文件,生成.i文件。

词法分析 (Lexical Analysis):将代码切成一个个 token,比如大小括号,等于号还有字符串等。是计算机科学中将字符序列转换为标记序列的过程。

语法分析(Semantic Analysis):验证语法是否正确,然后将所有节点组成抽象语法树 AST 。由 Clang 中 Parser 和 Sema 配合完成。

静态分析(Static Analysis):使用它来表示用于分析源代码以便自动发现错误。

中间代码生成(Code Generation):开始IR中间代码的生成了,CodeGen 会负责将语法树自顶向下遍历逐步翻译成 LLVM IR,IR 是编译过程的前端的输出后端的输入。

优化(Optimize):LLVM 会去做些优化工作,在 Xcode 的编译设置里也可以设置优化级别-01,-03,-0s,还可以写些自己的 Pass,官方有比较完整的 Pass 教程: Writing an LLVM Pass — LLVM 5 documentation 。如果开启了 bitcode 苹果会做进一步的优化,有新的后端架构还是可以用这份优化过的 bitcode 去生成。

生成目标文件(Assemble):生成Target相关Object(Mach-o) 。

链接(Link):生成 Executable 可执行文件。

关于此过程的详细测试,参考掘金

LLVM的具体操作

请参考关于LLVM,这些东西你必须知道!

基于ClangPlugin 可以用来定义一些编码规范,比如代码风格检查,命名检查等等
Pass就是LLVM系统转化和优化的工作的一个节点,可以写一个这样的节点去做一些自己的优化工作或者其它的操作,比如 a+b 改为 a-(-b)
将Pass加入PassManager管理,这样我们就可以直接通过clang的参数去加载我们的Pass了
基于Pass,我们可以编写自己的Pass去混淆代码,以增加他人反编译的难度。

所以基于LLVM可以完成:

  • 做语法树分析,实现语言转换OC转Swift、JS or 其它语言,字符串加密。
  • 编写ClangPlugin,命名规范,代码规范,扩展功能。
  • 编写Pass,代码混淆优化。

使用Clang进行开发

详细参考IBM developerWorks

Clang的特性
相比于 GCC,Clang 具有如下优点:

  • 编译速度快:在某些平台上,Clang 的编译速度显著的快过 GCC。
  • 占用内存小:Clang 生成的 AST 所占用的内存是 GCC 的五分之一左右。
  • 模块化设计:Clang 采用基于库的模块化设计,易于 IDE 集成及其他用途的重用。
  • 诊断信息可读性强:在编译过程中,Clang 创建并保留了大量详细的元数据 (metadata),有利于调试和错误报告。
  • 设计清晰简单,容易理解,易于扩展增强。与代码基础古老的 GCC 相比,学习曲线平缓。

当前 Clang 还处在不断完善过程中,相比于 GCC, Clang 在以下方面还需要加强:

  • 支持更多语言:GCC 除了支持 C/C++/Objective-C, 还支持 Fortran/Pascal/Java/Ada/Go 和其他语言。Clang 目前支持的语言有 C/C++/Objective-C/Objective-C++。
  • 支持更多平台:GCC 流行的时间比较长,已经被广泛使用,对各种平台的支持也很完备。Clang 目前支持的平台有 Linux/Windows/Mac OS。

以下是目前GCC和Clang对C++支持的情况:

更多参考C++ 编译器支持情况表

使用LLVM创建一个编译器

首先参考这篇文章来写一个helloworld
IBM developerWorks

关于LLVM IR的生成与创建
IBM developerWorks