1- #include " llvm/Passes/PassBuilder.h" // 引入新版Pass Manager的PassBuilder,用於註冊Pass
2- #include " llvm/Passes/PassPlugin.h" // 引入Pass插件API,用於定義插件入口點
3- #include " llvm/IR/Module.h" // 提供Module類,代表整個程式模組
4- #include " llvm/IR/Function.h" // 提供Function類,代表單個函數
5- #include " llvm/IR/BasicBlock.h" // 提供BasicBlock類,代表函數中的基本塊
6- #include " llvm/IR/IRBuilder.h" // 提供IRBuilder類,用於生成LLVM IR指令
7- #include " llvm/IR/Instructions.h" // 提供指令類,如CallInst、StoreInst等
8- #include " llvm/IR/Type.h" // 提供類型定義,如IntegerType、PointerType
9- #include " llvm/IR/Constants.h" // 提供常數類,如ConstantInt、ConstantDataArray
10- #include " llvm/Support/raw_ostream.h" // 提供輸出流,支援LLVM內部除錯(本程式未使用)
1+ #include " llvm/Passes/PassPlugin.h"
2+ #include " llvm/Passes/PassBuilder.h"
3+ #include " llvm/IR/IRBuilder.h"
114
12- using namespace llvm ; // 使用llvm命名空間,避免重複寫llvm::
5+ using namespace llvm ;
136
14- namespace { // 匿名命名空間,限制類和函數的範圍僅在本檔案內
15-
16- // 定義LLVMPass結構,繼承PassInfoMixin以適配新版Pass Manager
177struct LLVMPass : public PassInfoMixin <LLVMPass> {
18- // run方法:Pass的核心邏輯,處理模組並執行插樁
19- PreservedAnalyses run (Module &M, ModuleAnalysisManager &AM ) {
20- // 獲取LLVM上下文,用於創建IR物件(如類型、常數)
21- LLVMContext &Ctx = M.getContext ();
22- // 定義32位整數類型(i32),用於argc和debug參數
23- IntegerType *Int32Ty = IntegerType::getInt32Ty (Ctx);
24- // 定義void類型,用於debug函數的回傳值
25- Type *VoidTy = Type::getVoidTy (Ctx);
26- // 定義指向8位整數的指標類型(i8*),用於字串指標(char*)
27- Type *Int8PtrTy = Type::getInt8PtrTy (Ctx);
28-
29- // 需求1:準備debug函數和參數
30- // 定義debug函數的簽名:void debug(i32)
31- FunctionType *DebugFnTy = FunctionType::get (VoidTy, {Int32Ty}, false );
32- // 獲取或插入debug函數的宣告,若不存在則創建原型
33- FunctionCallee DebugFunc = M.getOrInsertFunction (" debug" , DebugFnTy);
34- // 創建常數48763(i32),作為debug函數的參數
35- ConstantInt *DebugArg = ConstantInt::get (Int32Ty, 48763 );
36-
37- // 需求2:創建全域字串常數"hayaku... motohayaku!"
38- // 生成字串常數,true表示添加結束符\0
39- Constant *StrConst = ConstantDataArray::getString (Ctx, " hayaku... motohayaku!" , true );
40- // 創建全域變數儲存字串,常數且僅模組內可見
41- GlobalVariable *StrGlobal = new GlobalVariable (
42- M, StrConst->getType (), true , GlobalVariable::InternalLinkage, StrConst, " " );
43- // 創建常數0(i32),用於計算字串地址
44- ConstantInt *Zero = ConstantInt::get (Int32Ty, 0 );
45- // 計算字串的起始地址(i8*),用於存入argv[1]
46- Value *StrPtr = ConstantExpr::getGetElementPtr (StrConst->getType (), StrGlobal, Zero);
47-
48- // 遍歷模組中的所有函數
49- for (Function &F : M) {
50- // 檢查是否為main函數
51- if (F.getName () == " main" ) {
52- // 獲取main函數的入口基本塊
53- BasicBlock &EntryBB = F.getEntryBlock ();
54- // 創建IRBuilder,插入點設為基本塊的第一條指令
55- IRBuilder<> IRB (&EntryBB, EntryBB.getFirstInsertionPt ());
56-
57- // 需求1:插入對debug(48763)的呼叫
58- IRB .CreateCall (DebugFunc, {DebugArg});
8+ PreservedAnalyses run (Module &M, ModuleAnalysisManager &MAM );
9+ };
5910
60- // 需求2:將argv[1]設為"hayaku... motohayaku!"
61- // 獲取argv(main的第二個參數,char**)
62- Value *Argv = F.getArg (1 );
63- // 計算argv[1]的地址(char*),索引1
64- Value *Argv1Ptr = IRB .CreateGEP (Int8PtrTy, Argv, ConstantInt::get (Int32Ty, 1 ));
65- // 將全域字串的地址存入argv[1]
66- IRB .CreateStore (StrPtr, Argv1Ptr);
11+ PreservedAnalyses LLVMPass::run (Module &M, ModuleAnalysisManager &MAM ) {
12+ LLVMContext &Ctx = M.getContext ();
13+ IntegerType *Int32Ty = IntegerType::getInt32Ty (Ctx);
14+ FunctionCallee debug_func = M.getOrInsertFunction (" debug" , Int32Ty);
15+ ConstantInt *debug_arg = ConstantInt::get (Int32Ty, 48763 );
6716
68- // 需求3:將argc設為48763
69- // 獲取argc(main的第一個參數,i32)
70- Value *Argc = F.getArg (0 );
71- // 創建常數48763(i32)
72- ConstantInt *NewArgc = ConstantInt::get (Int32Ty, 48763 );
73- // 將argc的所有使用替換為48763
74- Argc->replaceAllUsesWith (NewArgc);
75- }
76- }
17+ for (auto &F : M) {
18+ errs () << " func: " << F.getName () << " \n " ;
7719
78- // 回傳PreservedAnalyses::none(),表示可能影響所有分析
79- return PreservedAnalyses::none ();
8020 }
81- };
82-
83- } // 結束匿名命名空間
21+ return PreservedAnalyses::none ();
22+ }
8423
85- // 定義插件入口點,告訴LLVM如何載入此Pass
8624extern " C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
8725llvmGetPassPluginInfo () {
88- return {
89- LLVM_PLUGIN_API_VERSION , // 插件API版本
90- " LLVMPass" , // 插件名稱
91- " v0.1" , // 插件版本
92- [](PassBuilder &PB ) { // 插件初始化回調
93- // 註冊到優化管線末尾,自動執行Pass
26+ return {LLVM_PLUGIN_API_VERSION , " LLVMPass" , " 1.0" ,
27+ [](PassBuilder &PB ) {
9428 PB .registerOptimizerLastEPCallback (
95- [](ModulePassManager &MPM , OptimizationLevel) {
29+ [](ModulePassManager &MPM , OptimizationLevel OL ) {
9630 MPM .addPass (LLVMPass ());
97- return true ;
98- });
99- // 也支援顯式調用(-passes=llvm-pass)
100- PB .registerPipelineParsingCallback (
101- [](StringRef Name, ModulePassManager &MPM , ArrayRef<PassBuilder::PipelineElement>) {
102- if (Name == " llvm-pass" ) {
103- MPM .addPass (LLVMPass ());
104- return true ;
105- }
106- return false ;
10731 });
10832 }};
109- }
33+ }
34+
0 commit comments