挖了一个坑,还不知道能不能填好。。。。。。
已经安装好了llvm,如llvm的3.7.0版本,编译安装好以后的文件结构如下,build是之前在build中进行make的文件夹,llvm是源码。
进入llvm文件夹中,llvm源码中有一个lib文件夹,里面有一个Transforms文件夹,进入/llvm/lib/Transforms。
在Transforms中关注两个地方,一个是Hello文件夹,这个是官方demo,还有下面的CMakeLists.txt,这个是官网中提到的那个要修改的文件之一,最后需要修改。
先新建一个文件夹,叫MyHello,把Hello下的复制过来,然后一个个改名。 对于MyHello文件夹下的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}/MyHello.exports) endif() endif() if(WIN32 OR CYGWIN) set(LLVM_LINK_COMPONENTS Core Support) endif() add_llvm_loadable_module( LLVMMyHello MyHello.cpp DEPENDS intrinsics_gen )对于Makefile,里面文件名要修改一个地方:
EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/MyHello.exports对于MyHello.cpp,修改的并不是很多:
#include "llvm/ADT/Statistic.h" #include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; #define DEBUG_TYPE "hello" STATISTIC(HelloCounter, "Counts number of functions greeted"); namespace { // Hello - The first implementation, without getAnalysisUsage. struct MyHello : public FunctionPass { static char ID; // Pass identification, replacement for typeid MyHello() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { ++HelloCounter; errs() << "MyHello: "; errs().write_escaped(F.getName()) << '\n'; return false; } }; } char MyHello::ID = 0; static RegisterPass<MyHello> X("MyHello", "Hello World Pass"); //注意这里是注册,第1个参数MyHello是命令行参数,第2个是pass的名字现在修改之前说到要修改的那个CMakeLists,官网说的加一条是加在这:
进入到之前build文件夹,输入make,如果一切正常,可以看到生成了LLVMMyHello.so文件,这个是之前第3步中自己指定的:
下面进行测试: test.c
int add(int a, int b) { return a+b; } int sub(int a, int b) { return a-b; }通过test.c生成LLVM IR文件test.ll:
clang -Os -S -emit-llvm test.c
可以看到MyHello成功运行,-MyHello是注册时指定的命令行参数:
