Clang新Pass Manager下注册运行具体LLVM Pass的方法
结论
完全可以直接通过Clang运行指定的LLVM Pass,你之前操作报错的核心原因是混淆了opt工具和Clang的参数逻辑,错用了无关参数。
之前操作的错误原因
-passes=<pass列表>是opt工具专属的命令行参数,LLVM 14及更早版本的核心库本身不注册该参数,通过-mllvm传递时会直接报「未知命令行参数」错误。-foptimization-record-passes=<regex>的作用是过滤哪些Pass可以生成优化记录信息,和Pass是否执行完全无关,自然无法触发你的自定义Pass。
具体实现方式
根据需求有两种主流实现方案,优先推荐第一种,兼容性最好,不需要依赖高版本Clang特性。
方案1:插件自动注册到Clang默认流水线(推荐)
这种方案不需要额外传递Pass列表参数,只要加载插件就能自动在指定位置运行你的Pass,适配所有支持-fpass-plugin的Clang 12+版本。
- 首先修改你的Pass动态库代码,实现Clang要求的Pass插件入口,完成两个核心注册逻辑:
- 注册Pass名的流水线解析规则,让Pass管理器能识别你的Pass名称
- 注册流水线扩展点回调,把你的Pass插入到Clang默认编译流水线的对应位置
最简入口代码示例如下:
#include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" // 替换成你自己的Pass头文件 #include "YourCustomPass.h" extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { return { LLVM_PLUGIN_API_VERSION, "your-pass-name", LLVM_VERSION_STRING, [](llvm::PassBuilder &PB) { // 注册Pass名解析规则,名称和命令中使用的Pass名保持一致 PB.registerPipelineParsingCallback( [](llvm::StringRef Name, llvm::FunctionPassManager &FPM, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>) { if (Name == "mypass") { FPM.addPass(YourCustomPass()); return true; } return false; } ); // 注册到默认流水线,示例为挂在所有优化流程的最后阶段 // 如果需要-O0等级也能运行,优先选择registerPipelineStartEPCallback注册 PB.registerOptimizerLastEPCallback( [](llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) { // 可通过判断Level选择只在特定优化等级下运行Pass MPM.addPass(llvm::createModuleToFunctionPassAdaptor(YourCustomPass())); } ); } }; } - 编译生成动态库后,编译源码时只需要加载插件即可,不需要额外传Pass相关参数:
clang -O0 -fpass-plugin=./mylib.dylib sourcefile.cpp -o output
方案2:手动指定Pass流水线,替换默认流程
如果你不想把Pass自动挂到默认流水线,想手动控制运行哪些Pass、运行顺序,在Clang 15+版本(LLVM核心库已内置-passes参数注册)可以用如下方式:
- 同样需要在动态库中实现上面示例里的
registerPipelineParsingCallback逻辑,让Pass管理器能识别你的自定义Pass名。 - 编译时先关闭Clang默认的Pass流水线,再通过
-mllvm传递自定义的Pass列表:
其中clang -O0 -fpass-plugin=./mylib.dylib \ -mllvm -disable-llvm-passes \ -mllvm -passes=mypass,default<O0> \ sourcefile.cpp -o output-mllvm -disable-llvm-passes用来关闭Clang默认添加的所有Pass,-passes后的字符串和opt工具的Pass语法完全一致,可以自由组合多个Pass、调整顺序。
注意事项
- 不要用旧版Legacy Pass管理器的
RegisterPass宏注册逻辑,新版Clang默认使用New Pass管理器,Legacy Pass的注册方式在-fpass-plugin加载逻辑下不会生效。 -O0等级下Clang默认只会运行最精简的必要流水线,如果你把Pass挂到优化阶段的扩展点可能不会触发,需要测试选择合适的扩展点注册。
内容的提问来源于stack exchange,提问作者KeksimvsMaximvs
相关产品推荐
相关产品推荐

