1- #include " llvm/Passes/PassPlugin.h"
2- #include " llvm/Passes/PassBuilder.h"
3- #include " llvm/IR/IRBuilder.h"
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內部除錯(本程式未使用)
411
5- using namespace llvm ;
12+ using namespace llvm ; // 使用llvm命名空間,避免重複寫llvm::
613
14+ namespace { // 匿名命名空間,限制類和函數的範圍僅在本檔案內
15+
16+ // 定義LLVMPass結構,繼承PassInfoMixin以適配新版Pass Manager
717struct LLVMPass : public PassInfoMixin <LLVMPass> {
8- PreservedAnalyses run (Module &M, ModuleAnalysisManager &MAM );
9- };
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 ());
1056
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 );
57+ // 需求1:插入對debug(48763)的呼叫
58+ IRB .CreateCall (DebugFunc, {DebugArg});
1659
17- for (auto &F : M) {
18- errs () << " func: " << F.getName () << " \n " ;
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);
1967
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+ }
77+
78+ // 回傳PreservedAnalyses::none(),表示可能影響所有分析
79+ return PreservedAnalyses::none ();
2080 }
21- return PreservedAnalyses::none ();
22- }
81+ };
82+
83+ } // 結束匿名命名空間
2384
85+ // 定義插件入口點,告訴LLVM如何載入此Pass
2486extern " C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
2587llvmGetPassPluginInfo () {
26- return {LLVM_PLUGIN_API_VERSION , " LLVMPass" , " 1.0" ,
27- [](PassBuilder &PB ) {
88+ return {
89+ LLVM_PLUGIN_API_VERSION , // 插件API版本
90+ " LLVMPass" , // 插件名稱
91+ " v0.1" , // 插件版本
92+ [](PassBuilder &PB ) { // 插件初始化回調
93+ // 註冊到優化管線末尾,自動執行Pass
2894 PB .registerOptimizerLastEPCallback (
29- [](ModulePassManager &MPM , OptimizationLevel OL ) {
95+ [](ModulePassManager &MPM , OptimizationLevel) {
3096 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 ;
31107 });
32108 }};
33- }
34-
109+ }
0 commit comments