欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LLVM9.0编写Hello pass

程序员文章站 2022-03-30 20:14:47
...

最近动手尝试了一下,在安装完成LLVM9.0之后,新建一个FunctionPass。以下是参考他人文档和自己实现的过程。

1. 新建或修改Hello.cpp

在/home/zgl/llvm-project-9.0.0/llvm/lib/Transforms/Hello目录下新建或修改Hello.cpp,代码如下:

#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.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()) << '\n';
            return false;
        }
    };
}
// 初始化pass的ID
char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass");

// 将本pass注册为现有流水线中的一步
static RegisterStandardPasses Y(
  PassManagerBuilder::EP_EarlyAsPossible,
  [](const PassManagerBuilder &Builder,
  legacy::PassManagerBase &PM)
  {PM.add(new Hello()); }
); 

2. 新建或修改CMakeLists.txt

在/home/zgl/llvm-project-9.0.0/llvm/lib/Transforms/Hello目录下新建或修改CMakeLists.txt,添加代码如下:

if( NOT LLVM_REQUIRES_RTTI )
   if( NOT LLVM_REQUIRES_EH )
     set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Hello.exports)
   endif()
 endif()
 
 if(WIN32 OR CYGWIN)
   set(LLVM_LINK_COMPONENTS Core Support)
endif()

add_llvm_library(LLVMHello MODULBUILDTREE_ONLY SHARED
   Hello.cpp

   DEPENDS
   intrinsics_gen
   PLUGIN_TOOL
   opt
   )

3. 修改上层目录CMakeLists.txt

修改/home/zgl/llvm-project-9.0.0/llvm/lib/Transforms目录下CMakeLists.txt文件,如下:
add_subdirectory(Hello)

4. 编译Hello.cpp

若你在xx/Hello/CMakeLists.txt文件中没采用添加SHARED属性的方式来生成动态链接库,而是使用clang编译:

clang `llvm-config --cxxflags` -Wl,-znodelete -fno-rtti -fPIC -shared Hello.cpp -o LLVMHello.so `llvm-config --ldflags`

在使用opt -load的时候可能会因为libc++stdlibc++不一致的原因出现如下错误:

Error opening '/home/zgl/llvm-project-9.0.0/llvm/lib/Transforms/Hello/LLVMHello.so': /home/zgl/llvm-project-9.0.0/llvm/lib/Transforms/Hello/LLVMHello.so: undefined symbol: _ZNK4llvm12FunctionPass17createPrinterPassERNS_11raw_ostreamERKSs
-load request ignored.

此处使用安装LLVM时的脚本来编译: step1.sh,编译完成之后在/home/zgl/llvm-project-9.0.0/llvm/build/lib/目录下生成一个LLVMHello.so的动态库,LLVMHello为生成的库名字。

5. 测试

找个测试文件,使用clang工具生成.ll文件。clang -emit-llvm -S -c size.c -o size.ll

使用opt -load /home/zgl/llvm-project-9.0.0/llvm/build/lib/LLVMHello.so -hello <size.ll> /dev/null便可成功查看到pass的输出信息。

也可使用opt -load /home/zgl/llvm-project-9.0.0/llvm/build/lib/LLVMHello.so -gvn -hello -licm --debug-pass=Structure <size.ll> /dev/null命令打印pass的依赖信息。


References:

  • https://zhuanlan.zhihu.com/p/122522485
  • https://www.jianshu.com/p/9f450969121b
相关标签: 编译器 编译器