基于LLVM-自定义Pass

首先我们要先去编写一个 FuncBlockCount.c文件

#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
//引入llvm命名空间,可以让其实用LLVM当中的函数
using namespace llvm;

//创建一个匿名的命名空间
namespace  {

    //声明Pass
    struct FuncBlockCount : public FunctionPass
    {
        //声明Pass的标识符,会被LLVM用作识别Pass
        static char ID;
        FuncBlockCount() : FunctionPass(ID){}

        //其实就是FunctionPass的一个虚函数,这里对它进行了实现。一个FunctionPass的子类要想做一些实际的工作,就必须对这个虚函数进行实现。
        bool runOnFunction(Function &F) override {
            //errs()是一个LLVM提供的C++输出流,我们可以用它来输出到控制台
            errs() << "Function "<<F.getName()<<'\n';
            //函数返回false说明它没有改动函数F。之后,如果我们真的变换了程序,我们需要返回一个true。
            return false;
        }
    };
}
//初始化Pass ID
char FuncBlockCount::ID = 0;
//需要注册Pass、填写名称和命令行参数
static RegisterPass<FuncBlockCount> X("funcblockcount","Function Block Count",false,false);//,最后两个参数描述了它的行为:如果一个pass不修改CFG,那么第三个参数将被设置为true;如果pass是一个分析传递,例如dominator树(支配树)传递,则true作为第四个参数提供。

然后我们再去使用g++ FuncBlockCount.cpp -fPIC -g -Wall -Wextra -std=c++11 `llvm-config --cxxflags ` -shared -o FuncBlockCount.so 命令去编译,就能编译出.so文件

我们去使用的时候直接输入下面的命令就可以了其中funcblockcount就是我们注册Pass时候的设置的命令行参数

使用opt -load /home/parallels/Desktop/FuncBlockCount/FuncBlockCount.so -funcblockcount sample.ll 命令去运行新的Pass,输出结果如下所示

这里写图片描述

我们的sample.c文件如下所示

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;
}

然后使用clang -O0 -S -emit-llvm sample.c -o sample.ll 就可以将C语言测试代码编译为LLVM IR的形式

综上所述其实就是opt命令行工具会动态的去加载动态链接库,以运行Pass,之后Pass会遍历每一个函数,输出其函数名,但未对IR做任何改动

猜你喜欢

转载自blog.csdn.net/zcmuczx/article/details/80856655