Unfortunately, plug-ins are dynamically linked in LLVM which excludes this approach on Windows (without relying on Cygwin). For all my searching I was not able to find instructions on integrating a pass directly with the opt tool but I needed to support custom passes on Windows without using Cygwin. Mostly as a note for myself, I am listing here the steps I used to create my own custom pass as part of the opt tool; hopefully they will be useful for others as well.
I've followed as best I could the format used by existing infrastructure within LLVM. This does not mean that I have not missed something critical or what I have provided adheres to LLVM policy and/or standards.
N.B. These examples assume you are:
- already familiar with writing a custom pass as described by the LLVM documentation
- capable of understanding Makefiles and how to modify them to suit your needs
- using llvm-3.0 (that is the version used in these examples)
These examples will build a pass named mypass which will simply print out all function names. This pass will be part of the Custom library (also created here).
The first step is to create a new directory named Custom under llvm/lib/Transforms. This is where all passes for the new library will live. Create a very simple function pass and place it in this new directory - I used the following (MyPass.cpp)
The first step is to create a new directory named Custom under llvm/lib/Transforms. This is where all passes for the new library will live. Create a very simple function pass and place it in this new directory - I used the following (MyPass.cpp)
#define DEBUG_TYPE "mypass"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/Custom.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
struct MyPass : public FunctionPass {
static char ID;
MyPass() : FunctionPass(ID) {
initializeMyPassPass(*PassRegistry::getPassRegistry());
}
/*
* Just print the function name
*/
bool runOnFunction(Function &F) {
bool Changed = false;
errs().write_escaped(F.getName()) << "\n";
return Changed;
}
};
}
char MyPass::ID = 0;
INITIALIZE_PASS(MyPass, "mypass", "Print all function names",
false, false)
FunctionPass *llvm::createMyPassPass() {
return new MyPass();
}
#include "llvm/InitializePasses.h"
#include "llvm-c/Initialization.h"
using namespace llvm;
/// initializeCustom - Initialize all passes in the Custom library
void llvm::initializeCustom(PassRegistry &Registry) {
initializeMyPassPass(Registry);
}
/// LLVMInitializeCustom - C binding for initializeCustom.
void LLVMInitializeCustom(LLVMPassRegistryRef R) {
initializeCustom(*unwrap(R));
}
LEVEL = ../../..
LIBRARYNAME = LLVMCustom
BUILD_ARCHIVE = 1
include $(LEVEL)/Makefile.common
add_llvm_library(LLVMCustom
MyPass.cpp
Custom.cpp
)
First, you need to define a way for LLVM to create an instance of your pass. Save the following as Custom.h in llvm/include/llvm/Transforms/
#ifndef LLVM_CUSTOM_H
#define LLVM_CUSTOM_H
namespace llvm {
FunctionPass *createMyPassPass();
}
#endif
void initializeCustom(PassRegistry&);
void initializeMyPassPass(PassRegistry&);
#include "llvm/Transforms/Custom.h"
// This part must reside in the constructor of struct ForcePassLinking
(void) llvm::createMyPassPass();
- llvm/lib/Transforms/Makefile
- llvm/lib/Transforms/CMakeLists.txt
- llvm/tools/opt/Makefile (add link dependency for 'custom')
- llvm/tools/opt/CMakeLists.txt (add link dependency for 'custom')
- llvm/tools/bugpoint/Makefile (add link dependency for 'custom')
- llvm/tools/bugpoint/CMakeLists.txt (add link dependency for 'custom')
initializeCustom(Registry);
-mergereturn - Unify function exit nodes
-module-debuginfo - Decodes module-level debug info
-mypass - Print all function names
-no-aa - No Alias Analysis (always returns 'may' alias)
-no-path-profile - No Path Profile Information
This seems to be right on the money, Kudos!
ReplyDeleteWhops, seemed to have encountered a problem:
ReplyDeleteLINK : fatal error LNK1104: cannot open file '..\..\lib\Debug\LLVMCustom.lib'
Help is much appreciated
You may want to check your project configuration to ensure that lib is added to the linker dependencies. As far as I remember this worked for me by simply running build clean and then a full rebuild. If your make files are properly filled out there should not be a problem.
ReplyDeleteI tried to follow your tutorial, but I failed, I got the following message after compiling everything:
ReplyDeleteError 1 error LNK2019: unresolved external symbol "class llvm::FunctionPass * __cdecl llvm::createMyPassPass(void)" (?createMyPassPass@llvm@@YAPAVFunctionPass@1@XZ) referenced in function "public: __thiscall `anonymous namespace'::ForcePassLinking::ForcePassLinking(void)" (??0ForcePassLinking@?A0x8aef65a6@@QAE@XZ) cc1_main.obj clang
As you can see, I have clang on my LLVM.sln, the error comes from this project. Any hint?
It looks as if the linker is having trouble finding your definition of createMyPassPass. In the examples above I have that definition in MyPass.cpp (in llvm/lib/Transforms). Have you checked that that definition exists? Perhaps there is a spelling error?
ReplyDeleteI still get llvm-config error unknown component name
ReplyDelete