官网地址 :https://llvm.org/docs/WritingAnLLVMPass.html#introduction-what-is-a-pass
一、创建文件
1、项目结构为: llvm-project/lib/Transforms/Hello
2、在Transforms下创建CMakeLists.txt
3、在Hello文件夹下创建Hello.cpp 和 CMakeLists.txt
4、在Hello文件夹下创建input.c
二、输入代码
1、在Hello/CMakeLists.txt 中输入
add_llvm_library( LLVMHello MODULE
Hello.cpp # CPP文件名
PLUGIN_TOOL
opt
)
2、在Transforms/CMakeLists.txt中 输入
add_subdirectory(Hello)
3、在Hello/Hello.cpp中输入
#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 Hello : public FunctionPass {
static char ID;
Hello() : 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 Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass", # "hello"注册名
false /* Only looks at CFG */,
false /* Analysis Pass */);
static RegisterStandardPasses Y(
PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) { PM.add(new Hello()); });
4、在input.c中输入
int foo(int a,int b)
{
return a>b?a:b;
}
三、编译
1、先把cpp文件编译成so文件
clang `llvm-config --cxxflags` -Wl,-znodelete -fno-rtti -fPIC -shared Hello.cpp -o LLVMHello.so `llvm-config --ldflags`
其中 LLVMHello.so 是自己取的名字
2、clang input.c -emit-llvm -S -o input.ll # 生成.ll 文件 -- 人能看懂的
3、clang -c -emit-llvm input.c -o input.bc #生成.bc文件 -- 二进制文件 ,人看不懂的
4、opt -enable-new-pm=0 -load ./LLVMHello.so -hello input.bc -o /dev/null #编译运行.bc文件 ,查看测试结果 ,结果输出为 foo(函数名)
5、opt -enable-new-pm=0 -load ./LLVMHello.so -hello input.ll # 编译运行.ll文件 ,其中hello 为cpp文件中注册名,结果输出为foo(函数名)