zoukankan      html  css  js  c++  java
  • LLVM使用其他Pass的结果

    之前的工作一直集中在clang中,最近有点空闲时间,又重新熟悉了一下Pass的书写过程。(参考LLVM CookBook和http://llvm.org/docs/WritingAnLLVMPass.html)

    比如要实现一个基本的读取函数名的Pass,比如FuncBlockCount.cpp

    #include "llvm/Pass.h"
    #include "llvm/IR/Function.h"
    #include "llvm/Support/raw_ostream.h"
    
    // ./opt load ../lib/FuncBlockCount.so -funcblockcount sample.ll
    using namespace llvm;
    namespace{
        struct FuncBlockCount : public FunctionPass {
            static char ID;
            FuncBlockCount() : FunctionPass(ID) { }
            bool runOnFunction(Function& F) override {
                errs() << "Function" << F.getName() << '
    ';
                return false;
            }
        };
        char FuncBlockCount::ID = 0;
        static RegisterPass<FuncBlockCount> X("funcblockcount", "Function Block Count", false, false);
    }

    大概过程就是,实现一个类(在C++中,struct和class只是有一些访问控制的不同,具体可以百度),这个类需要继承至各种Pass,一般都是从FunctionPass作为入口,如果你对全局信息有需求的话,建议可以考虑ASTModule。

    然后需要一个ID,其实这个ID不是特别关键,然后是注册Pass,有4个参数,第一个是执行的时候调用的命令,第二个是介绍。

    看起来非常简单,就是三步:

    1.写一个带有runOnxxx的类,这个类需要继承至Pass

    2. 给一个初始ID

    3.注册Pass

    花几分钟读一下代码,其实发现最简单的Pass其实就是这么简单

    写好了代码,下面介绍如何进行编译和链接,由于现在llvm主要依靠cmake来生成Makefile文件,所以要想这个Pass能运行,需要在合适的地方写CMakeList.txt文件。

    这里,为了简化,介绍最简单的方式。在your_src_dir/lib/Transforms/下,新建一个文件夹,我这里新建的是FuncBlockCount,如果一切都正常的话,下边一般会有Scalar,Vectorize,Hello等这几个文件夹

    在Transforms目录下的CMakeLists.txt中添加

    add_subdirectory(FuncBlockCount)
    

     切换到新建的FuncBlockCount下,将刚才FuncBlockCount.cpp复制到下边,然后新建CMakeLists.txt,内容如下:

    add_llvm_loadable_module( FuncBlockCount
      FuncBlockCount.cpp
    
      DEPENDS
      intrinsics_gen
     )
    

     然后重新cmake,make就可以生成FuncBlockCount.so文件了

    写一个简单的sample.c测试一下

    int foo(int n, int m)
    {
            int sum = 0;
            sum = n + m;
            return sum;
    }

    使用-emit-llvm生成ll文件

    ./clang -O0 -S -emit-llvm sample.c -o sample.ll
    

     再用opt加载就可以了

    ./opt -load ../lib/FuncBlockCount.so -funcblockcount sample.ll
    

     可以看到,成功的输出了

    Functionfoo

    这里,我们已经成功地完成了一个Pass,下面我们希望能做一点有挑战的事情,在我们的Pass中使用其他Pass,这里我们使用LoopInfoWrapperPass,这是一个分析循环信息的Pass

    在FuncBlockCount.cpp中插入

    namespace {
      // Hello2 - The second implementation with getAnalysisUsage implemented.
      struct GetLoopInfo2 : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
        GetLoopInfo2() : FunctionPass(ID) {}
    
        bool runOnFunction(Function &F) override {
          LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
          errs() <<"Function "<< F.getName() << '
    ';
          for(Loop *L : *LI)
          {
              countBlocksInLoop(L, 0);
          }
          return false;
        }
    
        // We don't modify the program, so we preserve all analyses.
        void countBlocksInLoop(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
    ";
          std::vector<Loop*> subLoops =L->getSubLoops();
          Loop::iterator j, f;
          for(j = subLoops.begin(), f= subLoops.end();j!=f;++j)
              countBlocksInLoop(*j, nest+1);
        }
        
        void getAnalysisUsage(AnalysisUsage &AU) const override {
          AU.addRequired<LoopInfoWrapperPass>();
          //AU.setPreservesAll();
        }
      };
      
    }
    char GetLoopInfo2::ID = 0;
    static RegisterPass<GetLoopInfo2> Y("getLoopInfo2", "Get LoopInfo2");

    这里其他部分变化不大,对于结构方面,添加了一个新的函数getAnalysisUsage,这个函数重载了原来Pass中的对应函数,告诉Pass管理器,我们的Pass依赖于LoopInfoWrapperPass

    重新编译生成后,我们新写一个测试例子,刚才的例子太简单了,都没有循环结构,完全无法体现出这个Pass的作用

    sample1.cpp

    //    ./opt load ../lib/FuncBlockCount.so -getLoopInfo2 sample1.ll
    int 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++;
            }
        }
        return t;
    }

    生成sample1.ll文件后,使用如下命令

    ./opt -load ../lib/FuncBlockCount.so -getLoopInfo2 sample1.ll -disable-output -debug-pass=Structure
    

     成功可以看到输出:

    如果不使用调试pass的方式,就是去掉-debug-pass选项,只有

    但是,如果你忘记了添加对LoopInfoWrapperPass的依赖,那么就会呈现类似的报错信息

  • 相关阅读:
    科学开源项目 : 建立一个 新的 光衍射 模型
    光不是电磁波 摩擦力不是电磁力
    收录一篇 贝尔不等式 的 文章
    数学家 程序员 哲学家 艺术家
    论 数学 的 工具性
    数学 怎么用?
    随便说说 广义相对论 的 时间膨胀
    逻辑物理学 : 光子 有 质量 吗 ?
    我对 “光子有质量 , 引力对光子有作用” 存疑
    收录一些 高等数学 的 文章
  • 原文地址:https://www.cnblogs.com/jourluohua/p/11108461.html
Copyright © 2011-2022 走看看