How to compile a new pass in source Tree

231 阅读1分钟

1 Prepare LLVM project.

  1. Clone LLVM-Project from Github.
git clone https://github.com/llvm/llvm-project.git <your_favorite_folder>
  1. Build LLVM-Project with Building LLVM with CMake
cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="RISCV" -G Ninja ../llvm
cmake --build .

After build completed, we have a workable opt for testing our new passes, like the following command shows.

cd llvm-project/build
./bin/opt -load lib/LLVMHello.dylib --help
...
Optimizations available:
--aa                                                                - Function Alias Analysis Results
...

2 Make your pass

Reference Writing an LLVM Pass to make a pass.

3 Compile your pass

Because in above step, following that document to make an example pass, we should add add_subdirectory(XXX) into the lib/Transforms/CMakeLists.txt.

So when we reconfig our cmake build, cmake will generate build commands to handle our new pass shared library.

cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="RISCV" -G Ninja ../llvm
cmake --build .

Then the compiled shared library would be under the build/lib directory.

4 Test it with opt

./bin/opt -load lib/LLVMHello.dylib -hello <xxx.ll>

-load: load a shared library. -hello: execute the hello pass. <xxx.ll>: the file to be run pass on.

5 Dump Passes

To dump passes, we can add a module pass to do that.

namespace {
struct DumpPasses : public ModulePass {
  static char ID; // Pass identification, replacement for typeid
  DumpPasses() : ModulePass(ID) {}
  bool runOnModule(Module &) override {
    this->getResolver()->getPMDataManager().getTopLevelManager()->dumpPasses();
    return false;
  }
};
} // namespace
char DumpPasses::ID = 0;
static RegisterPass<DumpPasses> Z("DumpPasses", "DumpPasses");

Then rebuild llvm:

cmake --build .

Now, use the following command to show the result:

./bin/opt --debug-pass=Structure -S -load lib/BBOpts.dylib -DumpPasses <xxx.ll>