LLVM编译器
LLVM介绍
- LLVM是一个跨平台的编译器基础设施,它不是一个单一的编译器,而是一系列工具和库的集合,其提供了丰富的数据结构和中间表示层,是实现编译原理的最佳框架。
- LLVM的架构和GCC编译器的架构一样,都是前端、中端、后端三层架构,但是LLVM的编译器的三层架构之间是相互独立的,而不是互相关联的。这就大大减少了编译器的开发工作。具体的LLVM三层架构如下图所示:
- LLVM前端:LLVM前端的编译器,一般是由语言的开发者或者开发团队进行编写的,而不是LLVM自带的,就好比
Clang就是配套LLVM的C语言编译器。这些前端的编译器,主要就是将高级语言编译成LLVM IR,这个中间语言。 - LLVM中端:从LLVM中端开始才是LLVM的一些工具集,并且LLVM中端的主要作用就是将
LLVM IR进行优化,使得后端编译和执行的时候变得更高效。 - LLVM后端:LLVM后端的只要作用就是将
LLVM IR,编译成不同架构的机器语言。后端的编译器也是LLVM的工具集。
- LLVM前端:LLVM前端的编译器,一般是由语言的开发者或者开发团队进行编写的,而不是LLVM自带的,就好比

- 补充1:常见的LLVM前端编译器
| 语言类型 | 适配LLVM的编译器 |
|---|---|
| C/C++/Object-C/Object-C++ | Clang |
| Fortran | llvm-gcc Frotran |
| Rust | rustc |
| Swift | Swift Compiler |
-
补充2:加入
LLVM IR使得编译器编写的工作量减少很多。假设有M种语言,N种硬件:- 如果按照
gcc三层架构比较紧凑的编译器设计,那么一共就需要开发M×N个编译器。(不讨论交叉编译的情况) - 如果按照
LLVM三层架构相互独立的编译器设计,那么一共就需要开发M+N个编译器,其中M个是开发的是编译器的前端数量,N个是开发编译器的后端数量。
- 如果按照
-
补充3:LLVM版本介绍与对应版本的一些比较大的改动对比。
- 先贴两个链接,一个就是LLVM的组织官网,另一个是LLVM的github仓库。要初步了解LLVM版本号,其实翻阅一下GitHub仓库就可以了。
- LLVM版本号大致说明如下:
- 在GitHub的
Relaease页面中最早的只有7.1.0版本, - 翻阅LLVM组织网站会发现,最早的
1.0版本是在2003年10月24日发布的。 - 截至目前
2026年9月20日,LLVM的版本号已经更新到了23.1.1版本了。
- 在GitHub的
- LLVM在版本更新中比较重要的几个版本更新阶段,如下图所示:
| 版本范围 | 重大更新内容 |
|---|---|
| LLVM2.0版本 | 引入了bitcode format |
| LLVM3.0版本 | 进行了tpye system rewrite |
| LLVM4.0版本 | 版本号体系发生变化 |
| LLVM9.0到LLVM13.0 | 现代LLVM逐渐成熟 |
| LLVM15.0版本之后 | Opaque Pointer默认启用 |
| LLVM17.0版本之后 | Typed Pointer正式消失 |
LLVM环境搭建
- 通过对LLVM的初步了解,以及对LLVM版本的更新内容的一些了解,现在来搭建LLVM的环境。这里推荐搭建
LLVM 17.0以及之后的版本,因为该版本以及后续版本的LLVM IR中的Typed Pointer不会再出现。在LLVM IR中举个例子:LLVM 17.0版本之前,这样的IR语法是被支持的:i32* %1。LLVM 17.0版本之后,上面的IR语法统一替换成:ptr %1。- 其实也就是不显示标明具体的指针指针类型。
Linux下LLVM环境安装
- 本人只在Linux下安装LLVM,安装过程如下。
- 首先,先使用一下命令,更新一下软件包:
1 | apt update |
- 接着使用
apt search命令搜索LLVM的软件包,发现软件包里面最高只有到llvm 15版本的软件包:
1 | apt search llvm |

- 那就直接从
github上,下载已经编译号的LLVM最新版本
1 | wget https://github.com/llvm/llvm-project/releases/download/llvmorg-23.1.1/LLVM-23.1.1-Linux-X64.tar.xz |
LLVM IR
- 本人使用
Claude Code配合教师skills,它了解了本人的实际情况后,推荐我从LLVM IR开始学习。 - 中间表示码是一种抽象的机器指令,它不针对具体的硬件,而是一种通用的指令集。它是一种中间表达,可以被进一步编译为目标代码。
LLVM IR是一种中间语言表示,作为编译器前端和后端的分水岭,LLVM编译器的前端Clang负责产生IR,而其LLVM后端负责消费IR。IR介于高级语言与汇编语言之间(更偏向汇编语言一些),发明IR是为了统一来自不同源码语言,去往不同目标硬件的一层抽象层。优点如下:- 第一个优点是:便于前端统一实现,
Clang这样的前端只需要生成抽象的数学运算,控制流这些IR预先定义号的指令就可以了,不用去专门为每个硬件设计一套生成汇编的引擎。 - 第二个优点是:
LLVM IR采用了对优化更友好的SSA格式,而不是糟糕的寄存器格式,大大方便了优化,等送到后端的末尾才开始将IR翻译为汇编代码,最终变成可执行的机器码。
- 第一个优点是:便于前端统一实现,
- 在正式了解
LLVM IR之前,先来了解一下要使用到的关于LLVM中的组件和工具。Clang:C/C++的前端编译器llc:LLVM静态编译器llvm-as:LLVM IR汇编器llvm-dis:LLVM IR反汇编器opt:LLVM中的LLVM IR优化器
LLVM IR文件
-
先来看看
LLVM实体文件具体是怎么样的,以及文件里面具体的内容。 -
LLVM IR有多种表现形式:- 内存中的
LLVM IR:内存中的IR是一组由C++对象构成的IR对象图,位于clang和libcLLVM.so进程的内存中,都是一个个C++类,通过指针相互连接。由于内存中LLVM IR对象存在虚表指针,以及其复杂的树状或图状数结构,无法直接存入磁盘以及人无法阅读,所以提供了下面两种磁盘中的存储形式。 - 磁盘中的
LLVM IR汇编:该形式通常是以文件.ll形式存储的,以人类可读的文本形式存储在磁盘中,方便人类观察、修改和调试。 - 磁盘中的
LLVM IR字节码:该形式通常是以文件.bc形式存储的,本质上和LLVM IR汇编相同,只是以更高效的二进制字节存储。虽然人类看不懂,但是节约磁盘空间,以及方便程序快速解析。
- 内存中的
-
接下来我们就具体来查看一下这三种形式,下面有一个
C语言的函数代码:
1 | int add(int a, int b) { |
- 使用
clang前端将该.c文件编译成两种不同形式的LLVM IR文件:
1 | # 编译成LLVM IR汇编 |


- 使用
LLVM工具集中的汇编器llvm-as和LLVM工具集中的反汇编器llvm-dis可以使.ll和.bc这两个形式的文件进行互相转换。
1 | # .bc文件反汇编成.ll文件 |


当需要长期储存 IR 的中间结果时会用到 IR 字节码,当需要人类观察分析中间结果时就需要 IR 汇编。
LLVM IR特点
LLVM IR的四层结构:模块、函数、基本块、指令。- 整个LLVM文件的内容会被视为一个LLVM模块模块是
LLVM IR顶层数据结构。 - 每个模块包含一系列函数,每个函数由一系列基本块组成。模块还包含用于支持该模型的外围实体,如全局变量、目标数据布局、外部函数原型以及数据结构声明。
- 整个LLVM文件的内容会被视为一个LLVM模块模块是
LLVM IR具有无限寄存器:
+
LLVM IR类型
LLVM IR指令
内存指令
控制流指令
终结指令
补充
LLVM项目的起源
LLVM项目总览
- 在LLVM项目的GitHub仓库中,其实有很多个子项目,我们在补充这里逐一介绍一下。直接从LLVM对应的GitHub仓库中拉取项目。仓库链接如下:https://github.com/llvm/llvm-project.git
1 | git clone https://github.com/llvm/llvm-project.git |
- 接着在终端中使用命令,将该项目的文件以目录树的形式在终端中输出出来。
1 | tree -L 1 |
- 会输出如下树状形式的文件:
- 我们主要学习:这些文件都是LLVM的子项目,其中我们主要学习的是
llvm文件夹,他是LLVM的本体。llvm文件夹不仅包含了LLVM库,也包含一些处理LLVM IR和字节码的实用工具。 clang文件夹:这个子项目就是大名鼎鼎的Clang编译器,他也是基于LLVM本体实现的,本身只是个前端,并不做优化和后端汇编的生成。clang-tools-extra:这个子项目是clangd、clang-tidy、clang-format等C/C++代码质量工具,可以选择不构建。cmake文件夹:该文件夹并不是子项目,而是装着和LLVM相关的一些CMake脚本文件。compiler-rt:是AddressSantizer(内存溢出检测工具)、MSAN(内存泄漏检测)、TSAN(线程安全检测)、UBSAN(未定义行为检测)等工具的实现。flang文件夹:是LLVM的Fortan前端,编程界的活化石。libc文件夹:是Clang官配的C标准库libcxx文件夹:是Clang官配的C++标准库lldb文件夹:是LLVM官方的调试器,对标GCC的gdb调试器,VScode的调试默认就是基于lldblibclc文件夹:是LLVM对OpenCL的实现mlir文件夹:是LLVM对MLIR的编译器实现(MLIR是一种为机器学习定制,允许用户自定义新的IR节点,例如矩阵乘法等高阶操作,方便特定硬件识别奥并优化成自研硬件专门的矩阵乘法指令)openmp:是LLVM对OpenMP的实现,一种用于傻瓜式CPU单机并行的框架。pstl:是LLVM对C++17Parallel STL的实现。
- 我们主要学习:这些文件都是LLVM的子项目,其中我们主要学习的是
1 | myheart@aaa /m/e/c/llvm-project-main> tree -L 1 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 iyheart的博客!

