本文由博主原创,转载请注明出处(保證文章完整性,保留此处和链接):
IT 人生 (http://blog.csdn.net/robinblog/article/details/18265209)
對llvm的pass研究有一段時間了,第一個pass的編寫比較簡單,可以直接從官網獲取(第一個pass) ,我獲取去的pass如下test.cpp,pass的意義在此不作過多解釋:
test$ cat test.cpp #include "llvm/Pass.h" #include "llvm/Function.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { struct Test : public FunctionPass { static char ID; Test() : FunctionPass(ID) {} virtual bool runOnFunction(Function &F) { errs() << "Test: "; errs() << F.getName() << "\n"; return false; } }; } char Test::ID = 0; static RegisterPass<Test> X("test", "First test Pass");
這裡的重點是說下編譯環境的構建,官網上給的編譯方法是在llvm源碼之中,lib/Transforms/Test下構建的,採用了一個Makefile。每次編譯pass就要整體編譯一下llvm源碼,博主感覺餓很煩。博主提供一句話編譯自己Pass的方法,如下:
test$ `llvm-config --bindir`/clang -shared -fPIC `llvm-config --cxxflags` `llvm-config --ldflags` test.cpp -o libtest.so
其中,
·llvm-config --bindir·/clang 表示clang的位置。
`llvm-config --cxxflags` 能夠列出llvm中的編譯選項。
`llvm-config --ldflags` 能夠列出llvm中的連接選項。
-shared 和 -fPIC 是爲了生成so文件。
llvm-config 官方介紹
接著來測試一下我們的pass,測試文件如下HelloWorld.ll:
test$ cat HelloWorld.ll ; ModuleID = 'HelloWorld.c' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" target triple = "i386-pc-linux-gnu" @.str = private unnamed_addr constant [13 x i8] c"Hello LLVM!\0A\00", align 1 define void @p() nounwind { entry: %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0)) ret void } declare i32 @printf(i8*, ...) define void @f() nounwind { entry: call void @p() ret void } define i32 @main(i32 %argc, i8** %argv, i8** %envp) nounwind { entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 4 %envp.addr = alloca i8**, align 4 store i32 0, i32* %retval store i32 %argc, i32* %argc.addr, align 4 store i8** %argv, i8*** %argv.addr, align 4 store i8** %envp, i8*** %envp.addr, align 4 call void @f() ret i32 0 }
最後,來測試一下我們的pass,測試pass的方法如下:
test$ opt -load ./libtest.so -test < HelloWorld.ll > /dev/null Test: p Test: f Test: main