[LLVM Pass/LLVM version 16] Failed to load passes from './lib/libMBAZZH.so'. Request ignored

Hi. I’m learning how to write an LLVM pass and following llvm-tutor. I’m trying to modify ./lib/MBAAdd.cpp in llvm-tutor but failed in an hello-world level LLVM pass. Here is my code, the code will print the binaryOP and unaryOP:

# ./lib/MBAZZH.cpp
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "MBAZZH.h"
using namespace llvm;
#define DEBUG_TYPE "mba-zzh"
bool MBAZZH::runOnBasicBlock(BasicBlock &BB){
    bool Changed = false;
    for(auto Inst = BB.begin(), IE = BB.end(); Inst != IE; ++Inst){
        if(auto *BinOp = dyn_cast<BinaryOperator>(Inst)){
            outs() << "I'm BinOP!\n";
        } 
        if(auto *UnaryOp = dyn_cast<UnaryOperator>(Inst)){
            outs() << "I'm unaryOP!\n";
        }
    }
    return Changed;
}

PreservedAnalyses MBAZZH::run(llvm::Function &F,
                              llvm::FunctionAnalysisManager &) {
  bool Changed = false;

  for (auto &BB : F) {
    Changed |= runOnBasicBlock(BB);
  }
  return (Changed ? llvm::PreservedAnalyses::none()
                  : llvm::PreservedAnalyses::all());
}


// New style PM Registration
// llvm::PassPluginLibraryInfo getMBAZZHPluginInfo(){
//     auto callback = [](PassBuilder &PB){
//         PB.registerPipelineParsingCallback(
//             [](StringRef Name, FunctionPassManager &FPM,
//             ArrayRef<PassBuilder::PipelineElement>){
//                 if(Name == "mba-zzh"){
//                     FPM.addPass(MBAZZH());
//                     return true;
//                 }
//                 return false;
//             }
//         );    
//     };
//     return {LLVM_PLUGIN_API_VERSION, "mba-zzh", LLVM_VERSION_STRING,callback};
// }
llvm::PassPluginLibraryInfo getMBAZZHPluginInfo() {
  return {LLVM_PLUGIN_API_VERSION, "mba-zzh", LLVM_VERSION_STRING,
          [](PassBuilder &PB) {
            PB.registerPipelineParsingCallback(
                [](StringRef Name, FunctionPassManager &FPM,
                   ArrayRef<PassBuilder::PipelineElement>) {
                  if (Name == "mba-zzh") {
                    FPM.addPass(MBAZZH());
                    return true;
                  }
                  return false;
                });
          }};
}

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo(){
    return getMBAZZHPluginInfo();
}

char LegacyMBAZZH::ID = 0;
static RegisterPass<LegacyMBAZZH> X("legacy-mba-zzh","MBAZZH",true,false);


#undef DEBUG_TYPE

#./include/MBAZZH.h
#ifndef __GIT_LLVM_TUTOR_INCLUDE_MBAZZH_H_
#define __GIT_LLVM_TUTOR_INCLUDE_MBAZZH_H_

#include "llvm/Pass.h"
#include "llvm/IR/PassManager.h"
struct MBAZZH : public llvm::PassInfoMixin<MBAZZH>{
  llvm::PreservedAnalyses run(llvm::Function &F,
                              llvm::FunctionAnalysisManager &);
    bool runOnBasicBlock(llvm::BasicBlock &B);
  static bool isRequired() { return true; }
};

struct LegacyMBAZZH : public llvm::FunctionPass {
    static char ID;
    LegacyMBAZZH(): FunctionPass(ID) {}
    bool runOnFunction(llvm::Function &F) override;
    MBAZZH Impl;
};
#endif // __GIT_LLVM_TUTOR_INCLUDE_MBAZZH_H_

I have modified CMakeLists.txt and ./lib/libMBAZZH.so can be generated correctly. But I got the following error:

opt -load-pass-plugin ./lib/libMBAZZH.so -passes=mba-zzh 1.ll                 
Failed to load passes from './lib/libMBAZZH.so'. Request ignored.
WARNING: You're attempting to print out a bitcode file.
This is inadvisable as it may cause display problems. If
you REALLY want to taste LLVM bitcode first-hand, you
can force output with the `-f' option.

opt-16: unknown pass name 'mba-zzh'

The error message is too ambiguous to debug. I have tried to use nm --demangle to compare the output symbol but still have no idea. Any guys have some idea?

Hey @syheliel ,

Your code looks OK. To keep things simple, you could strip all the logic related to the legacy pass manager.

How do you build your new plugin? What’s the CMake output?

-Andrzej

1 Like

@banach-space Thanks. The root cause is the code about legacy pass manager. After remove them and rebuild, the code can work again. But I’m cursious about why the code in llvm-tutor doesn’t have the same problem? e.g. in https://github.com/banach-space/llvm-tutor/blob/main/lib/MBAAdd.cpp , it contains two pass manager:

//-----------------------------------------------------------------------------
// New PM Registration
//-----------------------------------------------------------------------------
llvm::PassPluginLibraryInfo getMBAAddPluginInfo() {
  return {LLVM_PLUGIN_API_VERSION, "mba-add", LLVM_VERSION_STRING,
          [](PassBuilder &PB) {
            PB.registerPipelineParsingCallback(
                [](StringRef Name, FunctionPassManager &FPM,
                   ArrayRef<PassBuilder::PipelineElement>) {
                  if (Name == "mba-add") {
                    FPM.addPass(MBAAdd());
                    return true;
                  }
                  return false;
                });
          }};
}

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
  return getMBAAddPluginInfo();
}

//-----------------------------------------------------------------------------
// Legacy PM Registration
//-----------------------------------------------------------------------------
char LegacyMBAAdd::ID = 0;

static RegisterPass<LegacyMBAAdd> X(/*PassArg=*/"legacy-mba-add",
                                    /*Name=*/"MBAAdd",
                                    /*CFGOnly=*/true,
                                    /*is_analysis=*/false);

But the generated pass doesn’t have the same problem like mine

It will be very hard to answer without knowing your full configuration and having it reproduced locally. But even then, mindful that the legacy pass manager is deprecated, I suggest focusing on the working version that uses the new pass manager :slight_smile:

-Andrzej

1 Like