#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
using namespace llvm;
#define DEBUG_TYPE "hello"
STATISTIC(HelloCounter, "Counts number of functions greeted");
namespace {
struct Hello : public FunctionPass {
static char ID;
Hello() : FunctionPass(ID) {}
~Hello() {
errs() << "\nCompile Finish!\n";
errs() << "Functions count: " << HelloCounter;
}
bool runOnFunction(Function &F) override {
++HelloCounter;
errs() << "Got Function> ";
errs().write_escaped(F.getName()) << '\n';
return false;
}
};
}
char Hello::ID = 0;
// 为 opt 注册
static RegisterPass<Hello> X("funcname", "Hello World Pass");
// 为 clang 注册, 在高版本中不可用, 测试在10.0.0版本中可用
static RegisterStandardPasses Y(PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder& Builder,
legacy::PassManagerBase& PM) {
PM.add(new Hello());
});
使用以下命令编译此 LLVM Pass
:
clang `llvm-config --cxxflags` -Wl,-znodelete -fno-rtti -fPIC -shared Hello.cpp -o LLVMHello.so `llvm-config --ldflags`
使用以下命令使用此 LLVM Pass
:
## opt
opt -enable-new-pm=0 -load ./LLVMHello.so -funcname main.ll
# -enable-new-pm=0: 设置 Pass 管理器为旧版本
# -load ./LLVMHello.so: 加载 LLVMBirkhoff.so 模块作为 LLVM Pass
# -funcname: 指定要执行的命令为 funcname
## clang
clang -flegacy-pass-manager -g -Xclang -load -Xclang ./LLVMHello.so main.c -o main.elf
# -flegacy-pass-manager: 使用旧版本的Pass Manager, 以支持在 LLVM 13 版本中使用 LLVM Pass
# -Xclang -load -Xclang ./LLVMHello.so: 加载LLVMHello.so作为LLVM Pass
# main.c: 要编译的源代码文件
# -o main.elf: 生成的可执行文件文件名。
文档中提到, optimization pipeline
使用新版本的 PM (New PM), 而后端(即 backend
) 使用旧版 PM(Legacy PM), 而一部分 IR Pass 被认为属于后端.
输出结果如下:
$ clang -flegacy-pass-manager -g -Xclang -load -Xclang ./LLVMHello.so main.c -o main.elf
Got Function> add
Got Function> main
Compile Finish!
Functions count: 2
文档信息
- 本文作者:Birkhoff
- 本文链接:https://blogs.maikebuke.com/2023/02/18/02-LLVM-Pass-%E5%AE%98%E6%96%B9%E7%A4%BA%E4%BE%8B/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)