挖了一个坑,还不知道能不能填好。。。。。。
前提
已经安装好了llvm,如llvm的3.7.0版本,编译安装好以后的文件结构如下,build是之前在build中进行make的文件夹,llvm是源码。
1
进入llvm文件夹中,llvm源码中有一个lib文件夹,里面有一个Transforms文件夹,进入/llvm/lib/Transforms。
2
在Transforms中关注两个地方,一个是Hello文件夹,这个是官方demo,还有下面的CMakeLists.txt,这个是官网中提到的那个要修改的文件之一,最后需要修改。
3
先新建一个文件夹,叫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的名字
4
现在修改之前说到要修改的那个CMakeLists,官网说的加一条是加在这:
5
进入到之前build文件夹,输入make,如果一切正常,可以看到生成了LLVMMyHello.so文件,这个是之前第3步中自己指定的:
6
下面进行测试:
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是注册时指定的命令行参数: