代码实现——添加一个中端Pass
在 LLVM 里如何添加一个 Pass?这边主要给出非插件式的教程。
我使用的 LLVM 版本是 19.1.0。一些中端文件位于 <source>/llvm/lib/
中,在本例子中,我使用 <source>/llvm/lib/Transform/Utils
。
步骤 1
首先,我新建两个目录,名为 MyExtension
。即 <source>/llvm/lib/Transform/Utils/MyExtension
和 <source>/llvm/include/llvm/Transforms/Utils/MyExtension
,用于后续存放我自己的 Pass,如果你觉得用 IDE 一层层点麻烦,你可以使用命令行,更快,也不容易出错。
步骤 2
这一步我会添加两个文件,即 C++里面的头文件和源文件,分别为. h 和. cpp。本例子想打印所有变量名,所以我取文件名为 ModifyVariablesName
。分别为:<source>/llvm/include/llvm/Transforms/Utils/MyExtension/ModifyVariablesName.h
和 <source>/llvm/lib/Transform/Utils/MyExtension/ModifyVariablesName.cpp
上述两个步骤的命令如下:
mkdir -p llvm/lib/Transform/Utils/MyExtension
mkdir -p llvm/include/llvm/Transforms/Utils/MyExtension
touch llvm/include/llvm/Transforms/Utils/MyExtension/ModifyVariablesName.h
touch llvm/lib/Transform/Utils/MyExtension/ModifyVariablesName.cpp
步骤 3
对上述两个文件写入内容(为了保证流程简洁性,文件内容见附录)
vim llvm/include/llvm/Transforms/Utils/MyExtension/ModifyVariablesName.h
vim llvm/lib/Transforms /Utils/MyExtension/ModifyVariablesName.cpp
步骤 4
下面需要去让 LLVM 知道我新加了一些内容,第一步:修改 CMakelist. txt
vim llvm/lib/Transforms/Utils/CMakeLists.txt
在内部添加如下内容:
MyExtension/ModifyVariablesName.cpp
步骤 5
继续注册代码到已有代码:
vim llvm/lib/Passes/PassBuilder.cpp
vim llvm/lib/Passes/PassBuilderPipelines.cpp
两个 cpp 文件都导入刚才的 Pass 头文件:
#include "llvm/Transforms/Utils/MyExtension/ModifyVariablesName.h"
在 PassBuilderPipelines. cpp 的适当位置用 addPass 接口引入你的优化或者打印
步骤 6
最后一步了,修改真正的 def 注册方式:
vim llvm/lib/Passes/PassRegistry.def
因为我这边是 FUNCTION_PASS,所以添加内容为
FUNCTION_PASS("mod-var", ModifyVariablesPass())
附录
ModifyVariablesName. h
#ifndef PRINT_VARIABLES_PASS_H
#define PRINT_VARIABLES_PASS_H
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instruction.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
// 定义 Module 级别的 Pass
class PrintVariablesPass : public PassInfoMixin<PrintVariablesPass> {
public:
// 运行 Pass
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
};
#endif // PRINT_VARIABLES_PASS_H
ModifyVariablesName. cpp
#include "llvm/Transforms/Utils/MyExtension/ModifyVariablesName.h"
PreservedAnalyses PrintVariablesPass::run(Module &M, ModuleAnalysisManager &) {
errs() << "Running PrintVariablesPass...\n";
// 遍历 Module 内的每个 Function
for (Function &F : M) {
errs() << "Function: " << F.getName() << "\n";
// 遍历 Function 内的每个 BasicBlock
for (BasicBlock &BB : F) {
// 遍历 BasicBlock 内的每条指令
for (Instruction &I : BB) {
if (!I.getName().empty()) { // 变量有名字
errs() << " Variable: " << I.getName() << "\n";
} else {
errs() << " Unnamed variable (may be temporary)\n";
}
}
}
}
return PreservedAnalyses::all();
}
评论