因为用了一下numba库,效果很好,得知其底层是LLVM,便一起学习了以下,顺带做个分享~
LLVM(Low Level Virtual Machine)是一个开源的编译器基础设施项目,它提供了一套可重用的编译器工具链技术。以下是关于LLVM的详细介绍:
1. LLVM概述
基本概念
- 名称来源:最初代表"Low Level Virtual Machine",但现在已不再强调这个全称
- 核心思想:提供模块化、可重用的编译器和工具链组件
- 创始:由Chris Lattner在伊利诺伊大学香槟分校发起,现在由LLVM基金会管理
主要特点
- 模块化设计:各个组件可以独立使用
- 中间表示(IR):统一的代码表示形式
- 跨平台支持:支持多种CPU架构和操作系统
- 开源社区:拥有活跃的开源社区贡献
2. LLVM架构组成
核心组件
前端 → LLVM IR → 优化器 → 后端 → 目标代码
2.1 前端(Frontend)
- 作用:将源代码转换为LLVM IR
- 支持的语言 :
- Clang (C/C++/Objective-C)
- Swift
- Rust
- Kotlin
- 以及其他语言的前端
2.2 LLVM IR(中间表示)
llvm
; 示例LLVM IR代码
define i32 @add(i32 %a, i32 %b) {
entry:
%result = add i32 %a, %b
ret i32 %result
}
IR特点:
- 静态单赋值形式(SSA)
- 强类型系统
- 平台无关
- 可读的文本格式和高效的二进制格式
2.3 优化器(Optimizer)
- 作用:对IR进行各种优化
- 优化级别:-O0到-O3,-Os(大小优化)
- 优化技术 :
- 死代码消除
- 内联展开
- 循环优化
- 常量传播等
2.4 后端(Backend)
- 作用:将优化后的IR转换为目标机器代码
- 支持的目标架构 :
- x86/x86-64
- ARM
- PowerPC
- MIPS
- RISC-V等
3. LLVM工具链
主要工具
bash
# 编译器前端
clang - C/C++/Objective-C编译器
# IR工具
llvm-as - 将LLVM IR文本汇编为二进制格式
llvm-dis - 将LLVM IR二进制反汇编为文本格式
opt - LLVM IR优化器
# 后端工具
llc - LLVM静态编译器
lli - LLVM IR解释器和JIT编译器
# 其他工具
llvm-link - LLVM IR链接器
llvm-ar - LLVM归档器
llvm-objdump - 目标文件反汇编器
4. 实际应用场景
4.1 编程语言开发
cpp
// 使用LLVM API创建简单函数的示例
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
using namespace llvm;
Module* createSampleModule() {
auto module = new Module("test", getGlobalContext());
// 创建函数类型: int add(int, int)
FunctionType *funcType = FunctionType::get(
Type::getInt32Ty(getGlobalContext()),
{Type::getInt32Ty(getGlobalContext()), Type::getInt32Ty(getGlobalContext())},
false
);
// 创建函数
Function *func = Function::Create(
funcType,
Function::ExternalLinkage,
"add",
module
);
return module;
}
4.2 JIT编译
cpp
// 简单的JIT编译示例
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JIT.h"
void simpleJITExample() {
// 创建模块和函数
Module* module = createSampleModule();
// 创建JIT执行引擎
ExecutionEngine* engine = EngineBuilder(module).create();
// 获取函数指针并执行
void* addFunc = engine->getPointerToFunction(module->getFunction("add"));
// 调用编译后的函数...
}
5. LLVM生态系统
相关项目
- Clang:C语言家族编译器
- LLDB:调试器
- libc++:C++标准库实现
- OpenMP:并行编程支持
- MLIR:多级中间表示(新兴项目)
工业应用
- Apple:Xcode工具链的核心(取代GCC)
- Google:Android NDK,TensorFlow
- NVIDIA:CUDA编译器
- Mozilla:Rust编译器后端
- 很多其他公司:AMD, Intel, ARM等
6. LLVM的优势
技术优势
-
模块化设计
cpp// 可以单独使用各个组件 Module* module = parseSourceCode(source); optimizeModule(module, OptimizationLevel::O2); TargetMachine* target = createTargetMachine(); emitObjectCode(module, target);
-
统一的中间表示
- 所有语言共享相同的优化器和后端
- 新的语言只需要实现前端
-
优秀的诊断信息
bash# Clang提供清晰的错误信息 $ clang -c test.c test.c:5:10: error: use of undeclared identifier 'undefined_var' return undefined_var; ^
-
快速编译
- Clang通常比GCC编译更快
- 内存占用更低
7. 学习资源
入门资料
- 官方文档:llvm.org/docs
- 教程:LLVM Kaleidoscope教程
- 书籍:《LLVM Cookbook》
开发环境设置
bash
# 获取LLVM源码
git clone https://github.com/llvm/llvm-project.git
# 构建LLVM
cd llvm-project
mkdir build && cd build
cmake -DLLVM_ENABLE_PROJECTS="clang" ../llvm
make -j$(nproc)
8. 实际用例:创建简单编译器
cpp
// 使用LLVM创建简单计算器编译器
class SimpleCalculatorCompiler {
LLVMContext context;
IRBuilder<> builder;
std::unique_ptr<Module> module;
public:
SimpleCalculatorCompiler() : builder(context) {
module = std::make_unique<Module>("simple_calc", context);
}
Function* createAddFunction() {
// 创建加法函数
FunctionType* funcType = FunctionType::get(
Type::getInt32Ty(context),
{Type::getInt32Ty(context), Type::getInt32Ty(context)},
false
);
Function* func = Function::Create(
funcType,
Function::ExternalLinkage,
"add",
module.get()
);
// 创建基本块和代码
BasicBlock* entry = BasicBlock::Create(context, "entry", func);
builder.SetInsertPoint(entry);
// 获取参数
Value* arg1 = &*func->arg_begin();
Value* arg2 = &*(std::next(func->arg_begin()));
// 创建加法指令
Value* result = builder.CreateAdd(arg1, arg2, "addresult");
builder.CreateRet(result);
return func;
}
};
总结
LLVM是现代编译器技术的基石,它的主要价值在于:
- 模块化:可以单独使用各个组件
- 可重用性:新的语言可以复用现有的优化器和后端
- 性能:产生高质量的机器代码
- 工具支持:提供完整的工具链生态系统
无论是开发新的编程语言,还是进行代码分析、优化,或是构建开发工具,LLVM都提供了强大的基础设施支持。