From: Bill Wendling
Now that we have a way to compile our new pass, we just have to write it. Start out with:
-++++#include "llvm/Pass.h" #include "llvm/Function.h" #include "llvm/Support/raw_ostream.h" -
Which are needed because we are writing a Pass, @@ -240,53 +242,66 @@ href="http://llvm.org/doxygen/classllvm_1_1Function.html">Function's, and we will be doing some printing.
Next we have:
-+ ++++using namespace llvm; -
... which is required because the functions from the include files -live in the llvm namespace. -
+live in the llvm namespace.Next we have:
-++++namespace { -
... which starts out an anonymous namespace. Anonymous namespaces are to C++ what the "static" keyword is to C (at global scope). It makes the -things declared inside of the anonymous namespace only visible to the current +things declared inside of the anonymous namespace visible only to the current file. If you're not familiar with them, consult a decent C++ book for more information.
Next, we declare our pass itself:
-+++struct Hello : public FunctionPass { -+
This declares a "Hello" class that is a subclass of FunctionPass. The different builtin pass subclasses are described in detail later, but for now, know that FunctionPass's operate a function at a +href="#FunctionPass">FunctionPass's operate on a function at a time.
-- static char ID; - Hello() : FunctionPass(ID) {} -
+
+ static char ID; + Hello() : FunctionPass(ID) {} ++
This declares pass identifier used by LLVM to identify pass. This allows LLVM to -avoid using expensive C++ runtime information.
+This declares pass identifier used by LLVM to identify pass. This allows LLVM +to avoid using expensive C++ runtime information.
-++++} // end of anonymous namespace +virtual bool runOnFunction(Function &F) { - errs() << "Hello: " << F.getName() << "\n"; + errs() << "Hello: "; + errs().write_escaped(F.getName()) << "\n"; return false; } }; // end of struct Hello -
We declare a "runOnFunction" method, which overloads an abstract virtual method inherited from FunctionPass. This is where we are supposed to do our thing, so we just print out our message with the name of each function.
-- char Hello::ID = 0; -
+char Hello::ID = 0; ++
We initialize pass ID here. LLVM uses ID's address to identify pass so +
We initialize pass ID here. LLVM uses ID's address to identify a pass, so initialization value is not important.
-- static RegisterPass<Hello> X("hello", "Hello World Pass", - false /* Only looks at CFG */, - false /* Analysis Pass */); -} // end of anonymous namespace -
+static RegisterPass<Hello> X("hello", "Hello World Pass", + false /* Only looks at CFG */, + false /* Analysis Pass */); ++
Lastly, we register our class Hello, -giving it a command line -argument "hello", and a name "Hello World Pass". -Last two arguments describe its behavior. -If a pass walks CFG without modifying it then third argument is set to true. -If a pass is an analysis pass, for example dominator tree pass, then true -is supplied as fourth argument.
+Lastly, we register our class Hello, +giving it a command line argument "hello", and a name "Hello World +Pass". The last two arguments describe its behavior: if a pass walks CFG +without modifying it then the third argument is set to true; if a pass +is an analysis pass, for example dominator tree pass, then true is +supplied as the fourth argument.
As a whole, the .cpp file looks like:
-++++ +char Hello::ID = 0; +static RegisterPass<Hello> X("hello", "Hello World Pass", false, false); +#include "llvm/Pass.h" #include "llvm/Function.h" #include "llvm/Support/raw_ostream.h" @@ -332,24 +350,26 @@ is supplied as fourth argument. Hello() : FunctionPass(ID) {} virtual bool runOnFunction(Function &F) { - errs() << "Hello: " << F.getName() << "\n"; + errs() << "Hello: "; + errs().write_escaped(F.getName()) << '\n'; return false; } + }; - - char Hello::ID = 0; - static RegisterPass<Hello> X("hello", "Hello World Pass", false, false); } - -
Now that it's all together, compile the file with a simple "gmake" command in the local directory and you should get a new file "Debug+Asserts/lib/Hello.so" under the top level directory of the LLVM source tree (not in the local directory). Note that everything in this file is -contained in an anonymous namespace: this reflects the fact that passes are self -contained units that do not need external interfaces (although they can have -them) to be useful.
+contained in an anonymous namespace — this reflects the fact that passes +are self contained units that do not need external interfaces (although they can +have them) to be useful.