Is there any initialization/finalization methods in new pass manager?

Hi folks. I’m working on analyzing the targets for each indirect call site. In the legacy LLVM pass manager, I can initialize the data structures to collect call sites in the doInitialization() function, and save the results to json files in the doFinalization() function.

I noticed that (link) there are no doInitialization() and doFinalization() functions in the new pass manager.
This post mentions dtor-based mechanism, but I have no idea about it.
I’m a newbie in LLVM and C++, any comment is welcomed.
Thanks in advance!

With the new pass manager, a pass is just a C++ class that exposes a run method with the appropriate parameters (depending on the kind of pass, e.g. taking a Module and ModuleAnalysisManager parameter if it’s a module pass, etc).

The idea is that you can do whatever you’d have done in doFinalization in the destructor of your pass.

For initialization - it depends. You mentioned call sites. If you need the call sites right before your pass starts doing its transformations, then I’m assuming your pass is a module pass, and you can just do what you need in your pass’ ::run(). If you need to capture that info at a different point in time, it’s a bit more complicated, let me know if that’s your scenario and I can walk you through that, too.

1 Like

Thank you mtrofin.
Actually I’m using a Function pass, which refers to the Bye pass from LLVM 15.0.0.
My HelloICall class was defined in helloicall.h:

#ifndef LLVM_TRANSFORMS_UTILS_HELLOICALL_H
#define LLVM_TRANSFORMS_UTILS_HELLOICALL_H

#include "llvm/IR/PassManager.h"
#include "llvm/json/json.h"
#include <fstream>

namespace llvm {

class HelloICallPass : public PassInfoMixin<HelloICallPass> {
private:
    Json::Value IndirectCallsitesJsonRoot;
    std::ofstream jsonFile;
public:
    HelloICallPass();
    ~HelloICallPass();
    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};

} // namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_HELLOICALL_H

In file HelloICall.cpp, I implemented

  • HelloICallPass::HelloICallPass(), where I did nothing.
  • HelloICallPass::run() function, where I analyzed the indirect call sites and collects the information to the IndirectCallsitesJsonRoot variable.
  • HelloICallPass::~HelloICallPass(), where I saved the collected results to a json file.

However, after I re-compiled LLVM, it reported an error:

llvm/include/llvm/IR/PassManager.h:557:9: error: use of deleted function 'llvm::HelloICallPass::HelloICallPass(const llvm::HelloICallPass&)'
  557 |         new PassModelT(std::forward<PassT>(Pass))));

I managed to remove the constructor HelloICallPass::HelloICallPass() and set IndirectCallsitesJsonRoot jsonFile as global variables rather than the private variables in HelloICallPass, then it compiled correctly.

Why it failed when I explicitly defined the constructor? I preferred to define variables as class’s private data.
Thank you!

Maybe it’s because std::ofstream is not copyable?

1 Like

Thank you Min!
I set only the std::ofstream jsonFile as a global variable, kept the constructor of HelloICallPass, and it works.