Hi.
I’m having difficulty writing a new pass and using opt. I’m following the instructions at Writing an LLVM Pass — LLVM 19.0.0git documentation and have set up a simple pass related to memory access.
Following the instructions in the user guide, I’ve structured the MemoryProfiler.h file in llvm/include/llvm/Transforms/Utils as follows.
#ifndef LLVM_TRANSFORMS_MEMORYNEW_MEMORYPROFILER_H
#define LLVM_TRANSFORMS_MEMORYNEW_MEMORYPROFILER_H
#include "llvm/IR/PassManager.h"
namespace llvm {
class MemoryProfilerPass : public PassInfoMixin<MemoryProfilerPass> {
public:
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
};
} // namespace llvm
#endif // LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H
Additionally, I’ve structured the MemoryProfiler.cpp file in llvm/lib/Transforms/Utils as follows.
#include "llvm/Transforms/Utils/MemoryProfiler.h"
#include <vector>
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Passes/PassBuilder.h"
using namespace llvm;
PreservedAnalyses MemoryProfilerPass::run(Module &M, ModuleAnalysisManager &MAM) {
IRBuilder<> builder(M.getContext());
// 'printf' function type and declaration
FunctionType *printfType = FunctionType::get(IntegerType::getInt32Ty(M.getContext()), {PointerType::get(Type::getInt8Ty(M.getContext()), 0)}, true);
FunctionCallee printFunc = M.getOrInsertFunction("printf", printfType);
// Creating message constants
GlobalVariable *loadStringVariable = new GlobalVariable(
M,
ArrayType::get(IntegerType::getInt8Ty(M.getContext()), 23),
true,
GlobalValue::PrivateLinkage,
ConstantDataArray::getString(M.getContext(), "I am loading address %p\n"),
"load_string"
);
GlobalVariable *storeStringVariable = new GlobalVariable(
M,
ArrayType::get(IntegerType::getInt8Ty(M.getContext()), 28),
true,
GlobalValue::PrivateLinkage,
ConstantDataArray::getString(M.getContext(), "I am storing %ld at address %p\n"),
"store_string"
);
for (auto &F : M) {
for (auto &B : F) {
for (auto &I : B) {
builder.SetInsertPoint(&I);
if (auto *load = dyn_cast<LoadInst>(&I)) {
auto *address = load->getPointerOperand();
Value *args[] = {builder.CreateGlobalStringPtr("I am loading address %p\n"), address};
builder.CreateCall(printFunc, args);
} else if (auto *store = dyn_cast<StoreInst>(&I)) {
auto *value = store->getValueOperand();
auto *address = store->getPointerOperand();
Value *args[] = {builder.CreateGlobalStringPtr("I am storing %ld at address %p\n"), value, address};
builder.CreateCall(printFunc, args);
}
}
}
}
return PreservedAnalyses::none();
}
To register the newly created pass, I’ve included the header file in PassBuilder.cpp, and I’ve also added
MODULE_PASS("memoryprofiler", MemoryProfilerPass())
to PassRegistry.def. Then, after building in the build directory using gmake, when I input
opt -disable-output ./test.ll -passes=memoryprofiler
I encounter the following error:
opt: unknown pass name 'memoryprofiler'.
Thanks for many helps!!