ORC JIT是LLVM面向编译器作者的可组合底层JIT构建块,用于将已生成的IR模块动态编译为机器码并执行;核心流程为:创建ExecutionSession→配置IRTransformLayer和ObjectLinkingLayer→添加模块→解析符号获取函数指针。

理解 ORC JIT 的核心定位
ORC(On-Resident Compilation)是 LLVM 提供的现代 JIT 框架,取代了旧版 MCJIT。它不是“一键运行字符串代码”的工具,而是面向编译器作者设计的、可组合、可扩展的底层 JIT 构建块。你用它来把 已生成的 IR 模块(Module) 动态编译成机器码并执行,不是直接喂 C++ 源码。
基础流程:从 Module 到可调用函数
典型路径分四步:构造 ExecutionSession → 设置 ORC Layer(IRTransformLayer + ObjectLinkingLayer)→ 添加模块 → 解析符号获取函数指针。
- 用
ExecutionSession管理 JIT 内存、符号表和资源生命周期 - 用
IRTransformLayer注入优化(如createFunctionPassManagerForModule),再接ObjectLinkingLayer完成链接 - 调用
addIRModule注入std::unique_ptr,ORC 自动编译、重定位、注册符号 - 用
lookup("func_name")得到JITSymbol,再调用getAddress()转为函数指针(注意类型强转)
关键细节:内存管理与符号可见性
ORC 默认使用 jitdylib 隔离符号空间。主 JIT dylib(如 es.createBareJITDylib("main"))需显式添加依赖才能看到外部符号(比如 printf)。
- 对外部 C 函数,先用
absoluteSymbols注册地址,再通过auto &mainJD = es.createBareJITDylib("main"); mainJD.addGenerator(...)让 JIT 能解析它们 - 避免多次
addIRModule引发重复定义错误:每个 Module 的全局符号名必须唯一,或启用setAutoClaimResponsibilityForObjectSymbols(true) - 释放资源时,调用
removeModule或直接销毁 JITDylib —— ORC 会自动回收对应内存页(通过SectionMemoryManager)
实用示例:编译一个加法函数并调用
假设你已有 LLVM IR 描述的 int add(int a, int b) { return a + b; }(可用 parseIRFile 或手动生成):
立即学习“C++免费学习笔记(深入)”;
- 创建
ExecutionSession ES;和MangleAndInterner Mangle(ES, DL); - 构建
ObjectLinkingLayer OL(ES, []() { return std::make_unique(); }); - 套上
IRTransformLayer IRT(ES, OL, [](Module &M, const MaterializationResponsibility &) { return optimizeModule(M); }); - 将 Module 加入 JITDylib:
auto &MainJD = ES.createBareJITDylib("main"); MainJD.addGenerator(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(DL.getGlobalPrefix())); IRT.addModule(std::move(M), MainJD); - 查符号:
auto Sym = ES.lookup({&MainJD}, Mangle("add")); auto AddPtr = (int(*)(int,int))Sym->getAddress(); int r = AddPtr(3, 5); // 得到 8
基本上就这些。不复杂但容易忽略符号注册和内存管理边界。











