llvm pass编译失败时,根本原因在于头文件依赖缺失、cmake链接配置错误或ir类型使用不匹配;须显式调用llvm_map_components_to_libnames映射新版本组件名,严格按llvmcore→analysis→transformutils等依赖顺序链接,并用llvm-as、opt-verify验证ir合法性。

检查CMakeLists.txt中llvm_map_components_to_libnames是否调用
LLVM 15+ 版本组件名已重命名,llvm_map_components_to_libnames 不再是可选项,而是必须显式调用。硬写 LLVMCore 或 LLVMAnalysis 这类旧名字会直接导致链接失败——因为实际库名可能是 LLVMScalarOpts、LLVMTarget 等。漏掉这一步,target_link_libraries 就等于在链不存在的库。
正确写法示例:
llvm_map_components_to_libnames(REQ_LIBS
Core
ScalarOpts
TransformUtils
Analysis
)
target_link_libraries(MyPass PRIVATE ${REQ_LIBS})
常见错误:只写 target_link_libraries(MyPass PRIVATE LLVMCore),不调用映射函数;或映射后没把变量传给 target_link_libraries。
确认target_link_libraries顺序是否颠倒
LLVM 库之间有强依赖关系,链接顺序错一位就可能触发 undefined reference to 'llvm::errs()' 或 llvm::FunctionPass::createPrinterPass。链接器从左到右解析符号,依赖者必须放在被依赖者前面。
必须遵守的顺序原则:
-
LLVMCore必须排第一(几乎所有 Pass 都依赖它) - 若用了
LoopInfo,LLVMScalarOpts必须在它之前 - 若访问
DataLayout或写ModulePass,LLVMTarget不可省略,且应靠前 -
LLVMTransformUtils依赖LLVMAnalysis,所以后者要先于前者出现
错误示例:target_link_libraries(MyPass PRIVATE LLVMTransformUtils LLVMCore) —— LLVMCore 在后,LLVMTransformUtils 里引用的符号找不到定义。
验证IR输入是否合法,避免Pass执行时才崩溃
很多“编译通过但 opt -load ./MyPass.so 段错误”,其实不是链接问题,而是 IR 本身不合法。LLVM 不会在加载时校验,而是在 Pass 第一次访问某条指令时断言失败,报错却显示成链接错误(因堆栈已损坏)。
快速验证步骤:
- 用
llvm-as -o /dev/null test.ll检查语法是否能汇编 - 运行
opt -verify -disable-output test.ll强制做 IR 合法性检查(会暴露getelementptr类型不匹配、undef被当实值用等问题) - 用
llc -march=x86-64 test.ll -o /dev/null测试后端兼容性——如果llc都报错,说明 IR 有问题,Pass 只是第一个撞上的
临时加日志定位阶段:llvm::errs() 放在构造函数里;<code>llvm::errs() 放在 <code>runOnFunction 开头。看输出停在哪,就能区分是加载失败还是执行崩溃。
最小化复现:从空FunctionPass开始逐步加逻辑
别一上来就写完整 ModulePass 或尝试改 IR。90% 的崩溃来自非法 IR 修改(比如删掉还在被引用的 Value),而不是链接配置本身。先确保骨架能跑通,再增量引入逻辑。
操作路径:
- 新建最简
FunctionPass,只保留runOnFunction和getAnalysisUsage,函数体 return false - 确保它能编译 +
opt -load成功运行(无段错误、无崩溃) - 每次只加一行 IR 访问逻辑:先加
for (auto &BB : F),再加for (auto &I : BB),每加一行就重新编译测试 - 一旦失败,问题就定位在这行对 IR 的访问方式——比如
I.getOperand(0)返回了nullptr,或I.getType()是 void 类型却当成指针用
最容易被忽略的是:IR 合法性检查和链接排查必须并行。一个 undefined reference 报错背后,可能是 CMake 配置错,也可能是你传进去的 .ll 文件里有个 call void @llvm.dbg.declare 缺少 metadata,而这个错误直到 Pass 执行时才暴露。











