LLVM pass(WIP)

Build llvm

这里假设读者对 cmake 有一定的了解,并且会下载 llvm 源码,官网或者github上都能下到。官网有各个 release 版本的发布。
打算自己构建的话推荐是 github。

首先是建一个 build 目录,在其下运行如下命令,通过 cmake 生成 makefile。
更多的配置项请参阅 Building LLVM with CMake

cmake -G Ninja -DLLVM_BUILD_TESTS=OFF \
-DLLVM_TARGETS_TO_BUILD="AArch64;ARM;X86" \
-DCMAKE_INSTALL_PREFIX=/mnt2/usr/local \
-DCMAKE_BUILD_TYPE="Release" \
-DLLVM_PARALLEL_LINK_JOBS=8 ../llvm

这里选择了 Ninja 作为构建工具,之后运行 ninja 即可开始构建。
最后 ninja install 即可完成安装。

很有意思的是在安装生成的程序前可以重新指定安装目录。
通过 cmake -DCMAKE_INSTALL_PREFIX=/tmp/llvm -P cmake_install.cmake 完成。

what is pass

Embedding LLVM in your project

可参阅 Embedding LLVM in your project

cmake_minimum_required(VERSION 3.4.3)
project(SimpleProject)

find_package(LLVM REQUIRED CONFIG)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

# Set your project compile flags.
# E.g. if using the C++ header files
# you will need to enable C++11 support
# for your compiler.

include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})

# Now build our tools
add_executable(simple-tool tool.cpp)

# Find the libraries that correspond to the LLVM components
# that we wish to use
llvm_map_components_to_libnames(llvm_libs support core irreader)

# Link against LLVM libraries
target_link_libraries(simple-tool ${llvm_libs})

Developing LLVM passes out of source

Hello pass 的例子是在 llvm 源码树下进行构建的。有时候我们希望不在源码树下构建自己的pass,可以采用以下方式。
目录结构如下:

<project dir>/
    |
    CMakeLists.txt
    <pass name>/
        |
        CMakeLists.txt
        Pass.cpp
        ...

一级目录下的 CMakeLists.txt

find_package(LLVM REQUIRED CONFIG)
add_definitions(${LLVM_DEFINITIONS})
include_directories(${LLVM_INCLUDE_DIRS})

add_subdirectory(<pass name>)

二级目录下的 CMakeLists.txt

add_library(LLVMPassname MODULE Pass.cpp)

这和源码树下的有些差异,源码树下的可以拷贝 llvm/lib/Transforms/Hello/ 下的个 CMakeLists.txt 。采用了 llvm 内部定义的函数 add_llvm_library() 的方式进行添加。

Run an LLVM Pass Automatically with Clang1

可参阅 Run an LLVM Pass Automatically with Clang

官方给的教程通常需要以下步骤去调用我们自己的 Pass 文件。
首先生成 .bc 文件,然后使用 opt 命令调用我们的 Pass,如果继续优化的话走第 3 步,之后通过 llc 生成 汇编文件,最后用汇编器和链接器生成可执行文件。

1. clang -c -emit-llvm code.c -o code.bc                   / clang -O0 -S -emit-llvm code.c -o code.ll
2. opt -load mypass.so -mpass < code.bc > code_inst.bc     / > /dev/null
3. opt -O3 < code_inst.bc > code_opt.bc
4. llc code_opt.bc -o code_opt.s
5. use your favorite assembler and linkers to get the rest of the way to an executable

通过 LLVM 的 pass registry 进行 Pass 注册来使得我们的 pass 在加载 Pass 的 .so 文件时生效。

static void registerMyPass(const PassManagerBuilder &, PassManagerBase &PM) {
    PM.add(new MyPass());
}
static RegisterStandardPasses RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, registerMyPass);

这样就能使用下面熟悉的命令行方式来运行我们的 Pass 了。
clang -Xclang -load -Xclang mypass.so ...

插入 Pass 运行的位置是可控的,参考 ExtensionPointTy

较新 LLVM 使用了新的 PassManager infrastructure, 旧框架的类被移到 llvm::legacy namespace 下。
Clang 我没去查证过,目前尚不清楚是否已经全部切过去,有一个兼容的写法如下。

#include "llvm/IR/LegacyPassManager.h"
using namespace llvm;

static void registerPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) {
    ...
}

运行 Pass

  • 各个 Pass 流程时间统计 opt -load mypass.so -mpass -time-passes < code.bc > code_inst.bc
  • 查看自己 Pass 支持选项 opt -load mypass.so -mpass -help

Debug a llvm Pass

如何进行 Pass 的调试呢?

Debug 信息输出

#include"llvm/Support/Debug.h"
// for more fine-grained control '-debug-only' option
#define DEBUG_TYPE "afl"
...
LLVM_DEBUG(dbgs() << "debug message\n");
...

特别注意 :需要 opt 本身是 Debug 选项下编译出来的,因为上述的 LLVM_DEBUGRelease 版本下失效。
llvm 工程编译的时候选择 Debug (默认) 而不是 Release。
最后在运行 Pass 的时候加个 -debug 选项。
opt -load mypass.so -mpass < code.bc > code_inst.bc -debug
opt -load mypass.so -mpass < code.bc > code_inst.bc -debug-only=afl

gdb opt
b llvm::Pass::preparePassManager
run -load Mypass -mpass < code.bc > /dev/null

  1. https://www.cs.cornell.edu/~asampson/blog/clangpass.html ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值