LLVM Running your first pass simplified.
After so much of struggle of many hours finally I found some step guide which can be useful for writing the pass successfully. I hope it will save your time. Dont know why no one make this simple for novice. I assume your llvm build environment is ready and installed with llvm, cmake and ninja. I dont want to mix it up here to make this more complex.
Step1: Create a directory to host your LLVM pass
mkdir ~/llvm-project/llvm/lib/Transforms/test
Step2: Update the CMake file in the Transforms directory
~/llvm/llvm/lib/Transforms/CMakeLists.txt
vim CMakeLists.txt
Add this line add_subdirectory(test)
Now goto your folder test
cd test
Now we will work inside test folder.
Step3 Create a CMake file for your LLVM pass
vim CMakeLists.txt
Add the following to the CMakeLists.txt file
add_llvm_library(LLVMtest MODULE test.cpp
PLUGIN_TOOL opt )
**Step4 **create CPP file for your LLVM pass
vim test.cpp
with following code
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
using namespace llvm;
namespace {
struct test : public FunctionPass {
static char ID;
test() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
errs() << "Hello: ";
errs().write_escaped(F.getName()) << '\n';
return false;
}
}; // end of struct Hello
} // end of anonymous namespace
char test::ID = 0;
static RegisterPass<test> X("test", "Hello World Pass",
false /* Only looks at CFG */,
false /* Analysis Pass */);
static RegisterStandardPasses Y(
PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) { PM.add(new test()); });
Step5: Generate the IR file clang++ -O0 -g -S -emit-llvm -o test.ll -c test.cpp
Step6: Now we will move to build folder
cd ~/llvm-project/build
(There is some problem in CMakeCache.txt regarding user name. Find and replace cpen400 with cpen)
vim CMakeCache.txt
:s/cpen400/cpen/g :wr and quit
Step7: Now run the cmake with path as .. will not work
~/llvm-project/build$ cmake ../llvm/lib/Transforms/test
Step8: Now run Ninja
~/llvm-project/build$ninja -j4
Step9: Now it will build full llvm project in 2 hours. Wait for it and move to lib directory to check .so file.
cd lib
ls -l
Step 10: Now to test this pass create a dummy program hello.c in your test directory:
void a(){
int c = 5;
}
int main()
{
int d = 1;
a();
return 5;
}
Step 11: Now create the IR file using
clang++ -O0 -g -S -emit-llvm -o fun.ll -c fun.c
Step12: Go back to ~/llvm-project/build directory and load the pass using "opt"
cd..
opt -enable-new-pm=0 -load lib/LLVMtest.so -test < ../llvm/lib/Transforms/test/fun.ll > /dev/null
You may see output like
Hello: _Z1av
Hello: main
Written By
Vinod Kotiya
Comments