参考书:《LLVM Cookbook中文版》
一个pass可能会依赖其他pass来分析或获取数据,所以这里我们依据 llvm学习日记九:编写一个基础pass 这一小节继续往下。
- FnArgCnt.cpp:
我们这里新增功能是对循环中的基本块进行计数;
getAnalysis 指定要使用的其他pass
#include "llvm/IR/Function.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/LoopInfo.h"
using namespace llvm;
namespace {
struct FnArgCnt : public FunctionPass {
static char ID;
FnArgCnt() : FunctionPass(ID) {
}
void countblockinloop(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) countblockinloop(*j, nest+1);
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<LoopInfoWrapperPass>();
}
virtual bool runOnFunction(Function &F) {
errs() << "FnArgCnt --- ";
errs() << F.getName() << "\n";
for (auto& B : F) {
for (auto& I : B) {
if(CallInst* call_inst = dyn_cast<CallInst>(&I)) {
Function* fn = call_inst->getCalledFunction();
StringRef fn_name = fn->getName();
errs() << fn_name << " : " << call_inst->getArgOperand(0) << "(getArgOperand)\n";
for(auto arg = fn->arg_begin(); arg != fn->arg_end(); ++arg) {
if(auto* ci = dyn_cast<ConstantInt>(arg))
errs() << ci->getValue() << "(getValue)\n";
errs() << *arg << "\n";
}
}
}
}
LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
for(Loop *L : *LI){
countblockinloop(L, 0);
}
return false;
}
};
}
char FnArgCnt::ID = 0;
static RegisterPass<FnArgCnt> X("fnargcnt", "Function Argument Count Pass", false, false);
- 编译:
直接make就行
image.png
- 创建一个sample.c
#include <stdio.h>
int main(int argc,char **argv) {
int i, j, k, t;
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(i=0;i<20;i++){
t++;
}
}
return 0;
}
- opt 加载
./bin/opt -load ./lib/LLVMFnArgCnt.dylib -fnargcnt <sample.bc> /dev/null
运行有一个问题是:
Assertion failed: (ResultPass && "getAnalysis*() called on an analysis that was not " "'required' by pass!")
怎么解决的呢:
就是实现函数getAnalysisUsage,上边代码已经实现了:
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<LoopInfoWrapperPass>();
}
运行OK:
image.png
- pass调试选项: -debug-pass=Structure
image.png