用C++基于LLVM OrcV2实现JIT编译器的核心是构建IR模块、配置ExecutionSession与IRCompileLayer、注册模块并获取函数指针调用;需启用RTTI/EH、链接llvm-orc等库、注意上下文生命周期和符号解析。

用 C++ 基于 LLVM 实现一个简单 JIT 编译器,核心不是“从零写编译器”,而是利用 LLVM 提供的 orc JIT 架构快速把内存中的 IR(中间表示)编译成可执行机器码并即时调用。关键在于理解 LLVM 的模块构建、优化、JIT 执行流程,而不是手写词法/语法分析。
准备环境:链接 LLVM 并启用 OrcV2
确保安装 LLVM(≥14.0,推荐 16+),CMake 中正确 find_package:
- 启用
LLVM_ENABLE_RTTI=ON和LLVM_ENABLE_EH=ON(OrcV2 需要 RTTI) - 链接库:llvm-core、llvm-support、llvm-orc、llvm-executionengine、llvm-irreader、llvm-bitwriter 等
- C++ 标准至少 C++17(OrcV2 大量使用 std::optional、concepts 风格接口)
构建模块:手动创建 Function + BasicBlock + Instructions
跳过前端解析,直接在内存中构造 LLVM IR:
- 用
llvm::LLVMContext、llvm::Module、llvm::IRBuilder创建函数 - 例如实现一个加法函数:
int add(int a, int b) { return a + b; } - 注意:必须设置函数调用约定(
CallingConv::C)、返回类型、参数名,并将函数加入 Module - 最后调用
module->dump()可查看生成的 IR(调试必备)
配置 ORCv2 JIT:ExecutionSession + Dylib + CompileLayer
LLVM 14+ 推荐使用 orc::ExecutionSession + orc::EPCExecutorProcessControl + orc::TidyIRCompileLayer:
立即学习“C++免费学习笔记(深入)”;
- 创建
ExecutionSession和共享资源(如符号查找器) - 用
orc::RTDyldObjectLinkingLayer管理对象文件链接 - 用
orc::IRCompileLayer将 Module 编译为 object code(自动选择 TargetMachine) - 通过
addIRModule注册模块,返回orc::MaterializationUnit句柄
获取并调用函数指针:getSymbolAddress + reinterpret_cast
JIT 编译后,需从符号表提取函数地址并转为可调用指针:
- 调用
jit_lookup("add")(封装了ES.lookup(...))获取JITEvaluatedSymbol - 检查 symbol.getAddress() 是否非零,再用
reinterpret_cast强转 - 直接调用该函数指针,效果等同于本地 C 函数 —— 这就是 JIT 的本质:运行时生成、加载、执行
- 注意:若函数含全局变量或调用外部函数(如 printf),需提前注册符号解析器(
SymbolResolver)
基本上就这些。不复杂但容易忽略细节:上下文生命周期管理、模块所有权转移、符号名是否以 @ 开头、JIT 内存权限(Linux 上可能需 mprotect 设置可执行)。跑通一个 add 函数后,再逐步支持常量、控制流、多函数调用,就自然进入 JIT 深水区了。











