Basic
想做一个有关llvm-pass的lab: 试试康奈尔 CS 6120: The Self-Guided Course (cornell.edu)
环境: Ubuntu + llvm 14 + clang 14
clone lab repo :
1
git clone https://github.com/sampsyo/llvm-pass-skeleton.git
进入这个repo,创建build文件夹,进入文件夹
LLVM_DIR=/usr/lib/llvm-14/cmake cmake ..
来生成makefile,注意LLVM_DIR 取决于你LLVM的安装路径。然后make编译,他会编译出一个libSkeletonPass.so 文件我们随便写一个main.c,然后使用下列命令行编译
clang -flegacy-pass-manager -Xclang -load -Xclang ./libSkeletonPass.so main.c
另一种方案
使用clang将 main.c 编译为 llvm-ir
clang -emit-llvm -c main.c
生成 main.bc修改Skeleton.cpp 为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36// #include <iostream>
using namespace llvm;
namespace
{
struct SkeletonPass : public FunctionPass
{
static char ID;
SkeletonPass() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F)
{
// std::cout<<"HELLO!";
errs() << "I saw a function called " << F.getName() << "!\n";
errs() << F;
return false;
}
};
}
char SkeletonPass::ID = 0;
// Register for opt
static RegisterPass<SkeletonPass> X("hello", "Hello World Pass");
// Register for clang
static RegisterStandardPasses Y(PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder, legacy::PassManagerBase &PM)
{
PM.add(new SkeletonPass());
});make重新编译
使用 opt 加载 pass 动态共享库
opt -load ./skeleton/libSkeletonPass.so -hello -enable-new-pm=0 main.bc
Example 1: 遍历IR
打印每条命令,每个BB。runOnFunction 返回值含义即函数是否被修改。
1 | virtual bool runOnFunction(Function &F) |
Example 2: 修改运算指令
打印所有的运算指令
1 | virtual bool runOnFunction(Function &F) |
下面我们尝试将所有运算指令换成乘法指令
1 | for (auto &I : B) |
还是比较清晰的。
Example 3: 插入函数
注意者不仅仅需要main.c 还需要编写logop 的实现并和main.c 链接。
1 | virtual bool runOnFunction(Function &F) |
References:
- LLVM 后端 : LLVM 后端实践笔记 0:序 - 知乎 (zhihu.com)