llvm pass既可以在源码目录编译,也可以在任务其他目录编译。用到的源码为 9.0

一:在源码目录编译

在 llvm/lib/Transforms的CMakeLists.txt中添加

add_subdirectory(MyPass)

然后创建目录 llvm/lib/Transforms/MyPass

创建文件:

llvm/lib/Transforms/MyPass/
|-- CMakeLists.txt
`-- MyPass.cpp

CMakeLists.txt内容如下

add_library( LLVMMyPass MODULE
  MyPass.cpp
)

# Use C++11 to compile our pass (i.e., supply -std=c++11).
target_compile_features(LLVMMyPass PRIVATE cxx_range_for cxx_auto_type)

# LLVM is (typically) built with no C++ RTTI. We need to match that;
# otherwise, we'll get linker errors about missing RTTI data.
set_target_properties(LLVMMyPass PROPERTIES
    COMPILE_FLAGS "-fno-rtti"
)

MyPass.cpp内容

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

using namespace llvm;

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

    bool runOnFunction(Function &F) override {
      errs() << "MyPass:";
      errs().write_escaped(F.getName()) << '\n';
      return false;
    }
  };
}

char MyPass::ID = 0;
static RegisterPass X("myPass", "Hello MyPass", false, false);

编译

cmake -G "Unix Makefiles" ../llvm/
make

运行

opt -load ./lib/libLLVMMyPass.so -myPass hello.bc

其中 hello.bc 是从http://hello.cc文件编译而来,http://hello.cc内容

#include 

using namespace std;

int main(int argc, char* argv[]) {
  cout << "hello" << endl;
  return 0;
}

编译命令:

clang -emit-llvm -c hello.cc

参考:

https://www.zhihu.com/question/47631469

https://github.com/sampsyo/llvm-pass-skeleton/tree/master/skeleton

二: 在任意目录编译

创建目录 pass

把前面的MyPass.cpp拷贝到pass目录,执行编译命令:

clang++ -c MyPass.cpp `llvm-config --cxxflags`

此时,会生成文件 MyPass.o,再次执行命令:

clang++ -shared -o MyPass.so MyPass.o `llvm-config --ldflags`

生成了 MyPass.so,运行

opt -load ./MyPass.so -myPass ../hello.bc

参考:

https://stackoverflow.com/questions/22007458/how-to-create-you-own-pass-in-llvm


original refer