opt -load报unknown pass name本质是so未成功加载,而非pass名错误;需确认LLVM版本一致、RTTI开启、符号导出完整、链接顺序正确,并排除IR非法导致的提前退出。

opt -load 后报 unknown pass name 是链接没生效,不是名字写错了
这个错误根本不是 opt 没认出你的 pass 名,而是它压根没加载到你的 so 文件——opt -load ./MyPass.so -mypass 中的 -mypass 还没走到解析阶段,就因为 so 加载失败被跳过了。常见现象是终端只打印一行 unknown pass name 'mypass',但完全没触发你代码里的 llvm::errs() 日志。
- 先确认 so 文件是否真被加载:在 Pass 构造函数里加一句
llvm::errs() ,如果这行不输出,说明 <code>-load失败 - 检查 so 文件路径是否正确、权限是否可读(
ls -l ./MyPass.so) - 运行
ldd ./MyPass.so看有没有 missing 的 LLVM 符号(比如libLLVMCore.so => not found),这是动态链接失败的铁证 - 确保你用的
opt和编译 Pass 时用的 LLVM 版本完全一致;混用 16 和 17 的opt与 so 会静默失败
pass name 在 RegisterPass 里注册,但必须被 opt 正确识别为可用 pass
static RegisterPass<mypass> X("mypass", "Hello World Pass")</mypass> 这行确实注册了名字,但它只是“声明”,不等于“可用”。opt 能列出或使用这个 pass,前提是:
- so 文件必须导出符号
_ZTVN4llvm10PassRegistryE及相关 RTTI 信息(所以 CMake 里不能盲目关 RTTI) - Pass 类必须继承自标准基类(
FunctionPass/ModulePass),且ID静态变量已定义(char MyPass::ID = 0) - 如果你用了 New Pass Manager(默认行为),而代码是 Legacy Pass,必须显式加
-enable-new-pm=0,否则opt根本不查 Legacy 注册表 - 验证方式:
opt -load ./MyPass.so --help | grep mypass—— 如果没输出,说明注册未生效;有输出但运行时报错,则是加载或执行阶段问题
CMake 编译参数错一个,pass name 就永远 unknown
Pass 编译时漏掉关键配置,会导致 so 文件缺失 LLVM 运行时依赖或符号表损坏,opt 加载时直接放弃解析,连名字都不认。
- 必须调用
llvm_map_components_to_libnames获取真实库名,不能硬写LLVMCore;15+ 版本组件名已变,比如LLVMAnalysis→LLVMScalarOpts -
target_link_libraries顺序不能颠倒:先LLVMCore,再LLVMScalarOpts、LLVMTransformUtils等你实际 include 的头文件对应模块 - 若 Pass 里用了
DataLayout或TargetLibraryInfo,必须加LLVMTarget;用了LoopInfo就得链LLVMScalarOpts - MODULE 类型库必须设
BUILDTREE_ONLY,否则 CMake 可能把它当普通静态库处理,导致符号不可见
IR 输入非法也会让 pass name “变 unknown”
这不是名字问题,而是 opt 在加载 so 后、解析命令前,先尝试解析输入 IR;如果 IR 本身语法错误或类型不合法(比如 getelementptr 指针类型错),opt 会提前退出,并把后续所有选项(包括 -mypass)当成未知参数处理,从而报 unknown pass name。
- 先用
llvm-as 验证语法 - 再跑
opt -verify -disable-output test.ll强制做 IR 合法性检查 - 用
llc -march=x86-64 test.ll -o /dev/null测试后端兼容性;如果 llc 都报错,说明 IR 有问题,Pass 只是第一个撞上的 - 临时把输入换成官方
Hello.ll(clang -S -emit-llvm hello.c -o hello.ll生成的),排除 IR 干扰
opt 默认走新管线,Legacy Pass 就像没写过一样。

















