Opt: unknown pass name

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!!

hey!

You can find a collection of examples that “just work” in this project on GitHub:

This might be helpful.

-Andrzej

Thanks!!
I’ll study with your github.