项目地址:https://github.com/llvm/llvm-project
官方网站:https://llvm.org/
当前最新稳定版:LLVM 22.1.8(2026 年 6 月发布)
许可证:Apache 2.0 License with LLVM exceptions
一、项目概述
LLVM 是一个模块化、可复用的编译器与工具链技术集合。尽管名字中带有 "VM",但它与传统的虚拟机毫无关系------"LLVM" 本身就是项目的全称,并非缩写。
项目起源于伊利诺伊大学厄巴纳-香槟分校(UIUC)的一个研究项目,目标是构建一种基于 SSA(静态单赋值)的现代编译策略,能够同时支持静态和动态编译,适用于任意编程语言。经过二十余年的发展,LLVM 已成长为一个庞大的伞形项目,包含十余个子项目,被大量商业和开源项目用于生产环境,同时也是学术研究的重镇。
LLVM 于 2012 年荣获 ACM 软件系统奖------该奖项每年仅授予全球一个软件系统,与 LLVM 同列的包括 Unix、Java、Mosaic 浏览器等。
二、整体架构:三层式编译器设计
LLVM 的核心设计哲学是模块化的三段式架构:
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
│ 前端 │ ──→ │ 优化器 (LLVM IR) │ ──→ │ 后端 (代码生成) │
│ (Frontend) │ │ (Optimizer) │ │ (CodeGen) │
└──────────────┘ └──────────────────┘ └──────────────┘
Clang/Flang LLVM Core Target Backends
Rustc/Swift Pass Framework X86/ARM/RISC-V
等语言前端 IR 优化 GPU/...
这种架构的关键在于:
- 前端将源代码解析为抽象语法树(AST),再翻译为 LLVM IR(中间表示)
- 优化器对 LLVM IR 进行一系列与源语言和目标平台无关的优化
- 后端将优化后的 IR 转换为目标平台的机器码
三阶段之间通过明确定义的接口隔离,任意一端都可以被独立替换。这意味着:
- 新语言只需实现前端,即可复用全部优化器和后端能力
- 新硬件平台只需实现后端,即可支持所有已有前端语言
- 优化器中的每个 Pass 都是独立的,可以自由组合
三、LLVM IR:一切的核心枢纽
LLVM IR(Intermediate Representation)是整个架构的枢纽。它是一种类型化、低级别、类似 RISC 的指令集,具有以下特性:
- 基于 SSA 形式:每个值只被赋值一次,简化了数据流分析和优化
- 类型安全:拥有完整的类型系统(整数、浮点、指针、向量、结构体、数组等)
- 三种表示形式 :人类可读的文本形式(
.ll文件)、二进制位码形式(.bc文件)和内存中的 C++ 对象表示
一个简单的 LLVM IR 示例------计算两个整数之和:
llvm
; 定义函数:i32 @add(i32 %a, i32 %b)
define i32 @add(i32 %a, i32 %b) {
entry:
%result = add i32 %a, %b
ret i32 %result
}
对应的 C 代码仅为 int add(int a, int b) { return a + b; },但 IR 显式表达了每个操作。
LLVM IR 的指令体系覆盖了:
| 指令类别 | 代表指令 | 说明 |
|---|---|---|
| 终结指令 | ret, br, switch, invoke |
控制流转移 |
| 二元运算 | add, sub, mul, sdiv, udiv |
整数算术 |
| 浮点运算 | fadd, fsub, fmul, fdiv |
浮点算术 |
| 位运算 | shl, lshr, ashr, and, or, xor |
位级操作 |
| 内存访问 | alloca, load, store, getelementptr |
栈分配与内存读写 |
| 类型转换 | trunc, zext, sext, bitcast, fptosi |
类型间转换 |
| 比较运算 | icmp, fcmp |
整数/浮点比较 |
| 向量运算 | extractelement, insertelement, shufflevector |
SIMD 向量操作 |
| 其他 | phi, select, call |
SSA 节点、条件选择、函数调用 |
LLVM IR 还包含丰富的内联函数(Intrinsics) ,如 llvm.memcpy、llvm.sqrt、llvm.ctlz 等,这些在 IR 层面提供了语义明确的高级操作,由后端负责映射到目标平台的最优实现。
四、代码生成流水线
后端代码生成是 LLVM 最复杂的部分之一。从 LLVM IR 到目标机器码,需要经过以下阶段:
LLVM IR
│
▼
① 指令选择 (Instruction Selection)
│ SelectionDAG / GlobalISel:将 IR 操作匹配为目标指令
▼
② 调度与形成 (Scheduling & Formation)
│ 确定指令顺序,生成 MachineInstr
▼
③ SSA 机器码优化 (SSA Machine Code Optimizations)
│ 在 SSA 形式上进行窥孔优化等
▼
④ 寄存器分配 (Register Allocation)
│ 将无限虚拟寄存器映射到有限物理寄存器,插入溢出代码
▼
⑤ 序言/尾声插入 (Prolog/Epilog Insertion)
│ 插入栈帧管理代码,实现帧指针消除等
▼
⑥ 后期机器码优化 (Late Machine Code Optimizations)
│ 溢出代码调度、最终窥孔优化
▼
⑦ 代码发射 (Code Emission)
│ 输出汇编文件或二进制目标文件
▼
机器码 / 目标文件
4.1 指令选择:SelectionDAG
SelectionDAG 是 LLVM 最成熟的指令选择框架。它将 LLVM IR 转换为有向无环图(DAG),节点是 SDNode,然后通过以下步骤处理:
- 构建初始 DAG:将 IR 翻译为目标无关的 DAG 节点
- 第一次优化:简化 DAG,识别旋转、div/rem 配对等元指令
- 类型合法化:将不支持的数据类型转换为支持的类型(如将 i1 提升为 i32)
- 第二次优化:清理类型合法化引入的冗余
- 操作合法化:将不支持的操作替换为支持的等价操作序列
- 第三次优化:清理操作合法化引入的冗余
- 指令选择:通过模式匹配将目标无关节点转换为目标指令节点
- 调度与形成 :线性化 DAG,生成
MachineInstr序列
此外,GlobalISel 是新一代指令选择框架,使用更统一的 IR(GlobaMIR),设计目标是将更多逻辑从 C++ 硬编码迁移到声明式描述。
4.2 寄存器分配
指令选择后,代码使用无限的虚拟寄存器(SSA 形式)。寄存器分配阶段将其映射到目标平台有限的物理寄存器:
- 当物理寄存器不够时,插入 溢出代码(spill code) 将值暂存到栈上
- 处理调用约定约束(如 x86 的
EAX/EDX用于除法) - SSA 形式在分配后被破坏(虚拟寄存器消失)
4.3 MC 层:目标文件级表示
MC 层是代码生成的最后一层,处理标签、节、指令等汇编级概念,不含"常量池"、"跳转表"等高级抽象。它负责:
- 将
MachineInstr转换为MCInst(更简洁的指令表示) - 输出汇编文件(
.s)或二进制目标文件(.o) - 支持多种目标文件格式:ELF、Mach-O、COFF、WASM、SPIR-V 等
五、核心子项目详解
LLVM 项目包含十余个子项目,覆盖编译器工具链的每个环节。
5.1 LLVM Core
编译器基础设施的核心,包含:
- LLVM IR 定义和操作 API
- 优化器:200+ 个优化 Pass,包括死代码消除、循环展开、向量化、内联、常量传播等
- 代码生成器:支持 X86、ARM、AArch64、RISC-V、MIPS、PowerPC、AMDGPU、NVPTX、WebAssembly、BPF 等数十种架构
5.2 Clang
"LLVM 原生"的 C/C++/Objective-C 编译器前端,设计目标:
- 极速编译:比 GCC 快数倍
- 高质量的错误诊断:精确的行列定位、修复建议、彩色输出
- 基于库的设计:Clang 的 AST 和表达式解析器可作为库复用,支撑静态分析工具
衍生工具包括:
- Clang Static Analyzer:符号执行驱动的静态分析器
- clang-tidy:基于规则的 C/C++ 代码质量检查与自动修复工具
- clang-format:代码格式化工具
5.3 Flang
现代 Fortran 编译器前端,目标是:
- 生成高性能代码
- 支持 Fortran 2023 及所有正式 Fortran 标准(回溯至 Fortran 77)
- 支持 OpenMP 并行(CPU 和 GPU)
- 包含常用 Fortran 扩展
5.4 LLDB
基于 LLVM 和 Clang 构建的原生调试器:
- 复用 Clang AST 和表达式解析器实现 C/C++/Objective-C 表达式求值
- 利用 LLVM JIT 实现动态代码注入
- 加载符号比 GDB 更快,内存效率更高
- 原生支持 macOS/Linux/Windows 等平台
5.5 libc++ / libc++ ABI
C++ 标准库的高性能实现:
- 完整支持 C++11/14/17/20/23 标准
- 由 LLVM 团队维护,被 Apple 等公司作为系统默认 C++ 标准库使用
5.6 libc
C 标准库的高性能实现,与 LLVM 深度集成:
- 针对现代 C 标准(C11/C17/C23)优化
- 利用 LLVM 编译器优化能力实现高性能
5.7 compiler-rt
编译器运行时库,提供两类功能:
- 低级运算支持 :当目标平台没有原生指令实现某 IR 操作时,提供软件实现(如
__fixunsdfdi) - 动态检测工具运行时:AddressSanitizer(内存越界检测)、ThreadSanitizer(数据竞争检测)、MemorySanitizer(未初始化内存检测)、DataFlowSanitizer(数据流跟踪)的运行时库
5.8 MLIR
多级中间表示(Multi-Level IR),是编译器基础设施领域的一项创新:
- 可扩展的 IR 生态:允许定义自定义的 Dialect(方言),每种 Dialect 有自己的操作、类型和约束
- 多层抽象:可以在不同抽象层次之间渐进式 lowering------从高层 DSL 到底层机器码,逐步细化
- 异构计算:原生支持 GPU、TPU、AI 加速器等异构硬件的编译
- 降低编译器开发成本:领域专用编译器可以复用 MLIR 的基础设施(Pass 管理、模式匹配、验证框架等)
MLIR 已被广泛用于 AI 编译器(如 TensorFlow/XLA、PyTorch/Torch-MLIR)、量子计算编译器、硬件设计等领域。
5.9 LLD
新一代链接器,设计为系统链接器的直接替代品:
- 比 GNU ld 和 gold 快数倍
- 支持 ELF、Mach-O、COFF、WASM 等格式
- 内存占用更低
5.10 BOLT
链接后优化器(Post-Link Optimizer):
- 基于运行时采样 profile 数据优化代码布局
- 通过重新排列基本块和函数布局提升指令缓存命中率
- 对大型应用可获得 2-15% 的性能提升
5.11 Polly
基于多面体模型(Polyhedral Model)的优化框架:
- 缓存局部性优化
- 自动并行化
- 自动向量化
5.12 OpenMP
为 Clang 和 Flang 提供 OpenMP 运行时支持,包括 CPU 和 GPU 的 offloading 能力。
5.13 libclc / klee
- libclc:OpenCL 标准库实现
- klee:符号虚拟机,使用定理证明器探索程序所有动态路径,自动发现 bug 并生成测试用例
六、TableGen:声明式目标描述
TableGen 是 LLVM 的代码生成工具,用于描述目标架构的信息:
- 指令定义:指令的助记符、操作数、编码、调度信息
- 寄存器定义:寄存器名、别名、寄存器类
- 调用约定:参数传递规则
- 指令映射:不同模式间的映射关系
TableGen 将 .td 描述文件转换为 C++ 代码,大幅减少手写代码量。这使得为新架构添加后端支持时,开发者只需编写声明式描述,而非大量 C++ 样板代码。
七、优化器 Pass 系统
LLVM 优化器基于 Pass 框架,每个 Pass 是一个独立的优化模块:
LLVM IR ──→ [Pass1] ──→ [Pass2] ──→ [Pass3] ──→ ... ──→ 优化后的 IR
常见的优化 Pass 包括:
- 标量优化:常量传播、死代码消除、指令合并、标量替换
- 循环优化:循环展开、循环不变量外提、循环旋转、循环向量化
- 过程间优化:函数内联、过程间常量传播、死参数消除
- 向量化:SLP(Superword-Level Parallelism)向量化、循环向量化
- Profile-Guided Optimization (PGO):基于 profile 数据的优化
- LTO(Link-Time Optimization):跨模块的全文优化
从 LLVM 15 开始,旧的 Legacy PassManager 已完全迁移到 New PassManager,它采用更现代的设计:
- Pass 按 Pass Manager 分组管理
- Pass 之间通过 Analysis Manager 共享分析结果
- 更好的缓存友好性和更低的 Pass 开销
八、生态与社区
8.1 依赖 LLVM 的语言与项目
LLVM 是众多现代编程语言的编译器后端:
- Swift:Apple 的编程语言,使用 Clang 和 LLVM
- Rust :使用 LLVM 作为默认后端(通过
rustc的 LLVM 后端和 Cranelift 后端) - Zig:使用 LLVM 后端
- Julia:JIT 编译使用 LLVM
- Crystal:使用 LLVM 后端
- Haskell:GHC 的 LLVM 后端
- Ruby:MJIT 和 YJIT 使用 LLVM 相关技术
- Python:Numba 使用 LLVM 进行 JIT 编译
8.2 商业用户
- Apple:macOS/iOS 工具链完全基于 LLVM/Clang
- Google:Android NDK、Chrome OS 使用 Clang/LLVM
- AMD:GPU 编译器基于 LLVM
- NVIDIA:CUDA 工具链使用 LLVM
- 索尼/微软:主机开发工具链基于 LLVM
8.3 社区治理
- LLVM Foundation:独立的非营利组织,负责社区治理和年度开发者大会
- LLVM Developers' Meeting:每年举办美国和欧洲两场开发者大会
- 代码审查:通过 Phabricator/GitHub Pull Requests
- Discourse 论坛 和 Discord 频道:日常交流
- 发布节奏:每年 2 个大版本(如 22.x、23.x),每个大版本包含 6-9 个小版本
九、版本与发布
截至 2026 年 7 月,LLVM 的发布情况:
| 版本系列 | 首次发布 | 最新小版本 | 状态 |
|---|---|---|---|
| 22.1.x | 2026-02 | 22.1.8 (2026-06) | 当前稳定版 |
| 23.1.x | 预计 2026-08 | 开发中 | release/23.x 分支已创建 |
LLVM 采用时间驱动的发布策略:
- 每个大版本约 6 个月周期
- 每个小版本约 2 周间隔
- 严格遵循 RC(Release Candidate)流程
十、如何开始使用
10.1 安装
macOS(通过 Homebrew):
bash
brew install llvm
Ubuntu/Debian(通过 APT 仓库):
bash
# 添加 LLVM 官方仓库
echo "deb http://apt.llvm.org/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/llvm.list
sudo apt install llvm
Windows :从 releases.llvm.org 下载预编译二进制包。
10.2 从源码构建
bash
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
# 使用 CMake 配置
cmake -S llvm -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS="clang;lld;lldb" \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \
-DLLVM_TARGETS_TO_BUILD="X86;AArch64;RISC-V"
# 编译
ninja -C build
10.3 实战:从源码到 IR 到可执行文件
bash
# 1. 将 C 代码编译为 LLVM IR 文本格式
clang -S -emit-llvm hello.c -o hello.ll
# 2. 优化 IR
opt -passes=O2 hello.ll -o hello_opt.bc
# 3. 将 IR 编译为可执行文件
clang hello_opt.bc -o hello
# 4. 查看优化过程中发生了什么
opt -passes=O2 -stats hello.ll -o /dev/null
10.4 编写自定义 Pass
cpp
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
struct HelloPass : PassInfoMixin<HelloPass> {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
errs() << "Hello from function: " << F.getName() << "\n";
return PreservedAnalyses::all();
}
};
十一、LLVM 的技术影响
LLVM 对编译器领域和整个软件行业产生了深远影响:
-
重新定义了编译器架构:三段式设计成为现代编译器的标准模式,GCC 后期也引入了类似结构(GIMPLE IR + 多后端)
-
降低了编译器开发门槛:任何新语言只需实现前端即可获得工业级优化和跨平台能力。Rust、Swift 等语言的成功很大程度上受益于此
-
推动了 JIT 编译的普及:LLVM 的 JIT 能力使得运行时优化成为可能,被 Julia、Numba 等动态语言项目广泛采用
-
催生了 MLIR 生态:MLIR 正在成为 AI 编译器和异构计算编译的事实标准,连接了从高层 DSL 到底层硬件的完整编译链路
-
工业标准级工具链:Apple、Google、Sony、Microsoft 等公司的产品工具链均以 LLVM 为基础,覆盖数十亿设备
十二、结语
LLVM 项目是现代计算机科学领域最成功的开源基础设施项目之一。它不仅是编译器技术的集大成者,更通过模块化设计和可复用组件,深刻改变了编程语言、开发工具和高性能计算的生态格局。
无论你是想为新语言实现编译器、为新型硬件添加后端支持、开发静态分析工具,还是深入理解代码优化原理,LLVM 都是一个值得深入研究的宝库。项目提供了从入门教程到深度文档的完整资源体系,社区也以开放和友好著称。
相关链接
- GitHub: https://github.com/llvm/llvm-project
- 官方文档: https://llvm.org/docs/
- Discourse 论坛: https://discourse.llvm.org/
- LLVM 博客: https://blog.llvm.org/
- Doxygen 文档: https://llvm.org/doxygen/