环境配置
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.c1
2
3
4
5
6
7
8
9
10
11int 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 | #include "llvm/Pass.h" |
修改sample.c源码为1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22int 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 | #define DEBUG_TYPE "opcodeCounter" |
这个Pass是统计各个opcode的数量
测试代码 testcode.c
1 | int func(int a,int b){ |
运行结果