llvm学习日记十一:调用其他pass

参考书:《LLVM Cookbook中文版》
一个pass可能会依赖其他pass来分析或获取数据,所以这里我们依据 llvm学习日记九:编写一个基础pass 这一小节继续往下。

  1. 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);


  1. 编译:
    直接make就行
image.png
  1. 创建一个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;
}


  1. 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
  1. pass调试选项: -debug-pass=Structure
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。