基于LLVM-分析Pass的制作

分析Pass在实际不修改IR的情况下提供关于IR的更高级的信息,而这些信息可以被其他的分析Pass使用来计算其结果,只要一个分析的Pass计算得出了结果,这个计算结果可以被不同的Pass拿来多次使用,直到一个Pass改变了这个IR

我们先编写下我们需要去进行测试的代码

int func(int a,int b)
{
    int sum=0;
    int iter;
    for (iter = 0; iter< a; iter++) {
        int iter1;
        for (iter1=0; iter<b; iter1++) {
            sum+=iter>iter1 ? 1:0;
        }
    }
    return sum;
}

然后我们去利用clang -c -emit-llvm testcode.c -o testcode.bc,去将其转换为.bc文件,也就是字节码文件

之后我们就开始进行编写分析Pass

#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  {

    //此分析Pass是在函数层级上使用的,作用于程序当中的每一个函数,因此,我们在声明CountOpcodes:public FunctionPass结构的时候基础了FunctionPass函数
    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循环遍历函数所有的基本块
            for (Function::iterator bb = F.begin(), e=F.end();bb!=e;++bb ) {
                //第二层for循环遍历基本块当中的每一条指令
                for (BasicBlock::iterator i = bb->begin(),e=bb->end(); i!=e;++i) {
                    //判断在map当中有没有过指令,如果没有就直接设置为1
                    //使用find,返回的是被查找元素的位置,没有则返回map.end()
                    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();
                        //函数没有修改测试代码当中的任何东西,所以返回false
                        return false;
                        }

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

紧接着我们再通过下面的命令去生成.so动态库

 g++ opcodeCount.cpp -fPIC -g -Wall -Wextra -std=c++11 `llvm-config --cppflags ` -shared -o opcodeCount.so 

最后通过下面的命令进行链接

 opt -load opcodeCount.so -opcodeCounter -disable-output testcode.bc

结果如下所示

Function func
add: 3
alloca: 5
br: 8
icmp: 3
load: 10
ret: 1
select: 1
store: 8

猜你喜欢

转载自blog.csdn.net/ZCMUCZX/article/details/80861158