在 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();
}