ORCv2是LLVM14后唯一可用的JIT接口,需用KaleidoscopeJIT封装orc::ThreadSafeContext、ExecutionSession和JITDylib,显式注册符号、处理lookup错误并校验getAddress返回值。
orc v2 是当前唯一能直接上手的 LLVM JIT 接口
LLVM 14 之后,
和旧版
已被移除,硬切到
+
+
这套组合。网上大量基于
或
的示例全失效——不是编译不过,就是运行时段错误或符号找不到。
真正可用的最小闭环是:用
(LLVM 自带的参考实现)改写,它封装了 session、dylib、resource tracker 等细节,避免手动管理内存生命周期出错。
不是玩具,它的设计就是为生产级 JIT 场景服务,支持增量添加函数、跨模块符号解析、懒编译(lazy compilation)
别自己拼
+
+
,初始化顺序错一环就卡在
报
或死锁
必须用
包裹
,否则多线程下
可能崩溃,且
内部会静默失败
编译 IR 模块前必须先 resolve 符号依赖
直接把含
、
或自定义 C++ 函数调用的 IR 丢给 JIT,大概率触发
异常,或执行时 SIGILL。JIT 不自动链接 libc 或你的程序符号——它只认你显式注册进去的东西。
解决方法不是“加个 -lc”,而是用
把当前进程的符号表注入
:
立即学习
“
C++免费学习笔记(深入)
”;
这一步必须在
之前完成,否则后续模块里所有外部调用都查不到
如果调用的是你自己写的 C++ 函数(比如
),得用
不能手写,要用
生成,C++ 符号名带 ABI 编码(如
),写错就等于没注册
获取函数指针必须用
+
两步走
很多人卡在最后一步:IR 编译成功、没报错,但调用
直接 crash。问题出在:JIT 返回的不是裸地址,而是
,需要解包并检查是否可执行。
C知道
CSDN推出的一款AI技术问答工具
下载
正确姿势是:
漏掉
的
检查,
不调用会导致后续异常累积,在奇怪位置崩溃
返回值必须判空,JIT 可能因内联、优化或 lazy 编译策略延迟生成机器码
C++ 成员函数、模板实例、lambda 闭包无法直接 JIT 执行——它们依赖 this 指针或捕获环境,JIT 只处理纯 C 风格函数签名
调试段错误最该先看
段错误不报具体行号,
停在
或随机地址?八成是 materialization(代码生成)阶段出问题:比如模块里用了未声明的全局变量、结构体布局和 JIT 假设不一致、或者
没对齐宿主平台。
开启 materialization 日志能快速定位卡点:
这会让 JIT 在每次触发编译时打印 “Compiling module X for symbol Y”,看到某符号卡住,就知道问题出在对应 IR 的生成逻辑
常见陷阱:
创建的
没设 alignment,或
字段顺序与 C++
不一致,导致栈帧错位
别依赖
查 IR——它不反映 JIT 实际看到的优化后 IR;用
(如果启用了 debug 构建)或
反汇编生成的 object 文件更可靠
LLVM JIT 的复杂性不在语法,而在它把编译器内部状态(context、session、dylib、tracker)全暴露给你管。少一个
、漏一次
错误处理、或符号名 mangling 差一个字符,都会让整个链条静默失败。动手前先跑通
里的 Chapter2,比读文档快十倍。
orc::LegacyJITExecutionEngineorc::ThreadSafeContextorc::ExecutionSessionorc::JITDylibcreateMCJITCompilerForModulegetSymbolAddressorc::KaleidoscopeJITKaleidoscopeJITExecutionSessionIRCompileLayerObjectLinkingLayeraddIRModulestd::bad_allocThreadSafeContextLLVMContextparseIRorc::JITDylibprintfmallocllvm::orc::SymbolsNotFoundorc::DynamicLibrarySearchGeneratorJITDylib
auto dylib = jit.createJITDylib("main");
dylib->addGenerator(
orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
jit.getDataLayout().getGlobalPrefix()));
addIRModuleint add(int, int)dylib->define(orc::absoluteSymbols({{mangle("add"), JITEvaluatedSymbol::fromPointer(&add, JITSymbolFlags::Exported)}}))mangle("add")orc::MangleAndInterner_Z3addiilookupgetAddressreinterpret_cast(func_ptr)(42) Expected
auto sym = jit.lookup("my_func");
if (!sym) {
// 处理 llvm::Error,比如打印 sym.takeError()
}
void *addr = sym->getAddress();
if (!addr) {
// getAddress() 返回 nullptr 表示符号存在但不可执行(比如被优化掉或未编译)
}
int (*f)(int) = reinterpret_cast(addr);
symErrortakeError()getAddress()ExecutionSession::setDispatchMaterializationgdb__lldb_init_debuggerDataLayout
jit.getExecutionSession().setDispatchMaterialization(true);
IRBuilderAllocaInstStructTypestructdump()jit.dump()llvm-disThreadSafeContextlookupllvm/examples/Kaleidoscope/BuildingAJIT