LLVM Pass 简介(2)
本节介绍一段对LLVM 的Function进行遍历的过程,遍历过程中统计每个Function内的BasicBlock数目和指令数目,同时统计所有的operand出现的次数。
因为涉及到IR的东西,UserManual手册为: https://llvm.org/docs/LangRef.html 。真的建议初学者都去简单的扫一遍这个文档,看下目录也好,网上的很多介绍文档和博客上边都给了很多错误的东西。
1 #include "llvm/ADT/Statistic.h" 2 #include "llvm/IR/Function.h" 3 #include "llvm/Pass.h" 4 #include "llvm/Support/raw_ostream.h" 5 #include <map> 6 #include <string> 7 #include "llvm/IR/Instructions.h" 8 #include "llvm/IR/InstVisitor.h" 9 #include "llvm/ADT/DepthFirstIterator.h" 10 #include "llvm/ADT/SmallPtrSet.h" 11 #include "llvm/ADT/SmallVector.h" 12 #include "llvm/IR/InstIterator.h" 13 #include "llvm/IR/Instructions.h" 14 #include "llvm/IR/IntrinsicInst.h" 15 using namespace llvm; 16 #define DEBUG_TYPE "hello" 17 18 STATISTIC(HelloCounter, "Counts number of functions greeted"); 19 namespace { 20 // Hello2 - The second implementation with getAnalysisUsage implemented. 21 struct Hello2 : public FunctionPass { 22 static char ID; // Pass identification, replacement for typeid 23 Hello2() : FunctionPass(ID) {} 24 using BasicBlockListType = SymbolTableList<BasicBlock>; 25 bool runOnFunction(Function &F) override { 26 ++HelloCounter; 27 errs() << "now process funcName: "; 28 errs().write_escaped(F.getName()) << '\n'; 29 //we just what to show how to Traverse 30 //BBsize = F.size(); 31 //when you just want get all instructions, you can use llvm::instructions(F) 32 uint BBsize = 0; 33 uint instSize = 0; 34 BasicBlockListType::const_iterator bbEnd = F.end(); 35 for(BasicBlockListType::const_iterator bbIter=F.begin(); bbIter!=bbEnd; ++bbIter){ 36 BBsize += 1; 37 SymbolTableList<Instruction>::const_iterator instIter = bbIter->begin(); 38 SymbolTableList<Instruction>::const_iterator instEnd = bbIter->end(); 39 for(; instIter != instEnd; ++instIter){ 40 instSize ++; 41 std::string opcName(instIter->getOpcodeName()); 42 std::map<std::string, uint>::iterator itFind = 43 opCodeMap.find(opcName); 44 if(itFind != opCodeMap.end() ){ 45 opCodeMap[opcName]++; 46 } 47 else{ 48 opCodeMap[opcName] = 1; 49 } 50 } 51 } 52 // 53 errs() << " has "<< BBsize <<" BasicBlocks "<<instSize <<" insts\n"; 54 for(auto it : opCodeMap){ 55 errs() <<" total opcode now use "<<it.first <<" "<<it.second <<"\n"; 56 } 57 return false; 58 } 59 60 // We don't modify the program, so we preserve all analyses. 61 void getAnalysisUsage(AnalysisUsage &AU) const override { 62 AU.setPreservesAll(); 63 } 64 std::map<std::string, uint> opCodeMap; 65 }; 66 } 67 68 char Hello2::ID = 0; 69 static RegisterPass<Hello2> 70 Y("hello2", "Hello World Pass (with getAnalysisUsage implemented)");
使用上一节的测试hello.c 这次需要将命令换为 ./bin/opt -load lib/LLVMHello.so -hello2 < hello.bc > /dev/null
结果如下图: