LLVM新Pass Manager迁移:如何访问llvm::CallGraphSCC?
解决方案:迁移基于CallGraphSCC的Pass到新Pass Manager
新Pass Manager(New PM)不再提供旧PM中CallGraphSCCPass直接封装的SCC遍历机制,也没有CallGraphWrapperPass的getCallGraphSCC()方法。你需要通过显式获取CallGraph分析结果,再用LLVM的scc_iterator工具手动遍历调用图的强连通分量(SCC)。
核心思路
- 新PM中,CallGraph是作为一种分析结果提供的,需要在自定义Pass中声明对它的依赖。
- 使用
llvm::scc_iterator遍历CallGraph的所有节点,生成每个SCC的函数集合,替代旧PM中runOnSCC的自动遍历逻辑。
新旧代码对比与迁移示例
旧PM代码(参考)
#include "llvm/Analysis/CallGraphSCCPass.h" namespace llvm { class AnnotateInternalFunctionsPass : public CallGraphSCCPass { public: static char ID; AnnotateInternalFunctionsPass() : CallGraphSCCPass(ID) {} bool runOnSCC(CallGraphSCC &SCC) override { // 处理当前SCC中的函数 for (CallGraphNode *Node : SCC) { Function *F = Node->getFunction(); if (!F || F->isDeclaration() || !F->hasInternalLinkage()) continue; // 你的标注逻辑,比如添加属性或元数据 F->addFnAttr("annotated-internal", "true"); } return true; } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } }; char AnnotateInternalFunctionsPass::ID = 0; static RegisterPass<AnnotateInternalFunctionsPass> X("annotate-internals", "Annotate internal functions in SCCs"); }
新PM迁移后的代码
#include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CallGraphSCCPass.h" // 仅用于scc_iterator #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/PassManager.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" using namespace llvm; class AnnotateInternalFunctionsPass : public PassInfoMixin<AnnotateInternalFunctionsPass> { public: PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { // 获取CallGraph分析结果 CallGraph &CG = AM.getResult<CallGraphAnalysis>(M); // 遍历CallGraph的所有SCC for (scc_iterator<CallGraph *> I = scc_begin(&CG), E = scc_end(&CG); I != E; ++I) { const std::vector<CallGraphNode *> &SCC = *I; // 处理当前SCC中的函数,逻辑与旧PM一致 for (CallGraphNode *Node : SCC) { Function *F = Node->getFunction(); if (!F || F->isDeclaration() || !F->hasInternalLinkage()) continue; // 你的标注逻辑 F->addFnAttr("annotated-internal", "true"); } } // 标注操作不影响分析结果,返回PreservedAnalyses::all() return PreservedAnalyses::all(); } // 声明需要CallGraphAnalysis依赖 static bool isRequired() { return true; } }; // 注册新PM Pass extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { return { LLVM_PLUGIN_API_VERSION, "AnnotateInternalFunctions", "v0.1", [](PassBuilder &PB) { PB.registerPipelineParsingCallback( [](StringRef Name, ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement>) { if (Name == "annotate-internals") { MPM.addPass(AnnotateInternalFunctionsPass()); return true; } return false; } ); } }; }
关键说明
- 依赖声明:通过
isRequired()返回true,或者在run方法中直接获取CallGraphAnalysis,新PM会自动处理依赖关系,确保CallGraph已被计算。 - SCC遍历:
scc_iterator是LLVM提供的通用工具,可用于遍历任何满足GraphTraits接口的图结构,CallGraph天然支持这个接口,因此可以直接使用。 - Pass注册:新PM使用插件式注册(
llvmGetPassPluginInfo),替代旧PM的RegisterPass宏。如果是在LLVM内部集成Pass,注册方式会略有不同,但核心逻辑一致。
内容的提问来源于stack exchange,提问作者supercheval
相关产品推荐
相关产品推荐

