Skip to content

Commit 0bbfa52

Browse files
authored
Merge pull request #439 from MinKuanIsHere/lab6
[LAB6] 313552009
2 parents 305bd68 + 9ad6a16 commit 0bbfa52

1 file changed

Lines changed: 95 additions & 20 deletions

File tree

lab6/llvm-pass.so.cc

Lines changed: 95 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,109 @@
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
717
struct 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
2486
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
2587
llvmGetPassPluginInfo() {
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

Comments
 (0)