建議可搭配 LLVM 寫一個 pass - 教學入門篇 一起玩
另外這是 GCC 的對照組GCC : Control Flow Graph
0. 使用前注意
通常在 LLVM 裡面你會是在某個 Pass 裡面去走訪 CFG,而這個時候你必須明確告訴 LLVM 你有使用 CFG, 然後他在呼叫你的 pass 之前就一定會幫你準備好
要作到這件事則必須把以下函數加入到你的 Pass 的那個 struct/class 中
virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); }
1. 走訪該函數所有的 Basic Block
Function F; for (Function::iterator itr = F.begin(); itr != F.end(); ++itr) { BasicBlock &bb = *itr; }
2. 走訪 basic block 的所有 successor
BasicBlock bb; for (succ_iterator itr = succ_begin(&bb); itr != succ_end(&bb); ++itr) { BasicBlock *succ = *itr; }
3. 走訪 basic block 的所有 Predecessor
BasicBlock bb; for (pred_iterator itr = pred_begin(&bb); itr != pred_end(&bb); ++itr) { BasicBlock *pred = *itr; }
4. 取得 Function 的 Entry Basic Block
要注意的是收的變數最好是 Reference !Function F; BasicBlock &bb = F.getEntryBlock();
5. Basic Block中所有指令
BasicBlock bb; for (BasicBlock::iterator itr = bb.begin(); itr != bb.end(); ++itr) { Instruction &inst = *itr; }
跳過所有 PHI Node
BasicBlock bb; for (BasicBlock::iterator itr = bb.getFirstNonPHI(); itr != bb.end(); ++itr) { Instruction &inst = *itr; }另外還有getFirstNonPHIOrDbg () 及 getFirstNonPHIOrDbgOrLifetime () 可以跳過除錯資訊及Lifetime 的資訊
6. 走訪一個函數裡面所有 BB 中的指令之FunctionPass 範例程式碼
#define DEBUG_TYPE "hello" #include "llvm/Pass.h" #include "llvm/Function.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/CFG.h" using namespace llvm; STATISTIC(HelloCounter, "Counts number of functions greeted"); namespace { // Hello - The first implementation, without getAnalysisUsage. struct Hello : public FunctionPass { static char ID; // Pass identification, replacement for typeid Hello() : FunctionPass(ID) {} virtual bool runOnFunction(Function &F) { ++HelloCounter; errs() << "Hello: "; errs() << F.getName() << '\n'; for (Function::iterator itr = F.begin(); itr != F.end(); ++itr) { BasicBlock &bb = *itr; errs() << "Basic block :" << bb.getName () << "\n"; errs() << "successor : {"; for (succ_iterator ssitr = succ_begin(&bb); ssitr != succ_end(&bb); ++ssitr) { BasicBlock *ss = *ssitr; errs() << ss->getName() <<", "; } errs() << "}\n"; errs() << "predecessors : {"; for (pred_iterator ssitr = pred_begin(&bb); ssitr != pred_end(&bb); ++ssitr) { BasicBlock *ss = *ssitr; errs() << ss->getName() <<", "; } errs() << "}\n"; for (BasicBlock::iterator iitr = bb.begin(); iitr != bb.end(); ++iitr) { Instruction &inst = *iitr; errs() << inst << '\n'; } } return false; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); } }; } char Hello::ID = 0; static RegisterPass<Hello> X("hello", "Hello World Pass");
沒有留言:
張貼留言