LLVM 16.0.6自定义HelloPass加载失败求助:opt提示未知pass名称
问题排查与解决方案
你的核心问题在于LLVM 16默认启用新版Pass Manager(New PM),但你的代码使用的是旧版Legacy Pass Manager的注册方式,导致opt无法识别自定义的hello Pass。以下是具体的排查和解决方法:
一、快速修复:使用旧版Pass Manager调用Opt
直接修改opt命令,强制启用旧版Pass Manager并使用旧参数格式:
opt -load build/helloPass/libHelloPass.so -legacy-pass-manager -hello test.bc > /dev/null
执行该命令后,应该能正常输出函数名的Hello日志。
二、长期方案:适配新版Pass Manager修改代码
如果需要兼容LLVM 16+的新版Pass Manager,需要修改代码和CMake配置:
1. 修改hello.cpp代码
替换为新版Pass的定义与注册逻辑:
#include "llvm/IR/Function.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/PassBuilder.h" using namespace llvm; namespace { // 继承新版Pass的基类PassInfoMixin struct Hello : public PassInfoMixin<Hello> { // 新版Pass的核心执行方法 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { errs() << "Hello: "; errs().write_escaped(F.getName()) << '\n'; return PreservedAnalyses::all(); // 保留所有分析结果 } // 标记该Pass为必须执行 static bool isRequired() { return true; } }; } // 匿名命名空间结束 // 注册Pass插件的入口函数 extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { return { LLVM_PLUGIN_API_VERSION, "HelloPass", "v0.1", [](PassBuilder &PB) { // 注册Pipeline解析回调,识别"hello"命令 PB.registerPipelineParsingCallback( [](StringRef Name, FunctionPassManager &FPM, ArrayRef<PassBuilder::PipelineElement>) { if (Name == "hello") { FPM.addPass(Hello()); return true; } return false; } ); } }; }
2. 更新CMake配置
修改helloPass/CMakeLists.txt,添加新版Pass所需的链接库:
cmake_minimum_required(VERSION 3.25) add_library(HelloPass MODULE hello.cpp) set_target_properties(HelloPass PROPERTIES COMPILE_FLAGS "-fno-rtti" ) # 链接新版Pass相关库 target_link_libraries(HelloPass PRIVATE LLVMIRReader LLVMPasses)
同时优化主CMakeLists.txt,使用LLVM提供的标准变量替代手动路径:
cmake_minimum_required(VERSION 3.25) project(llvm_kernel CXX C) set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_COMPILER /usr/bin/clang) set(CMAKE_CXX_COMPILER /usr/bin/clang++) find_package(LLVM REQUIRED CONFIG) separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) add_definitions(${LLVM_DEFINITIONS_LIST}) # 使用LLVM自动设置的目录变量 include_directories(${LLVM_INCLUDE_DIRS}) link_directories(${LLVM_LIBRARY_DIRS}) add_subdirectory(helloPass)
3. 编译并调用
重新编译后,使用新版Pass Manager的命令调用:
opt --load-pass-plugin=build/helloPass/libHelloPass.so -p hello test.bc > /dev/null
三、额外验证
执行以下命令查看是否能识别自定义Pass:
opt --load-pass-plugin=build/helloPass/libHelloPass.so --print-passes | grep hello
此时应该能看到自定义的hello Pass。
内容的提问来源于stack exchange,提问作者Hardy
相关产品推荐
相关产品推荐

