ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

开发和调试第一个 LLVM Pass

2019-02-05 18:56:43  阅读:323  来源: 互联网

标签:opt LLVM 6.0 编译 llvm Pass 调试 First


1. 下载和编译 LLVM

LLVM 下载地址 http://releases.llvm.org/download.html
目前最新版是 6.0.0,下载完成之后,执行 tar 解压 llvm 包:

tar -xzvf llvm-6.0.0.src.tar.xz

再下载 Clang 解压:

tar -xzvf cfe-6.0.0.src.tar.xz

将 cfe-6.0.0.src 目录复制到 llvm-6.0.0.src/tools,重命名为 clang。通过 brew 安装 cmake:

brew install cmake

然后在命令行下切换到 llvm-6.0.0.src 目录,新建 build 目录,切换到 build 目录执行 cmake 生成配置文件,命令如下:

mkdir build
cd build
cmake -G Xcode CMAKE_BUILD_TYPE="Debug" ..

执行完成之后,可以看到 Xcode 的工程文件 LLVM.xcodeproj,打开工程文件,会提示是否自动创建 Schemes,如图所示:

开发和调试第一个 LLVM Pass

点击 Manually Manage Schemes 手动创建,添加 ALL_BUILD,如图所示:

开发和调试第一个 LLVM Pass

然后在 Xcode 上进行编译,编译过程比如慢,可能得二十分钟到半小时左右,全部编译完文件会在 11G 左右。

2. 编写 Pass 代码

我们编写第一个 Pass 的功能很简单,只是输出程序中的每个方法名,操作步骤如下:

(1) 在 lib/Transforms 目录下新建一个文件夹,文件夹名称为 TestPass,在 TestPass 目录下创建文件 TestPass.cpp,代码如下:

//导入头文件
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;  //指定所使用的 LLVM 命名空间

namespace {

  //定义 First 类继承自 FunctionPass
  struct First : public FunctionPass {
    static char ID; // Pass ID
    First() : FunctionPass(ID) {}

    //定义 runOnFunction 重载继承父类的抽象虚函数
    bool runOnFunction(Function &F) override {

      //打印每个函数的名字
      errs() << "First: ";
      errs().write_escaped(F.getName()) << '\n';
      return false;
    }
  };
}

char First::ID = 0;  //初始化 Pass ID

//最后注册 FirstPass, 指定命令行参数为 First
static RegisterPass<First> X("First", "First Pass");

(2) 然后再在 lib/Transforms/TestPass 下新建 CMakeList.txt,编辑内容如下:

add_llvm_loadable_module( LLVMFirstPass
  FirstPass.cpp

  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )

(3) 在 lib/Transforms/CMakeLists.txt 添加 add_subdirectory(TestPass)

(4) 重新编译整个工程,添加 LLVMFirstPass 到 Scheme,如图:

开发和调试第一个 LLVM Pass

编译 LLVMFirstPass 成功之后,动态库保存在 build/Debug/lib/LLVMFirstPass.dylib。

3. 使用 opt 加载和调试 Pass

(1) 编写一段测试代码:

#include <stdio.h>

int test() {

        printf("test\n");
        return 0;
}
int main(){

        int num = 1;
        printf("main %d\n", num);
        test();
        return 0;
}

编译源文件,生成 Bitcode:

clang -emit-llvm -c test.c -o test.bc

(2) 在 Xcode 中将 opt 添加到 scheme,编辑 scheme 的启动参数,-load 参数指向 LLVMFirstPass.dylib,-First 参数就是刚才在源代码里注册的参数,如图所示:

开发和调试第一个 LLVM Pass

编译 opt 并运行起来,可以看到输出了程序的每个函数名称,并且前面还打印了 First 字符串,效果如下:

First: test
First: main
Program ended with exit code: 0

opt 编译成功保存在 build/Debug/bin/opt。也可以给 pass 的代码下断点,在 Xcode 上运行 opt 就可以调试 pass,效果如图:

开发和调试第一个 LLVM Pass

原文地址:https://www.exchen.net/开发和调试第一个-llvm-pass.html

标签:opt,LLVM,6.0,编译,llvm,Pass,调试,First
来源: http://blog.51cto.com/6095891/2348778

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有