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

如何在单个文件中同时注册LLVM函数Pass与模块Pass?

如何在单个LLVM新Pass Manager插件中同时注册FunctionPass和ModulePass

你遇到的问题核心在于registerPipelineParsingCallback的回调签名需要匹配不同类型的PassManager(FunctionPassManager或ModulePassManager),不能直接把两者同时作为参数传入同一个lambda。下面是两种可行的解决方案:

方案1:注册多个独立的回调函数

最直观的方式是分别注册两个registerPipelineParsingCallback调用,每个回调对应一种PassManager类型,分别处理你的FunctionPass和ModulePass:

修正后的完整代码如下:

#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"

namespace {
struct HelloNewPMPass : public llvm::PassInfoMixin<HelloNewPMPass> {
  llvm::PreservedAnalyses run(llvm::Function &F, llvm::FunctionAnalysisManager &FAM) {
    llvm::errs() << "Running HelloNewPMPass on function: " << F.getName() << "\n";
    return llvm::PreservedAnalyses::all();
  }
};

// 注意修正PassInfoMixin的模板参数为当前类名(你之前写的StringEncryptionPass是笔误)
struct SecondPass : public llvm::PassInfoMixin<SecondPass> {
  llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &MAM) {
    llvm::errs() << "Running SecondPass on module: " << M.getName() << "\n";
    return llvm::PreservedAnalyses::all();
  }
};
}

extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() {
  return {
    LLVM_PLUGIN_API_VERSION, "MultiPassPlugin", "v0.1",
    [](llvm::PassBuilder &PB) {
      // 注册处理FunctionPass的回调
      PB.registerPipelineParsingCallback(
        [](llvm::StringRef PassName, llvm::FunctionPassManager &FPM, auto...) {
          if (PassName == "fiber") {
            FPM.addPass(HelloNewPMPass());
            return true;
          }
          return false;
        }
      );

      // 注册处理ModulePass的回调
      PB.registerPipelineParsingCallback(
        [](llvm::StringRef PassName, llvm::ModulePassManager &MPM, auto...) {
          if (PassName == "second-pass") {
            MPM.addPass(SecondPass());
            return true;
          }
          return false;
        }
      );
    }
  };
}

方案2:使用泛型Lambda统一处理多种PassManager类型

如果你倾向于用单个回调覆盖两种场景,可以利用C++17的泛型Lambda和constexpr if来判断传入的PassManager类型:

extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() {
  return {
    LLVM_PLUGIN_API_VERSION, "MultiPassPlugin", "v0.1",
    [](llvm::PassBuilder &PB) {
      PB.registerPipelineParsingCallback(
        [](llvm::StringRef PassName, auto &PM, auto...) {
          using PMType = std::decay_t<decltype(PM)>;
          // 编译时判断PassManager类型
          if constexpr (std::is_same_v<PMType, llvm::FunctionPassManager>) {
            if (PassName == "fiber") {
              PM.addPass(HelloNewPMPass());
              return true;
            }
          } else if constexpr (std::is_same_v<PMType, llvm::ModulePassManager>) {
            if (PassName == "second-pass") {
              PM.addPass(SecondPass());
              return true;
            }
          }
          return false;
        }
      );
    }
  };
}

关键注意事项

  1. 修正SecondPass的PassInfoMixin模板参数:你之前写的StringEncryptionPass是笔误,必须改为当前类名SecondPass,否则会触发编译错误。
  2. 编译器版本要求:两种方案都需要编译器支持C17(LLVM本身也要求C17及以上版本)。
  3. 运行方式:使用opt命令时可以分别或同时指定两个Pass,比如:
    • 单独运行FunctionPass:opt -passes="fiber" -disable-output input.ll
    • 单独运行ModulePass:opt -passes="second-pass" -disable-output input.ll
    • 同时运行两个Pass:opt -passes="second-pass,fiber" -disable-output input.ll(ModulePass通常先于FunctionPass执行)

内容的提问来源于stack exchange,提问作者HAPPY

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:18:10