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?