追溯llvm的历史要追溯到10年前(2014),起初它着眼于编译器的后端算法和中间表述(今天依然是llvm的重点),当时其余部分还要依赖gcc。其中最重要的是它的IR,llvm在整个编译的过程当中有不少种中间表示,如AST(C/C++转换成IR的过程)、DAG(IR转换成特定机器的汇编语言的过程)、某种特定的中间表示(汇编器和连接器使用)等其余中间表示依然起到很重要的做用,可是,真正让llvm不同凡响的仍是它的IR,甚至llvm这个名字的由来还和IR有很大的关系。html
首先看IR(intermediate representation)的特色:前端
其存在方式有两种,一种在内存中,一种是在磁盘上,SSA可以更方便的优化,再加上保存在磁盘上的这种编码方式可以达到几近全时优化的效果,这也是llvm的做者在最先介绍llvm的论文中提出的目标,可是IR的描述能力毕竟有限,要想实现全时优化,就要求对诸如程序分布这种行为作出描述,这也意味着实现了此功能的llvm要像jvm那样可以成为一个运行平台,相似jvm的名字,llvm这个名字就是这么来的。java
随着llvm项目的发展,其设计目标已经重点放在了经过磁盘上的IR操做实现连接时优化等功能,而不是全时优化,最终只保留了llvm这个名字,可是llvm已经成了一个强大的编译器框架,而不是一个相似jvm的那样的平台。算法
说到这,说一下我的理解吧,感受是llvm起初提出了一个比较精妙的编码表示方案,有利于一些编译优化,进而发现能够憧憬的的目标——全时优化,可是又发现实现全时优化比较困难,在llvm的mail list上有人专门就此发起了一个很详细的讨论,详细阐述了llvm不能像java那样成为一个platform或者vm的缘由,重点仍是要作编译器。后端
无论怎样,llvm这么名字仍是保留下来了,如今若是有人跟你提起“LLVM”,多是指如下内容:架构
LLVM框架主要包括三个方面的核心内容:框架
LLVM的编译流程如图:
每一个步骤中间交互有两种介质:1) in-memory; 2) by-file,前者变现出来经过一些高层的工具如clang,自动进行指定的动做;后者能够每一步每一步分离开来,经过一个个独立的工具完成。frontend
如前文所述,可使用driver来自动完成一系列动做,对于代码hello.c:jvm
#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
直接编译:工具
clang hello.c -o hello
便可经过clang来执行一系列编译器的功能,直接生成可执行文件。
-###参数能够查看clang调用了哪些工具:
clang -### hello.c -o hello