GCOVProfiling.cpp revision a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56
1b1928704201034c785a26296a49f69355eb56a05Nick Lewycky//===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===// 2b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 3b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// The LLVM Compiler Infrastructure 4b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 5b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// This file is distributed under the University of Illinois Open Source 6b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// License. See LICENSE.TXT for details. 7b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 8b1928704201034c785a26296a49f69355eb56a05Nick Lewycky//===----------------------------------------------------------------------===// 9b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 10b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// This pass implements GCOV-style profiling. When this pass is run it emits 11b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// "gcno" files next to the existing source, and instruments the code that runs 12b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// to records the edges between blocks that run and emit a complementary "gcda" 13b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// file on exit. 14b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 15b1928704201034c785a26296a49f69355eb56a05Nick Lewycky//===----------------------------------------------------------------------===// 16b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 17b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#define DEBUG_TYPE "insert-gcov-profiling" 18b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 19b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "ProfilingUtils.h" 20b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Transforms/Instrumentation.h" 21b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Analysis/DebugInfo.h" 22b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Module.h" 23b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Pass.h" 24b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Instructions.h" 25b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Support/raw_ostream.h" 26b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Support/Debug.h" 27b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Support/DebugLoc.h" 28b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Support/InstIterator.h" 29b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Support/IRBuilder.h" 30b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/Support/PathV2.h" 31b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/DenseMap.h" 32b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/Statistic.h" 33b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/STLExtras.h" 34b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringExtras.h" 35b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringMap.h" 36b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/UniqueVector.h" 37b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <string> 38b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <utility> 39b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyusing namespace llvm; 40b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 41b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace { 42b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVProfiler : public ModulePass { 43b1928704201034c785a26296a49f69355eb56a05Nick Lewycky bool runOnModule(Module &M); 44b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 45b1928704201034c785a26296a49f69355eb56a05Nick Lewycky static char ID; 46a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky GCOVProfiler() 47a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky : ModulePass(ID), EmitNotes(true), EmitData(true) { 48a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 49a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky } 50a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky GCOVProfiler(bool EmitNotes, bool EmitData) 51a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky : ModulePass(ID), EmitNotes(EmitNotes), EmitData(EmitData) { 52a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky assert((EmitNotes || EmitData) && "GCOVProfiler asked to do nothing?"); 53b1928704201034c785a26296a49f69355eb56a05Nick Lewycky initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 54b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 55b1928704201034c785a26296a49f69355eb56a05Nick Lewycky virtual const char *getPassName() const { 56b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return "GCOV Profiler"; 57b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 58b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 59b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 60b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Create the GCNO files for the Module based on DebugInfo. 61b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void EmitGCNO(DebugInfoFinder &DIF); 62b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 630c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky // Modify the program to track transitions along edges and call into the 640c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky // profiling runtime to emit .gcda files when run. 650c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky bool EmitProfileArcs(DebugInfoFinder &DIF); 660c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 67b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Get pointers to the functions in the runtime library. 68b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getStartFileFunc(); 69b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getEmitFunctionFunc(); 70b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getEmitArcsFunc(); 71b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getEndFileFunc(); 72b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 73b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Add the function to write out all our counters to the global destructor 74b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // list. 75b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void InsertCounterWriteout(DebugInfoFinder &, 76b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SmallVector<std::pair<GlobalVariable *, 77b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t>, 8> &); 78b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 79a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky bool EmitNotes; 80a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky bool EmitData; 81a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky 82b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Module *Mod; 83b1928704201034c785a26296a49f69355eb56a05Nick Lewycky LLVMContext *Ctx; 84b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 85b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 86b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 87b1928704201034c785a26296a49f69355eb56a05Nick Lewyckychar GCOVProfiler::ID = 0; 88b1928704201034c785a26296a49f69355eb56a05Nick LewyckyINITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling", 89b1928704201034c785a26296a49f69355eb56a05Nick Lewycky "Insert instrumentation for GCOV profiling", false, false) 90b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 91a61e52c9b7cf874b46cef687c1c4627a35952542Nick LewyckyModulePass *llvm::createGCOVProfilerPass(bool EmitNotes, bool EmitData) { 92a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky return new GCOVProfiler(EmitNotes, EmitData); 93a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky} 94b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 95b1928704201034c785a26296a49f69355eb56a05Nick Lewyckystatic DISubprogram FindSubprogram(DIScope scope) { 96b1928704201034c785a26296a49f69355eb56a05Nick Lewycky while (!scope.isSubprogram()) { 97b1928704201034c785a26296a49f69355eb56a05Nick Lewycky assert(scope.isLexicalBlock() && 98b1928704201034c785a26296a49f69355eb56a05Nick Lewycky "Debug location not lexical block or subprogram"); 99b1928704201034c785a26296a49f69355eb56a05Nick Lewycky scope = DILexicalBlock(scope).getContext(); 100b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 101b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return DISubprogram(scope); 102b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 103b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 104b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace { 105b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVRecord { 106b1928704201034c785a26296a49f69355eb56a05Nick Lewycky protected: 107b1928704201034c785a26296a49f69355eb56a05Nick Lewycky static const char *lines_tag; 108b1928704201034c785a26296a49f69355eb56a05Nick Lewycky static const char *function_tag; 109b1928704201034c785a26296a49f69355eb56a05Nick Lewycky static const char *block_tag; 110b1928704201034c785a26296a49f69355eb56a05Nick Lewycky static const char *edge_tag; 111b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 112b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVRecord() {} 113b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 114b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void WriteBytes(const char *b, int size) { 115b1928704201034c785a26296a49f69355eb56a05Nick Lewycky os->write(b, size); 116b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 117b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 118b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void Write(uint32_t i) { 119b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteBytes(reinterpret_cast<char*>(&i), 4); 120b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 121b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 122b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Returns the length measured in 4-byte blocks that will be used to 123b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // represent this string in a GCOV file 124b1928704201034c785a26296a49f69355eb56a05Nick Lewycky unsigned LengthOfGCOVString(StringRef s) { 125b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs 12617df2c3240837b4382898ead8c3ead407a338520Nick Lewycky // padding out to the next 4-byte word. The length is measured in 4-byte 12717df2c3240837b4382898ead8c3ead407a338520Nick Lewycky // words including padding, not bytes of actual string. 128b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return (s.size() + 5) / 4; 129b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 130b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 131b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void WriteGCOVString(StringRef s) { 132b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t len = LengthOfGCOVString(s); 133b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(len); 134b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteBytes(s.data(), s.size()); 135b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 136b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Write 1 to 4 bytes of NUL padding. 137b1928704201034c785a26296a49f69355eb56a05Nick Lewycky assert((unsigned)(5 - ((s.size() + 1) % 4)) > 0); 138b1928704201034c785a26296a49f69355eb56a05Nick Lewycky assert((unsigned)(5 - ((s.size() + 1) % 4)) <= 4); 139b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteBytes("\0\0\0\0", 5 - ((s.size() + 1) % 4)); 140b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 141b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 142b1928704201034c785a26296a49f69355eb56a05Nick Lewycky raw_ostream *os; 143b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 144b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const char *GCOVRecord::lines_tag = "\0\0\x45\x01"; 145b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const char *GCOVRecord::function_tag = "\0\0\0\1"; 146b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const char *GCOVRecord::block_tag = "\0\0\x41\x01"; 147b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const char *GCOVRecord::edge_tag = "\0\0\x43\x01"; 148b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 149b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVFunction; 150b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVBlock; 151b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 152b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Constructed only by requesting it from a GCOVBlock, this object stores a 153b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // list of line numbers and a single filename, representing lines that belong 154b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // to the block. 155b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVLines : public GCOVRecord { 156b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 157b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void AddLine(uint32_t line) { 158b1928704201034c785a26296a49f69355eb56a05Nick Lewycky lines.push_back(line); 159b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 160b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 161b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t Length() { 162b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return LengthOfGCOVString(filename) + 2 + lines.size(); 163b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 164b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 165b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 166b1928704201034c785a26296a49f69355eb56a05Nick Lewycky friend class GCOVBlock; 167b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 168b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVLines(std::string filename, raw_ostream *os) 169b1928704201034c785a26296a49f69355eb56a05Nick Lewycky : filename(filename) { 170b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 171b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 172b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 173b1928704201034c785a26296a49f69355eb56a05Nick Lewycky std::string filename; 174b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SmallVector<uint32_t, 32> lines; 175b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 176b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 177b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Represent a basic block in GCOV. Each block has a unique number in the 178b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // function, number of lines belonging to each block, and a set of edges to 179b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // other blocks. 180b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVBlock : public GCOVRecord { 181b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 182b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVLines &GetFile(std::string filename) { 183b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVLines *&lines = lines_by_file[filename]; 184b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (!lines) { 185b1928704201034c785a26296a49f69355eb56a05Nick Lewycky lines = new GCOVLines(filename, os); 186b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 187b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return *lines; 188b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 189b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 190b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void AddEdge(GCOVBlock &successor) { 191b1928704201034c785a26296a49f69355eb56a05Nick Lewycky out_edges.push_back(&successor); 192b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 193b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 194b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void WriteOut() { 195b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t len = 3; 196b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (StringMap<GCOVLines *>::iterator I = lines_by_file.begin(), 197b1928704201034c785a26296a49f69355eb56a05Nick Lewycky E = lines_by_file.end(); I != E; ++I) { 198b1928704201034c785a26296a49f69355eb56a05Nick Lewycky len += I->second->Length(); 199b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 200b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 201b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteBytes(lines_tag, 4); 202b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(len); 203b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(number); 204b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (StringMap<GCOVLines *>::iterator I = lines_by_file.begin(), 205b1928704201034c785a26296a49f69355eb56a05Nick Lewycky E = lines_by_file.end(); I != E; ++I) { 206b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(0); 207b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteGCOVString(I->second->filename); 208b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (int i = 0, e = I->second->lines.size(); i != e; ++i) { 209b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(I->second->lines[i]); 210b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 211b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 212b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(0); 213b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(0); 214b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 215b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 216b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ~GCOVBlock() { 217b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DeleteContainerSeconds(lines_by_file); 218b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 219b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 220b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 221b1928704201034c785a26296a49f69355eb56a05Nick Lewycky friend class GCOVFunction; 222b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 223b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVBlock(uint32_t number, raw_ostream *os) 224b1928704201034c785a26296a49f69355eb56a05Nick Lewycky : number(number) { 225b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 226b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 227b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 228b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t number; 229b1928704201034c785a26296a49f69355eb56a05Nick Lewycky BasicBlock *block; 230b1928704201034c785a26296a49f69355eb56a05Nick Lewycky StringMap<GCOVLines *> lines_by_file; 231b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SmallVector<GCOVBlock *, 4> out_edges; 232b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 233b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 234b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // A function has a unique identifier, a checksum (we leave as zero) and a 235b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // set of blocks and a map of edges between blocks. This is the only GCOV 236b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // object users can construct, the blocks and lines will be rooted here. 237b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVFunction : public GCOVRecord { 238b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 239b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVFunction(DISubprogram SP, raw_ostream *os) { 240b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 241b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 242b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Function *F = SP.getFunction(); 243b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t i = 0; 244b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 245b1928704201034c785a26296a49f69355eb56a05Nick Lewycky blocks[BB] = new GCOVBlock(i++, os); 246b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 247a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky return_block = new GCOVBlock(i++, os); 248b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 249b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteBytes(function_tag, 4); 250b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t block_len = 1 + 1 + 1 + LengthOfGCOVString(SP.getName()) + 251b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1 + LengthOfGCOVString(SP.getFilename()) + 1; 252b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(block_len); 253b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t ident = reinterpret_cast<intptr_t>((MDNode*)SP); 254b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(ident); 255b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(0); // checksum 256b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteGCOVString(SP.getName()); 257b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteGCOVString(SP.getFilename()); 258b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(SP.getLineNumber()); 259b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 260b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 261b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ~GCOVFunction() { 262b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DeleteContainerSeconds(blocks); 263a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky delete return_block; 264b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 265b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 266b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVBlock &GetBlock(BasicBlock *BB) { 267b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return *blocks[BB]; 268b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 269b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 270a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky GCOVBlock &GetReturnBlock() { 271a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky return *return_block; 272a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky } 273a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky 274b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void WriteOut() { 275b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit count of blocks. 276b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteBytes(block_tag, 4); 277a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky Write(blocks.size() + 1); 278a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky for (int i = 0, e = blocks.size() + 1; i != e; ++i) { 279b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(0); // No flags on our blocks. 280b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 281b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 282b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit edges between blocks. 283b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = blocks.begin(), 284b1928704201034c785a26296a49f69355eb56a05Nick Lewycky E = blocks.end(); I != E; ++I) { 285b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVBlock &block = *I->second; 286b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (block.out_edges.empty()) continue; 287b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 288b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteBytes(edge_tag, 4); 289b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(block.out_edges.size() * 2 + 1); 290b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(block.number); 291b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (int i = 0, e = block.out_edges.size(); i != e; ++i) { 292b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(block.out_edges[i]->number); 293b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Write(0); // no flags 294b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 295b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 296b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 297b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit lines for each block. 298b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = blocks.begin(), 299b1928704201034c785a26296a49f69355eb56a05Nick Lewycky E = blocks.end(); I != E; ++I) { 300b1928704201034c785a26296a49f69355eb56a05Nick Lewycky I->second->WriteOut(); 301b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 302b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 303b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 304b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 305b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DenseMap<BasicBlock *, GCOVBlock *> blocks; 306a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky GCOVBlock *return_block; 307b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 308b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 309b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3100c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky// Replace the stem of a file, or add one if missing. 3110c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewyckystatic std::string ReplaceStem(std::string orig_filename, std::string new_stem){ 3120c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky return (sys::path::stem(orig_filename) + "." + new_stem).str(); 3130c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky} 3140c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 3150c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewyckybool GCOVProfiler::runOnModule(Module &M) { 3160c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky Mod = &M; 3170c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky Ctx = &M.getContext(); 3180c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 3190c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky DebugInfoFinder DIF; 3200c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky DIF.processModule(*Mod); 3210c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 322a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky if (EmitNotes) EmitGCNO(DIF); 323a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky if (EmitData) return EmitProfileArcs(DIF); 324a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky return false; 3250c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky} 3260c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 327b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyvoid GCOVProfiler::EmitGCNO(DebugInfoFinder &DIF) { 328b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DenseMap<const MDNode *, raw_fd_ostream *> gcno_files; 329b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (DebugInfoFinder::iterator I = DIF.compile_unit_begin(), 330b1928704201034c785a26296a49f69355eb56a05Nick Lewycky E = DIF.compile_unit_end(); I != E; ++I) { 331b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Each compile unit gets its own .gcno file. This means that whether we run 332b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // this pass over the original .o's as they're produced, or run it after 333b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // LTO, we'll generate the same .gcno files. 334b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 335b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DICompileUnit CU(*I); 336b1928704201034c785a26296a49f69355eb56a05Nick Lewycky raw_fd_ostream *&Out = gcno_files[CU]; 337b1928704201034c785a26296a49f69355eb56a05Nick Lewycky std::string ErrorInfo; 3380c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky Out = new raw_fd_ostream(ReplaceStem(CU.getFilename(), "gcno").c_str(), 3390c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky ErrorInfo, raw_fd_ostream::F_Binary); 340b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Out->write("oncg*404MVLL", 12); 341b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 342b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 343b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(), 344b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) { 345b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DISubprogram SP(*SPI); 346b1928704201034c785a26296a49f69355eb56a05Nick Lewycky raw_fd_ostream *&os = gcno_files[SP.getCompileUnit()]; 347b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 348b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVFunction function(SP, os); 349b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Function *F = SP.getFunction(); 350b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 351b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVBlock &block = function.GetBlock(BB); 352b1928704201034c785a26296a49f69355eb56a05Nick Lewycky TerminatorInst *TI = BB->getTerminator(); 353b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (int successors = TI->getNumSuccessors()) { 354b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (int i = 0; i != successors; ++i) { 355b1928704201034c785a26296a49f69355eb56a05Nick Lewycky block.AddEdge(function.GetBlock(TI->getSuccessor(i))); 356b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 357a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky } else if (isa<ReturnInst>(TI)) { 358a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky block.AddEdge(function.GetReturnBlock()); 359b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 360b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 361b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t line = 0; 362b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) { 363b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const DebugLoc &loc = I->getDebugLoc(); 364b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (loc.isUnknown()) continue; 365b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (line == loc.getLine()) continue; 366b1928704201034c785a26296a49f69355eb56a05Nick Lewycky line = loc.getLine(); 367b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (SP != FindSubprogram(DIScope(loc.getScope(*Ctx)))) continue; 368b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 369b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GCOVLines &lines = block.GetFile(SP.getFilename()); 370b1928704201034c785a26296a49f69355eb56a05Nick Lewycky lines.AddLine(loc.getLine()); 371b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 372b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 373b1928704201034c785a26296a49f69355eb56a05Nick Lewycky function.WriteOut(); 374b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 375b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 376b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (DenseMap<const MDNode *, raw_fd_ostream *>::iterator 377b1928704201034c785a26296a49f69355eb56a05Nick Lewycky I = gcno_files.begin(), E = gcno_files.end(); I != E; ++I) { 378b1928704201034c785a26296a49f69355eb56a05Nick Lewycky raw_fd_ostream *&Out = I->second; 37917df2c3240837b4382898ead8c3ead407a338520Nick Lewycky Out->write("\0\0\0\0\0\0\0\0", 8); // EOF 380b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Out->close(); 381b1928704201034c785a26296a49f69355eb56a05Nick Lewycky delete Out; 382b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 383b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 384b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3850c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewyckybool GCOVProfiler::EmitProfileArcs(DebugInfoFinder &DIF) { 3860c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky if (DIF.subprogram_begin() == DIF.subprogram_end()) 3870c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky return false; 388b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 389b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SmallVector<std::pair<GlobalVariable *, uint32_t>, 8> counters_by_ident; 390b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(), 391b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) { 392b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DISubprogram SP(*SPI); 393b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Function *F = SP.getFunction(); 394b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 395b1928704201034c785a26296a49f69355eb56a05Nick Lewycky unsigned edges = 0; 396b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 397b1928704201034c785a26296a49f69355eb56a05Nick Lewycky TerminatorInst *TI = BB->getTerminator(); 398a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky if (isa<ReturnInst>(TI)) 399a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky ++edges; 400a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky else 401a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky edges += TI->getNumSuccessors(); 402b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 403b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 404b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const ArrayType *counter_type = 405b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ArrayType::get(Type::getInt64Ty(*Ctx), edges); 406b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GlobalVariable *counter = 407b1928704201034c785a26296a49f69355eb56a05Nick Lewycky new GlobalVariable(*Mod, counter_type, false, 408b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GlobalValue::InternalLinkage, 409b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant::getNullValue(counter_type), 410b1928704201034c785a26296a49f69355eb56a05Nick Lewycky "__llvm_gcov_ctr", 0, false, 0); 411b1928704201034c785a26296a49f69355eb56a05Nick Lewycky counters_by_ident.push_back( 412b1928704201034c785a26296a49f69355eb56a05Nick Lewycky std::make_pair(counter, reinterpret_cast<intptr_t>((MDNode*)SP))); 413b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 414b1928704201034c785a26296a49f69355eb56a05Nick Lewycky UniqueVector<BasicBlock *> complex_edge_preds; 415b1928704201034c785a26296a49f69355eb56a05Nick Lewycky UniqueVector<BasicBlock *> complex_edge_succs; 416b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 417b1928704201034c785a26296a49f69355eb56a05Nick Lewycky unsigned edge_num = 0; 418b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 419b1928704201034c785a26296a49f69355eb56a05Nick Lewycky TerminatorInst *TI = BB->getTerminator(); 420a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky int successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 421a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky if (successors) { 422b1928704201034c785a26296a49f69355eb56a05Nick Lewycky IRBuilder<> builder(TI); 423b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 424b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (successors == 1) { 425b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Value *ctr = builder.CreateConstInBoundsGEP2_64(counter, 0, edge_num); 426b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Value *count = builder.CreateLoad(ctr); 427b1928704201034c785a26296a49f69355eb56a05Nick Lewycky count = builder.CreateAdd(count, 428b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 429b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateStore(count, ctr); 430b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { 431b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Value *sel = builder.CreateSelect( 432b1928704201034c785a26296a49f69355eb56a05Nick Lewycky BI->getCondition(), 433b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ConstantInt::get(Type::getInt64Ty(*Ctx), edge_num), 434b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ConstantInt::get(Type::getInt64Ty(*Ctx), edge_num + 1)); 435b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SmallVector<Value *, 2> idx; 436b1928704201034c785a26296a49f69355eb56a05Nick Lewycky idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx))); 437b1928704201034c785a26296a49f69355eb56a05Nick Lewycky idx.push_back(sel); 438b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Value *ctr = builder.CreateInBoundsGEP(counter, 439b1928704201034c785a26296a49f69355eb56a05Nick Lewycky idx.begin(), idx.end()); 440b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Value *count = builder.CreateLoad(ctr); 441b1928704201034c785a26296a49f69355eb56a05Nick Lewycky count = builder.CreateAdd(count, 442b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 443b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateStore(count, ctr); 444b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } else { 445b1928704201034c785a26296a49f69355eb56a05Nick Lewycky complex_edge_preds.insert(BB); 446b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (int i = 0; i != successors; ++i) { 447b1928704201034c785a26296a49f69355eb56a05Nick Lewycky complex_edge_succs.insert(TI->getSuccessor(i)); 448b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 449b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 450b1928704201034c785a26296a49f69355eb56a05Nick Lewycky edge_num += successors; 451b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 452b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 453b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 454b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // TODO: support switch, invoke, indirectbr 455b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (!complex_edge_preds.empty()) { 456b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // emit a [preds x [succs x i64*]]. 457b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (int i = 0, e = complex_edge_preds.size(); i != e; ++i) { 458b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // call runtime to state save 459b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 460b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (int i = 0, e = complex_edge_succs.size(); i != e; ++i) { 461b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // call runtime to perform increment 462b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 463b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 464b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 465b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 466b1928704201034c785a26296a49f69355eb56a05Nick Lewycky InsertCounterWriteout(DIF, counters_by_ident); 467b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 468b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return true; 469b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 470b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 471b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getStartFileFunc() { 472b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) }; 473b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 474b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Args, false); 475b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return Mod->getOrInsertFunction("llvm_gcda_start_file", FTy); 476b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 477b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 478b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitFunctionFunc() { 479b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const Type *Args[1] = { Type::getInt32Ty(*Ctx) }; 480b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 481b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Args, false); 482b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return Mod->getOrInsertFunction("llvm_gcda_emit_function", FTy); 483b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 484b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 485b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitArcsFunc() { 486b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const Type *Args[] = { 487b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Type::getInt32Ty(*Ctx), // uint32_t num_counters 488b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Type::getInt64PtrTy(*Ctx), // uint64_t *counters 489b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 490b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 491b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Args, false); 492b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return Mod->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); 493b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 494b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 495b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEndFileFunc() { 496b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 497b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return Mod->getOrInsertFunction("llvm_gcda_end_file", FTy); 498b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 499b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 500b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyvoid GCOVProfiler::InsertCounterWriteout( 501b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DebugInfoFinder &DIF, 502b1928704201034c785a26296a49f69355eb56a05Nick Lewycky SmallVector<std::pair<GlobalVariable *, uint32_t>, 8> &counters_by_ident) { 503b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 504b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const FunctionType *WriteoutFTy = 505b1928704201034c785a26296a49f69355eb56a05Nick Lewycky FunctionType::get(Type::getVoidTy(*Ctx), false); 506b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Function *WriteoutF = Function::Create(WriteoutFTy, 507b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GlobalValue::InternalLinkage, 508b1928704201034c785a26296a49f69355eb56a05Nick Lewycky "__llvm_gcda_writeout", Mod); 509b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteoutF->setUnnamedAddr(true); 510b1928704201034c785a26296a49f69355eb56a05Nick Lewycky BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); 511b1928704201034c785a26296a49f69355eb56a05Nick Lewycky IRBuilder<> builder(BB); 512b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 513b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *StartFile = getStartFileFunc(); 514b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EmitFunction = getEmitFunctionFunc(); 515b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EmitArcs = getEmitArcsFunc(); 516b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EndFile = getEndFileFunc(); 517b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 518b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (DebugInfoFinder::iterator CUI = DIF.compile_unit_begin(), 519b1928704201034c785a26296a49f69355eb56a05Nick Lewycky CUE = DIF.compile_unit_end(); CUI != CUE; ++CUI) { 520b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DICompileUnit compile_unit(*CUI); 521b1928704201034c785a26296a49f69355eb56a05Nick Lewycky std::string filename_gcda = ReplaceStem(compile_unit.getFilename(), "gcda"); 522b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateCall(StartFile, 523b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateGlobalStringPtr(filename_gcda)); 524b1928704201034c785a26296a49f69355eb56a05Nick Lewycky for (SmallVector<std::pair<GlobalVariable *, uint32_t>, 8>::iterator 525b1928704201034c785a26296a49f69355eb56a05Nick Lewycky I = counters_by_ident.begin(), E = counters_by_ident.end(); 526b1928704201034c785a26296a49f69355eb56a05Nick Lewycky I != E; ++I) { 527b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateCall(EmitFunction, ConstantInt::get(Type::getInt32Ty(*Ctx), 528b1928704201034c785a26296a49f69355eb56a05Nick Lewycky I->second)); 529b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GlobalVariable *GV = I->first; 530b1928704201034c785a26296a49f69355eb56a05Nick Lewycky unsigned num_arcs = 531b1928704201034c785a26296a49f69355eb56a05Nick Lewycky cast<ArrayType>(GV->getType()->getElementType())->getNumElements(); 532b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateCall2( 533b1928704201034c785a26296a49f69355eb56a05Nick Lewycky EmitArcs, 534b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ConstantInt::get(Type::getInt32Ty(*Ctx), num_arcs), 535b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateConstGEP2_64(GV, 0, 0)); 536b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 537b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateCall(EndFile); 538b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 539b1928704201034c785a26296a49f69355eb56a05Nick Lewycky builder.CreateRetVoid(); 540b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 541b1928704201034c785a26296a49f69355eb56a05Nick Lewycky InsertProfilingShutdownCall(WriteoutF, Mod); 542b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 543