All LLVM passes are subclasses of the pass
class, and they implement functionality by overriding the virtual methods inherited from pass
. LLVM applies a chain of analyses and transformations on the target program. A pass is an instance of the Pass LLVM class.
Let's see how to write a pass. Let's name the pass function block counter
; once done, it will simply display the name of the function and count the basic blocks in that function when run. First, a Makefile
needs to be written for the pass. Follow the given steps to write a Makefile
:
Makefile
in the llvm lib/Transform
folder:$ vi Makefile
Makefile
, as follows:LEVEL = ../../.. LIBRARYNAME = FuncBlockCount LOADABLE_MODULE = 1 include $(LEVEL)/Makefile.common
This Makefile
specifies that all the .cpp
files in the current directory are to be compiled and linked together in a shared object.
Do the following steps:
.cpp
file called FuncBlockCount.cpp
:$ vi FuncBlockCount.cpp
#include "llvm/Pass.h" #include "llvm/IR/Function.h" #include "llvm/Support/raw_ostream.h"
llvm
namespace to enable access to LLVM functions:using namespace llvm;
namespace {
struct FuncBlockCount : public FunctionPass {
static char ID; FuncBlockCount() : FunctionPass(ID) {}
run
function. Since this pass inherits FunctionPass
and runs on a function, a runOnFunction
is defined to be run on a function:bool runOnFunction(Function &F) override { errs() << "Function " << F.getName() << ' '; return false; } }; }
This function prints the name of the function that is being processed.
char FuncBlockCount::ID = 0;
static RegisterPass<FuncBlockCount> X("funcblockcount", "Function Block Count", false, false);
Putting everything together, the entire code looks like this:
#include "llvm/Pass.h" #include "llvm/IR/Function.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { struct FuncBlockCount : public FunctionPass { static char ID; FuncBlockCount() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { errs() << "Function " << F.getName() << ' '; return false; } }; } char FuncBlockCount::ID = 0; static RegisterPass<FuncBlockCount> X("funcblockcount", "Function Block Count", false, false);
A simple gmake
command compiles the file, so a new file FuncBlockCount.so
is generated at the LLVM root directory. This shared object file can be dynamically loaded to the opt tool to run it on a piece of LLVM IR code. How to load and run it will be demonstrated in the next section.
18.221.163.13