You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LLVM新Pass Manager迁移:如何访问llvm::CallGraphSCC?

解决方案:迁移基于CallGraphSCC的Pass到新Pass Manager

新Pass Manager(New PM)不再提供旧PM中CallGraphSCCPass直接封装的SCC遍历机制,也没有CallGraphWrapperPass的getCallGraphSCC()方法。你需要通过显式获取CallGraph分析结果,再用LLVM的scc_iterator工具手动遍历调用图的强连通分量(SCC)。

核心思路

  1. 新PM中,CallGraph是作为一种分析结果提供的,需要在自定义Pass中声明对它的依赖。
  2. 使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:05:25