zoukankan      html  css  js  c++  java
  • LLVM Pass 简介(1)

    LLVM Pass框架是LLVM系统的重要组成部分,因为LLVM Pass负责LLVM编译器绝大部分的工作。 构成编译器的Pass执行各种转换和优化,在转换中使用的前边Pass的分析结果。所有的类实现都必须继承至Pass基类,一般来说可供使用的Pass类型一般包括 ModulePass , CallGraphSCCPassFunctionPass , or LoopPass, or RegionPass 这几个类。Function/Module/Loop/Region这几个Pass都不难理解,主要是 CallGraphSCCPass这个,CallGraph顾名思义,SCC(Strongly-Connected-Component)是强联通分量,这个从llvm/ADT/SCCIterator.h中定义的scc_iterator定义中可以得到,是一个DFS遍历顺序。

    下边介绍了一段对CallGraphSCC中的runOnFunction进行遍历的代码:

     1  std::stack<scc_iterator<Function*> > sccs;
     2     for(scc_iterator<Function*> SCCI=scc_begin(F),SCCE=scc_end(F);SCCI!=SCCE;++SCCI)
     3         sccs.push(SCCI);
     4 
     5     //按照顺序遍历强连通分量(SCC)
     6     unsigned sccNum=0;
     7     while(!sccs.empty()){
     8         scc_iterator<Function*> SCCI=sccs.top();
     9         sccs.pop();
    10         std::vector<BasicBlock*> & nextSCC=*SCCI;
    11         errs()<<"
     SCC#"<<++sccNum<<":";
    12          //遍历SCC中的块(DFS顺序 )
    13         std::vector<BasicBlock*>::const_iterator I=nextSCC.begin(),E=nextSCC.end();
    14         for(--E,--I;E!=I;--E){
    15             errs()<<(*E)->getName()<<",";
    16         }
    17      }
    View Code

    下边介绍如何添加一个最简单的Pass。该Hello pass位于lib/Transform/Hello文件夹下。

    添加在lib/Transforms/CMakeLists.txt:

    add_subdirectory(Hello)
    

    在Hello文件夹下新建CMakeLists.txt,内容如下:

    add_llvm_library( LLVMHello MODULE
      Hello.cpp
    
      PLUGIN_TOOL
      opt
      )
    

     新建Hello.cpp,内容

    //===- Hello.cpp - Example code from "Writing an LLVM Pass" ---------------===//
    //
    //                     The LLVM Compiler Infrastructure
    //
    // This file is distributed under the University of Illinois Open Source
    // License. See LICENSE.TXT for details.
    //
    //===----------------------------------------------------------------------===//
    //
    // This file implements two versions of the LLVM "Hello World" pass described
    // in docs/WritingAnLLVMPass.html
    //
    //===----------------------------------------------------------------------===//
    
    #include "llvm/ADT/Statistic.h"
    #include "llvm/IR/Function.h"
    #include "llvm/Pass.h"
    #include "llvm/Support/raw_ostream.h"
    #include <map>
    #include <string>
    #include "llvm/IR/Instructions.h"
    #include "llvm/IR/InstVisitor.h"
    #include "llvm/ADT/DepthFirstIterator.h"
    #include "llvm/ADT/SmallPtrSet.h"
    #include "llvm/ADT/SmallVector.h"
    #include "llvm/IR/InstIterator.h"
    #include "llvm/IR/Instructions.h"
    #include "llvm/IR/IntrinsicInst.h"
    using namespace llvm;
    
    #define DEBUG_TYPE "hello"
    
    STATISTIC(HelloCounter, "Counts number of functions greeted");
    namespace {
      // Hello - The first implementation, without getAnalysisUsage.
      struct Hello : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
        Hello() : FunctionPass(ID) {}
    
        bool runOnFunction(Function &F) override {
          ++HelloCounter;
          errs() << "Hello: ";
          errs().write_escaped(F.getName()) << '
    ';
          return false;
        }
      };
    }
    
    char Hello::ID = 0;
    static RegisterPass<Hello> X("hello", "Hello World Pass");

    这里说点不一样的,这是旧版本的LLVM中的Pass添加方式,现在只有部分Machine部分采用这种Pass管理方式,新的PassManager使用方式https://llvm.org/docs/NewPassManager.html

    在正常编译后,build/bin/目录下出现了clang/llvm-dis等各种binary文件,而build/lib目录下可以找到LLVMHello.so,是刚才生成的。

    采用的测试代码hello.c

     1 int foo(int a, int b, int *c) {
     2     int ret = 0;
     3     if (a > b) {
     4         ret = a;
     5     } else {
     6         ret = b;
     7     }
     8     for (int temp = 0; temp < 100; ++temp) {
     9         *c = (*c + temp);
    10     }
    11     return ret;
    12 }
    13 
    14 
    15 int main() {
    16     int a = 1, b = 2;
    17     int c = 0;
    18     int d = foo(a, b, &c);
    19     return 0;
    20 }

    使用./bin/clang -c -emit-llvm hello.c -o hello.bc 生成bc文件

     opt -load lib/LLVMHello.so -hello < hello.bc > /dev/null 进行测试

    测试结果如图:

    本教程来自于:https://llvm.org/docs/WritingAnLLVMPass.html

    http://stackoverflow.com/questions/18650999/topological-sorting-of-basic-blocks-in-llvm

  • 相关阅读:
    标准粒子群算法(PSO)
    Java开发中的23种设计模式详解
    分布式事务
    sjk 分页
    有用吗2
    有用吗1
    存储过程
    在虚拟机Linux安装Redis
    ajax调用WebAPI添加数据
    SVN安装和使用(简单版)
  • 原文地址:https://www.cnblogs.com/jourluohua/p/14556147.html
Copyright © 2011-2022 走看看