编写LLVM Pass

上一篇的基础上,编写一个简单的LLVM Pass。

  1. llvm-project-17.0.6.src/llvm/lib/Transforms/目录下,新建一个文件夹SweetWound

image-20240312160020667

  1. 在在llvm-project-17.0.6.src/llvm/include/llvm/Transforms/目录下,新建一个文件夹SweetWound

image-20240312160800961

  1. Transforms目录下的CMakeLists.txt文件末尾,增加如下代码:
1
2
...
add_subdirectory(SweetWound)

image-20240312160306762

  1. llvm-project-17.0.6.src/llvm/include/llvm/Transforms/SweetWound/目录下,新建ModuleTest.h文件,并写入如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ModuleTest.h
#ifndef _LLVM_TRANSFORMS_SWEETWOUND_H_
#define _LLVM_TRANSFORMS_SWEETWOUND_H_
#include "llvm/Pass.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Module.h"

namespace llvm {
class ModuleTestPass : public PassInfoMixin<ModuleTestPass> {
public:
bool flag;
ModuleTestPass(bool flag) {
this->flag = flag;
}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
static bool isRequired() {
return true;
}
};
}

#endif

image-20240312162122849

  1. llvm-project-17.0.6.src/llvm/lib/Transforms/SweetWound/目录下,创建ModuleTest.cpp文件,并写入如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
// ModuleTest.cpp
#include "llvm/Transforms/SweetWound/ModuleTest.h"

using namespace llvm;

PreservedAnalyses ModuleTestPass::run(Module &M, ModuleAnalysisManager &AM) {
if (this->flag == true) {
outs() << "[SW]:" << M.getName() << "\n";
return PreservedAnalyses::none();
}
return PreservedAnalyses::all();
}

image-20240312162703411

  1. llvm-project-17.0.6.src/llvm/lib/Transforms/SweetWound/目录下,创建CMakeLists.txt文件,并写入如下代码:
1
2
3
4
5
6
7
8
9
add_llvm_component_library(LLVMSweetWound
ModuleTest.cpp

LINK_COMPONENTS
Analysis
Core
Support
TransformUtils
)

image-20240312162932261

  1. 修改llvm-project-17.0.6.src/llvm/lib/Passes/PassBuilder.cpp文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
......
#include <optional>
//======================导入头文件======================//
#include "llvm/Transforms/SweetWound/ModuleTest.h"
......
// ======================增加编译参数 begin ======================//
static cl::opt<bool> s_sw_test("test", cl::init(false), cl::desc("test module pass."));
// ======================增加编译参数 end ========================//

PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
std::optional<PGOOptions> PGOOpt,
PassInstrumentationCallbacks *PIC)
: TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) {
......
// 注册Pass
this->registerPipelineStartEPCallback(
[](llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) {
MPM.addPass(ModuleTestPass(s_sw_test));
}
);
}
  1. 重新执行编译脚本,成功后,替换LLVM17.0.6.xctoolchain文件。
  2. 在Xcode的Build Settings-->Other C Flags中,设置编译参数:-mllvm -test:

image-20240312163657204

  1. Command + B编译(或Command + R运行):

image-20240312164200731

可以看到每个编译单元都有对应的输出,即代表编写的LLVM Pass加载成功!!!