LLVM Pass

Writing an LLVM Pass

LLVM Pass 是整个 LLVM 架构的重要组成部分。Passes 主要工作就是对代码进行优化工作,如果要进行优化工作,自然少不了对代码的分析,所以 Passes 自然也负责一些对代码的分析工作。

每个 Pass 都有自己的功能,可以把每个 Pass 看成一个小模块,这些小模块可以单独工作,完成一个简单的任务,当然这些小模块也可以组合起来,共同完成一个比较复杂的任务。这样做的话,使整个 LLVM 的架构变得很灵活。

LLVM 给我们提供一个 Pass 类,并给我们提供了一些 Pass 类的子类。如果我们要写自己的 Pass,我们可以根据我们的目标去合理的选择继承其中的类。自然我们就需要对这些类有比较深入的了解。这点儿目前我还在学习。

下面我们通过仿写一个最简单的样例来简单说明下,如何自己写一个 Pass。以跑通流程为主。

创建文件夹

首先我们到 llvm/lib/Transforms 目录下新建一个文件夹 MyHello。

mkdir MyHello

MyHello.cpp

创建 MyHello.cpp,内容如下。

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
  struct MyHello : public FunctionPass {
    static char ID;
    MyHello() : FunctionPass(ID) {}

    bool runOnFunction(Function &F) override {
      errs() << "Hello: ";
      errs().write_escaped(F.getName()) << '\n';
      return false;
    }
  }; // end of struct Hello
}  // end of anonymous namespace

char MyHello::ID = 0;
static RegisterPass X("myhello", "My Hello World Pass",
                             false /* Only looks at CFG */,
                             false /* Analysis Pass */);

编写 CMakeLists.txt

我们要使用 cmake 工具得到 Makefile 文件,所以我们这里要编写一个 CMakeLists.txt 文件。文件内容如下。

add_llvm_loadable_module( LLVMMyHello
  MyHello.cpp
  )

之后,我们要在 Transforms/ 目录下的 CMakeLists.txt 文件中添加我们创建的 MyHello 子目录。添加方式如下。

add_subdirectory(MyHello)

至此,Pass 的源代码就写完了。

编译、安装

接下来,我们要切到 build 目录下,如果你不知道 bulid 目录是指哪里,可以参考安装 LLVM 和 Clang。接着执行以下三步(请参考安装 LLVM 和 Clang 教程)。执行完成后,会看到 build/lib 目录下多了一个 LLVMMyHello.so 文件。到此我们就得到了自己 Pass。

cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86" ../llvm
make -j 12
sudo make install

执行测试

首先任意找一个位置,写一个测试文件 feature.cpp。

#include 
#include 

class MyClass {
    public:
        std::string s ="Hello, world\n"; // Non-static data member initializer
};

int main() {
    std::cout << MyClass().s;
}

接着,使用 Clang 编译得到 .ll 或 .bc 文件。

clang++ -Wall -g -O3 -emit-llvm -std=c++11 -stdlib=libc++ feature.cpp -S -o feature.ll

最后我们使用测试我们的 Pass。

 opt -load LLVMMyHello.so -myhello < feature.ll > /dev/null

到此,就大致了解了写一个 Pass 的基本流程,更详细的内容可以参考官方文档。

你可能感兴趣的:(LLVM Pass)