本文由博主原创,转载请注明出处(保證文章完整性,保留此处和链接):
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文件。
接著來測試一下我們的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