llvm pass运行实践


前言

      继llvm安装之后,进行自定义pass实现并运行。

      需要注意的是,在网上有不少文章以及官方文档,如果读者可以成功实践,那最好不过了;不然仅以此文作为参考。

      环境为Ubuntu20.04。

一、环境

      编写pass实践在这里是基于源码编译的方式。相关文件如下所示:

root@ca0e100b0df4:/usr/local# ls
bin  etc  games  include  lib  llvm  llvm-project-main  man  sbin  share  src
root@ca0e100b0df4:/usr/local/llvm-project-main# ls
CONTRIBUTING.md  bolt   clang-tools-extra  cross-project-tests  libclc     libunwind  llvm         openmp  runtimes
README.md        build  cmake              flang                libcxx     lld        llvm-libgcc  polly   third-party
SECURITY.md      clang  compiler-rt        libc                 libcxxabi  lldb       mlir         pstl    utils
	...llvm 为源代码文件目录,build 为编译中间目录...

二、编写MyPass并运行

      这里请参考官方文档中对每一步的说明。

1、准备三个文件:

      CMakeLists.txt、MyPass.cpp 和 MyPass.exports,这三个文件可以对 llvm/lib/Transforms/Hello中文件内容稍作修改获得,具体如下;

      1,CMakeLists.txt中内容如下:

# If we don't need RTTI or EH, there's no reason to export anything
# from the hello plugin.
if( NOT LLVM_REQUIRES_RTTI )
  if( NOT LLVM_REQUIRES_EH )
    set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/MyPass.exports)
  endif()
endif()
 
if(WIN32 OR CYGWIN)
  set(LLVM_LINK_COMPONENTS Core Support)
endif()
 
add_llvm_library( LLVMMyPass MODULE BUILDTREE_ONLY
  MyPass.cpp

  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )

      2,MyPass.cpp中内容如下:

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

#define DEBUG_TYPE "mypass"
namespace {

  	struct MyPass : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    MyPass() : FunctionPass(ID) {}

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

char MyPass::ID = 0; //LLVM uses ID’s address to identify a pass, so initialization value is not important.
static RegisterPass<MyPass> X("mypass", "Hello World Pass"); //这里的 mypass 为pass名。

      3,MyPass.exports为空。

2、将文件放入相应的目录下

      新建文件夹 MyPass,将第一步中的三个文件放入其中。然后将该文件夹放入到 llvm/lib/Transforms/ 下(自己电脑上全路径为:/usr/local/llvm-project-main/llvm/lib/Transforms/)。

      在 Transforms/CMakeLists.txt 中添加新的一行: add_subdirectory(MyPass),此 CMakeLists.txt 中内容如下:

add_subdirectory(Utils)
add_subdirectory(Instrumentation)
add_subdirectory(AggressiveInstCombine)
add_subdirectory(InstCombine)
add_subdirectory(Scalar)
add_subdirectory(IPO)
add_subdirectory(Vectorize)
add_subdirectory(Hello)
add_subdirectory(ObjCARC)
add_subdirectory(Coroutines)
add_subdirectory(CFGuard)
add_subdirectory(MyPass)

3、执行

      第一步:通过 make 将 MyPass.cpp 编译为 LLVMMyPass .so 文件。

root@ca0e100b0df4:/# cd /usr/local/llvm-project-main/build/
root@ca0e100b0df4:/usr/local/llvm-project-main/build# make
...因为之前已经编译过了,此次 make 时间大概几十秒就可以,仅编译新的 MyPass 文件夹...
root@ca0e100b0df4:/usr/local/llvm-project-main/build# cd lib
root@ca0e100b0df4:/usr/local/llvm-project-main/build/lib# ls -l | grep MyPass
-rwxr-xr-x  1 root root     18904 May 19 22:39 LLVMMyPass.so

      第二步:建立一个测试文件为 test.c,它位于 /home/dataVolume/tmp 目录下:

#include<stdio.h>

void haha(){
	printf("haha\n");
}

int heihei(int a){
	return a;
}
int main(){
	haha();
	int tmp=heihei(4);
	return 0;
}

      然后生成 test.c 相应的IR文件 test.ll:

root@ca0e100b0df4:/home/dataVolume/tmp# clang -emit-llvm -S test.c test.ll

      第三步,采用 opt 工具来执行 MyPass,注意参数 -enable-new-pm=0 :


root@ca0e100b0df4:/home/dataVolume/tmp# opt -load /usr/local/llvm-project-main/build/lib/LLVMMyPass.so -mypass test.ll
WARNING: You're attempting to print out a bitcode file.
This is inadvisable as it may cause display problems. If
you REALLY want to taste LLVM bitcode first-hand, you
can force output with the `-f' option.

opt: unknown pass name 'mypass'
root@ca0e100b0df4:/home/dataVolume/tmp# opt -load /usr/local/llvm-project-main/build/lib/LLVMMyPass.so -mypass test.ll -enable-new-pm=0
WARNING: You're attempting to print out a bitcode file.
This is inadvisable as it may cause display problems. If
you REALLY want to taste LLVM bitcode first-hand, you
can force output with the `-f' option.

MyPass: haha
MyPass: heihei
MyPass: main
root@ca0e100b0df4:/home/dataVolume/tmp# opt -load /usr/local/llvm-project-main/build/lib/LLVMMyPass.so -mypass test.ll -enable-new-pm=0 >/dev/null
MyPass: haha
MyPass: heihei
MyPass: main

总结

      相关资料:
参数 -enable-new-pm=0 表示:采用 legacy pass 管理器,禁用 new pass 管理器。
Out-of-tree:可以不需要再llvm源代码树下构建pass
llvm-pass-skeleton:更加方便的构建pass

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值