LLVM 初探(1) 简单Pass编写

环境配置

llvm版本4.0.0,使用官网的prebuilt binary安装

跟着llvm-cookbook的教程做了下,发现教程那种方法需要重新编译llvm源码

于是上网搜了下,找到一个repo llvm-pass-skeleton,可以在不重新编译全部源码的情况下生成Pass

FuncBlockCount Pass

Pass源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

namespace {
struct FuncBlockCount : public FunctionPass {
static char ID;
FuncBlockCount() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
errs() << "Function " << F.getName() << '\n';
return false;
}
};
}
char FuncBlockCount::ID = 0;
static RegisterPass<FuncBlockCount> X("funcblockcount", "Function Block Count", false, false);

编译出libFuncBlockCountPass. so

创建一个文件 sample.c

1
2
3
4
5
6
7
8
9
10
11
int foo(int n,int m) {
int sum = 0;
int c0;
for(c0 = n; c0 >0 ;c0--){
int c1 = m;
for(; c1>0 ; c1--) {
sum += c0 > c1 ?1:0;
}
}
return sum;
}

使用

1
clang -O0 -S -emit-llvm sample.c -o sample.ll

生成IR

然后用opt运行Pass,结果如下,输出函数名字

FuncBlockCount Pass v2

源码如下

这里提一下getAnalysisUsage这个函数,在llvm cookbook里面并没有提到,但是如果没有加这个函数的话,后面用opt跑的时候会报错

至于这个函数的作用,可以看【LLVM】Pass之间的依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/LoopInfo.h"
using namespace llvm;

namespace {
struct FuncBlockCount : public FunctionPass {
static char ID;
void countBlocksInLoop(Loop* L,unsigned nest){
unsigned num_Blocks = 0;
Loop::block_iterator bb;
for(bb = L->block_begin(); bb!=L->block_end();++bb)
num_Blocks++;
errs()<<"Loop level "<<nest<<" has "<<num_Blocks<<" blocks\n";
std::vector<Loop*> subLoops = L->getSubLoops();
Loop::iterator j,f;
for( j = subLoops.begin(), f = subLoops.end(); j != f; ++j)
countBlocksInLoop(*j, nest+1);
}
FuncBlockCount() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
LoopInfo* LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
errs() << "Function " << F.getName() << '\n';
for(Loop *L : *LI)
countBlocksInLoop(L, 0);
return false;
}
virtual void getAnalysisUsage(AnalysisUsage& AU) const override {
AU.addRequired<LoopInfoWrapperPass>();
}
};

}
char FuncBlockCount::ID = 0;
static RegisterPass<FuncBlockCount> X("funcblockcount", "Function Block Count", false, false);

修改sample.c源码为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main(int argc, char **argv) {  
int i, j, k, t = 0;
for(i = 0; i < 10; i++) {
for(j = 0; j < 10; j++) {
for(k = 0; k < 10; k++) {
t++;
}
}
for(j = 0; j < 10; j++) {
t++;
}
}
for(i = 0; i < 20; i++) {
for(j = 0; j < 20; j++) {
t++;
}
for(j = 0; j < 20; j++) {
t++;
}
}
return t;
}

使用

1
clang –O0 –S –emit-llvm sample.c –o sample.ll

来生成IR

输出的结果

opcodeCounter

源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#define DEBUG_TYPE "opcodeCounter"
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
using namespace llvm;

namespace {

struct CountOpcode: public FunctionPass{
std::map<std::string, int> opcodeCounter;
static char ID;
CountOpcode() : FunctionPass(ID) {}
virtual bool runOnFunction (Function& F){
llvm::outs() << "Function " <<F.getName() << "\n";
for( Function::iterator bb = F.begin(), e = F.end();bb!=e;++bb){
for(BasicBlock::iterator i = bb->begin(),ee = bb->end();i!=ee;++i){
if(opcodeCounter.find(i->getOpcodeName()) == opcodeCounter.end()){
opcodeCounter[i->getOpcodeName()] = 1;
}else{
opcodeCounter[i->getOpcodeName()] += 1;
}
}
}
std::map<std::string, int>::iterator i = opcodeCounter.begin();
std::map<std::string, int>::iterator e = opcodeCounter.end();
while(i!=e){
llvm::outs()<<i->first <<": "<<i->second<<"\n";
i++;
}
llvm::outs()<<"\n";
opcodeCounter.clear();
return false;
}
};

}

char CountOpcode::ID = 0;
static RegisterPass<CountOpcode> X("opcodeCounter","Count the number of opcode in a functions");

这个Pass是统计各个opcode的数量

测试代码 testcode.c

1
2
3
4
5
6
7
8
9
10
11
int func(int a,int b){
int sum = 0;
int iter;
for(iter = 0; iter<a;iter++) {
int iter1;
for(iter1 = 0; iter1<b;iter1++){
sum += iter> iter1 ? 1: 0;
}
}
return sum;
}

运行结果