需要学习LLVM的大家肯定知道这是一个强大的开源编译工具链,其实越往后学习越会发现,这个东西和设计的思想非常的牛逼,这个东西可以给编译流程带来可插拔式的优化,十分的方便,这篇文章不讲LLVM是什么,主要涉及实操,如何安装到完成第一个Pass优化。
下载LLVM源码的方法非常之多,这里我们只讲git方法。
LLVM源码下载
git clone https://github.com/llvm/llvm-project
直接从git上克隆下来这个项目,可以发现克隆完成后在llvm-project下有非常多的文件夹,包含llvm等等,这个llvm就是我们需要用的核心工具,在llvm-project中(和llvm同级)创建文件夹build,然后进行源码编译。
LLVM编译
这里需要注意的是:
- cmake 可以加一些选项指定平台或者其他信息等等,这个可以参考网上其他,但是我这边直接cmake就可以了
- make -j 后边那个数字制定编译的核数,如果单核会非常非常的慢(几个小时)我这边用的16核大概几分钟
- 如果在make 和 make install的过程中碰到报红,加上sudo试试,可能是编译过程无法创建文件
cd llvm-project
mkdir build
cd build
cmake ../llvm
make -j4
make install
第一个PASS编写
这部分编写第一个PASS,也不介绍PASS是啥了,我们这边写一个简单的IR分析型PASS,输出一个函数名字,下一章节将详细介绍PASS的详细写法。
其实你跟着官方文档(Writing an LLVM Pass — LLVM 15.0.0git documentation)是肯定可以的,这里就以简洁明了的中文搬一下。
Step1 : 创建一个文件夹存放你的PASS,官网文档说路径随意,但是我们跟着教程来,首先进入/llvm-project/llvm/lib/Transforms , 创建一个myhello文件夹来存放我们的pass。
cd llvm/lib/Transforms
mkdir my hello
在这个新的文件夹里,要有两个东西
- CMakeLists.txt 这肯定是要给咱们的新PASS编译一下的,但是LLVM给我们提供了很好的接口,我们只需这么做
add_llvm_library( LLVMmyhello MODULE
myhello.cpp
PLUGIN_TOOL
opt
)
2. myhello.cpp 这个就是我们的PASS了,我们这边简单输出Hello 函数名字吧。(一个简单分析型PASS
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
struct myhello : public FunctionPass {
static char ID;
myhello() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
errs() << "Hello: ";
errs().write_escaped(F.getName()) << '\n';
return false;
}
}; // end of struct Hello
} // end of anonymous namespace
char myhello::ID = 0;
static RegisterPass<myhello> X("myhello", "my Hello World Pass",
false /* Only looks at CFG */,
false /* Analysis Pass */);
x相信你一定看懂了,这是要Hello函数名字。
Step2: 回到build目录重新make,make结束后会发现在build/lib中已经出现了LLVMmyhello.so这个文件(不要问我为什么文件命名这么挫,好区分嘛)
Step3: 我们和llvm与build同级创建一个test文件夹,用来测试,里边我们随便写一个input.c
int add(int a,int b){
return a+b;
}
int sub(int a,int b){
return a-b;
}
Step4: 然后我们用clang工具编译成bitcode,再使用opt工具加载我门自己的pass,就结束了!! 如果报红,或者全错误,请继续sudo
注意:新版本需要加上-enable-new-pm=0必须加,不加报错
clang -emit-llvm input.c -o -c input.bc
sudo opt -enable-new-pm=0 -load ../build/lib/LLVMmyhello.so -myhello input.bc