119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===// 219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// The LLVM Compiler Infrastructure 419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file is distributed under the University of Illinois Open Source 619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// License. See LICENSE.TXT for details. 719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===// 919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 1019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This pass implements GCOV-style profiling. When this pass is run it emits 1119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// "gcno" files next to the existing source, and instruments the code that runs 1219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// to records the edges between blocks that run and emit a complementary "gcda" 1319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// file on exit. 1419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===// 1619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#define DEBUG_TYPE "insert-gcov-profiling" 1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "ProfilingUtils.h" 2019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Transforms/Instrumentation.h" 2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Analysis/DebugInfo.h" 2219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Module.h" 2319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Pass.h" 2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Instructions.h" 2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/raw_ostream.h" 2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/Debug.h" 2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/DebugLoc.h" 2819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/InstIterator.h" 2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/IRBuilder.h" 3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/PathV2.h" 3119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/DenseMap.h" 3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/Statistic.h" 3319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/STLExtras.h" 3419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/StringExtras.h" 3519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/StringMap.h" 3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/UniqueVector.h" 3719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include <string> 3819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include <utility> 3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanusing namespace llvm; 4019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 4119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace { 4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class GCOVProfiler : public ModulePass { 4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public: 4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman static char ID; 4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVProfiler() 4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman : ModulePass(ID), EmitNotes(true), EmitData(true), Use402Format(false) { 4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 4919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVProfiler(bool EmitNotes, bool EmitData, bool use402Format = false) 5019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman : ModulePass(ID), EmitNotes(EmitNotes), EmitData(EmitData), 5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Use402Format(use402Format) { 5219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman assert((EmitNotes || EmitData) && "GCOVProfiler asked to do nothing?"); 5319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman virtual const char *getPassName() const { 5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return "GCOV Profiler"; 5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 5919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman private: 6019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool runOnModule(Module &M); 6119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Create the GCNO files for the Module based on DebugInfo. 6319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void emitGCNO(); 6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Modify the program to track transitions along edges and call into the 6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // profiling runtime to emit .gcda files when run. 6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool emitProfileArcs(); 6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Get pointers to the functions in the runtime library. 7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *getStartFileFunc(); 7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *getIncrementIndirectCounterFunc(); 7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *getEmitFunctionFunc(); 7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *getEmitArcsFunc(); 7419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *getEndFileFunc(); 7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Create or retrieve an i32 state value that is used to represent the 7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // pred block number for certain non-trivial edges. 7819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *getEdgeStateValue(); 7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Produce a table of pointers to counters, by predecessor and successor 8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // block number. 8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *buildEdgeLookupTable(Function *F, 8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *Counter, 8419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const UniqueVector<BasicBlock *> &Preds, 8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const UniqueVector<BasicBlock *> &Succs); 8619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 8719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Add the function to write out all our counters to the global destructor 8819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // list. 8919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void insertCounterWriteout(SmallVector<std::pair<GlobalVariable *, 9019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MDNode *>, 8> &); 9119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 9219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman std::string mangleName(DICompileUnit CU, std::string NewStem); 9319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 9419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool EmitNotes; 9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool EmitData; 9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool Use402Format; 9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Module *M; 9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman LLVMContext *Ctx; 10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanchar GCOVProfiler::ID = 0; 10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanINITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling", 10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman "Insert instrumentation for GCOV profiling", false, false) 10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 10719bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanModulePass *llvm::createGCOVProfilerPass(bool EmitNotes, bool EmitData, 10819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool Use402Format) { 10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return new GCOVProfiler(EmitNotes, EmitData, Use402Format); 11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 11119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace { 11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class GCOVRecord { 11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman protected: 11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman static const char *LinesTag; 11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman static const char *FunctionTag; 11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman static const char *BlockTag; 11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman static const char *EdgeTag; 11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVRecord() {} 12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void writeBytes(const char *Bytes, int Size) { 12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman os->write(Bytes, Size); 12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void write(uint32_t i) { 12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeBytes(reinterpret_cast<char*>(&i), 4); 12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Returns the length measured in 4-byte blocks that will be used to 13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // represent this string in a GCOV file 13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned lengthOfGCOVString(StringRef s) { 13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs 13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // padding out to the next 4-byte word. The length is measured in 4-byte 13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // words including padding, not bytes of actual string. 13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return (s.size() / 4) + 1; 13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void writeGCOVString(StringRef s) { 14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t Len = lengthOfGCOVString(s); 14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Len); 14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeBytes(s.data(), s.size()); 14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Write 1 to 4 bytes of NUL padding. 14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman assert((unsigned)(4 - (s.size() % 4)) > 0); 14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman assert((unsigned)(4 - (s.size() % 4)) <= 4); 14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeBytes("\0\0\0\0", 4 - (s.size() % 4)); 14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_ostream *os; 15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const char *GCOVRecord::LinesTag = "\0\0\x45\x01"; 15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const char *GCOVRecord::FunctionTag = "\0\0\0\1"; 15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const char *GCOVRecord::BlockTag = "\0\0\x41\x01"; 15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const char *GCOVRecord::EdgeTag = "\0\0\x43\x01"; 15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class GCOVFunction; 15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class GCOVBlock; 15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Constructed only by requesting it from a GCOVBlock, this object stores a 16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // list of line numbers and a single filename, representing lines that belong 16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // to the block. 16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class GCOVLines : public GCOVRecord { 16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public: 16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void addLine(uint32_t Line) { 16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Lines.push_back(Line); 16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 16819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t length() { 17019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Here 2 = 1 for string lenght + 1 for '0' id#. 17119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return lengthOfGCOVString(Filename) + 2 + Lines.size(); 17219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 17319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 17419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void writeOut() { 17519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(0); 17619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeGCOVString(Filename); 17719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0, e = Lines.size(); i != e; ++i) 17819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Lines[i]); 17919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 18019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 18119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVLines(StringRef F, raw_ostream *os) 18219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman : Filename(F) { 18319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman this->os = os; 18419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 18519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 18619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman private: 18719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman StringRef Filename; 18819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SmallVector<uint32_t, 32> Lines; 18919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 19019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 19119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Represent a basic block in GCOV. Each block has a unique number in the 19219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // function, number of lines belonging to each block, and a set of edges to 19319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // other blocks. 19419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class GCOVBlock : public GCOVRecord { 19519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public: 19619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVLines &getFile(StringRef Filename) { 19719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVLines *&Lines = LinesByFile[Filename]; 19819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Lines) { 19919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Lines = new GCOVLines(Filename, os); 20019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 20119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return *Lines; 20219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 20319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 20419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void addEdge(GCOVBlock &Successor) { 20519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OutEdges.push_back(&Successor); 20619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 20719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 20819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void writeOut() { 20919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t Len = 3; 21019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), 21119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman E = LinesByFile.end(); I != E; ++I) { 21219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Len += I->second->length(); 21319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 21419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 21519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeBytes(LinesTag, 4); 21619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Len); 21719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Number); 21819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), 21919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman E = LinesByFile.end(); I != E; ++I) 22019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman I->second->writeOut(); 22119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(0); 22219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(0); 22319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 22419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 22519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ~GCOVBlock() { 22619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DeleteContainerSeconds(LinesByFile); 22719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 22819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 22919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman private: 23019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman friend class GCOVFunction; 23119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 23219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVBlock(uint32_t Number, raw_ostream *os) 23319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman : Number(Number) { 23419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman this->os = os; 23519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 23619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 23719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t Number; 23819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman StringMap<GCOVLines *> LinesByFile; 23919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SmallVector<GCOVBlock *, 4> OutEdges; 24019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 24119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 24219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // A function has a unique identifier, a checksum (we leave as zero) and a 24319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // set of blocks and a map of edges between blocks. This is the only GCOV 24419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // object users can construct, the blocks and lines will be rooted here. 24519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman class GCOVFunction : public GCOVRecord { 24619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman public: 24719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVFunction(DISubprogram SP, raw_ostream *os, bool Use402Format) { 24819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman this->os = os; 24919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 25019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Function *F = SP.getFunction(); 25119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t i = 0; 25219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 25319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Blocks[BB] = new GCOVBlock(i++, os); 25419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 25519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ReturnBlock = new GCOVBlock(i++, os); 25619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 25719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeBytes(FunctionTag, 4); 25819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(SP.getName()) + 25919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1 + lengthOfGCOVString(SP.getFilename()) + 1; 26019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Use402Format) 26119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ++BlockLen; // For second checksum. 26219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(BlockLen); 26319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t Ident = reinterpret_cast<intptr_t>((MDNode*)SP); 26419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Ident); 26519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(0); // checksum #1 26619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Use402Format) 26719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(0); // checksum #2 26819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeGCOVString(SP.getName()); 26919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeGCOVString(SP.getFilename()); 27019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(SP.getLineNumber()); 27119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 27219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 27319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ~GCOVFunction() { 27419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DeleteContainerSeconds(Blocks); 27519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman delete ReturnBlock; 27619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 27719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 27819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVBlock &getBlock(BasicBlock *BB) { 27919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return *Blocks[BB]; 28019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 28119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 28219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVBlock &getReturnBlock() { 28319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return *ReturnBlock; 28419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 28519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 28619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman void writeOut() { 28719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Emit count of blocks. 28819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeBytes(BlockTag, 4); 28919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Blocks.size() + 1); 29019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0, e = Blocks.size() + 1; i != e; ++i) { 29119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(0); // No flags on our blocks. 29219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 29319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 29419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Emit edges between blocks. 29519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(), 29619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman E = Blocks.end(); I != E; ++I) { 29719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVBlock &Block = *I->second; 29819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Block.OutEdges.empty()) continue; 29919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 30019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman writeBytes(EdgeTag, 4); 30119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Block.OutEdges.size() * 2 + 1); 30219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Block.Number); 30319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) { 30419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(Block.OutEdges[i]->Number); 30519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman write(0); // no flags 30619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 30719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 30819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 30919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Emit lines for each block. 31019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(), 31119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman E = Blocks.end(); I != E; ++I) { 31219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman I->second->writeOut(); 31319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 31419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 31519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 31619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman private: 31719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DenseMap<BasicBlock *, GCOVBlock *> Blocks; 31819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVBlock *ReturnBlock; 31919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 32019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 32119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 32219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstd::string GCOVProfiler::mangleName(DICompileUnit CU, std::string NewStem) { 32319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) { 32419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) { 32519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MDNode *N = GCov->getOperand(i); 32619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (N->getNumOperands() != 2) continue; 32719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0)); 32819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MDNode *CompileUnit = dyn_cast<MDNode>(N->getOperand(1)); 32919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!GCovFile || !CompileUnit) continue; 33019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (CompileUnit == CU) { 33119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SmallString<128> Filename = GCovFile->getString(); 33219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman sys::path::replace_extension(Filename, NewStem); 33319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Filename.str(); 33419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 33519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 33619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 33719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 33819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SmallString<128> Filename = CU.getFilename(); 33919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman sys::path::replace_extension(Filename, NewStem); 34019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return sys::path::filename(Filename.str()); 34119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 34219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 34319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool GCOVProfiler::runOnModule(Module &M) { 34419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman this->M = &M; 34519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Ctx = &M.getContext(); 34619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 34719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (EmitNotes) emitGCNO(); 34819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (EmitData) return emitProfileArcs(); 34919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return false; 35019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 35119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 35219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid GCOVProfiler::emitGCNO() { 35319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DenseMap<const MDNode *, raw_fd_ostream *> GcnoFiles; 35419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 35519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (CU_Nodes) { 35619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 35719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Each compile unit gets its own .gcno file. This means that whether we run 35819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // this pass over the original .o's as they're produced, or run it after 35919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // LTO, we'll generate the same .gcno files. 36019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 36119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DICompileUnit CU(CU_Nodes->getOperand(i)); 36219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_fd_ostream *&out = GcnoFiles[CU]; 36319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman std::string ErrorInfo; 36419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman out = new raw_fd_ostream(mangleName(CU, "gcno").c_str(), ErrorInfo, 36519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_fd_ostream::F_Binary); 36619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Use402Format) 36719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman out->write("oncg*404MVLL", 12); 36819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else 36919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman out->write("oncg*204MVLL", 12); 37019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 37119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DIArray SPs = CU.getSubprograms(); 37219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { 37319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DISubprogram SP(SPs.getElement(i)); 37419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!SP.Verify()) continue; 37519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_fd_ostream *&os = GcnoFiles[CU]; 37619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 37719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Function *F = SP.getFunction(); 37819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!F) continue; 37919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVFunction Func(SP, os, Use402Format); 38019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 38119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 38219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVBlock &Block = Func.getBlock(BB); 38319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman TerminatorInst *TI = BB->getTerminator(); 38419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (int successors = TI->getNumSuccessors()) { 38519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0; i != successors; ++i) { 38619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Block.addEdge(Func.getBlock(TI->getSuccessor(i))); 38719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 38819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } else if (isa<ReturnInst>(TI)) { 38919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Block.addEdge(Func.getReturnBlock()); 39019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 39119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 39219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t Line = 0; 39319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) { 39419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const DebugLoc &Loc = I->getDebugLoc(); 39519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Loc.isUnknown()) continue; 39619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Line == Loc.getLine()) continue; 39719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Line = Loc.getLine(); 39819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (SP != getDISubprogram(Loc.getScope(*Ctx))) continue; 39919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 40019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GCOVLines &Lines = Block.getFile(SP.getFilename()); 40119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Lines.addLine(Loc.getLine()); 40219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 40319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 40419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Func.writeOut(); 40519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 40619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 40719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 40819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 40919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (DenseMap<const MDNode *, raw_fd_ostream *>::iterator 41019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman I = GcnoFiles.begin(), E = GcnoFiles.end(); I != E; ++I) { 41119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman raw_fd_ostream *&out = I->second; 41219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman out->write("\0\0\0\0\0\0\0\0", 8); // EOF 41319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman out->close(); 41419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman delete out; 41519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 41619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 41719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 41819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool GCOVProfiler::emitProfileArcs() { 41919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 42019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!CU_Nodes) return false; 42119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 42219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool Result = false; 42319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 42419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DICompileUnit CU(CU_Nodes->getOperand(i)); 42519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DIArray SPs = CU.getSubprograms(); 42619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; 42719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { 42819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DISubprogram SP(SPs.getElement(i)); 42919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!SP.Verify()) continue; 43019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Function *F = SP.getFunction(); 43119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!F) continue; 43219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Result) Result = true; 43319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned Edges = 0; 43419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 43519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman TerminatorInst *TI = BB->getTerminator(); 43619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (isa<ReturnInst>(TI)) 43719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ++Edges; 43819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else 43919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Edges += TI->getNumSuccessors(); 44019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 44119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 44219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ArrayType *CounterTy = 44319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ArrayType::get(Type::getInt64Ty(*Ctx), Edges); 44419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *Counters = 44519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman new GlobalVariable(*M, CounterTy, false, 44619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalValue::InternalLinkage, 44719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant::getNullValue(CounterTy), 44819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman "__llvm_gcov_ctr", 0, false, 0); 44919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman CountersBySP.push_back(std::make_pair(Counters, (MDNode*)SP)); 45019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 45119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman UniqueVector<BasicBlock *> ComplexEdgePreds; 45219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman UniqueVector<BasicBlock *> ComplexEdgeSuccs; 45319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 45419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned Edge = 0; 45519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 45619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman TerminatorInst *TI = BB->getTerminator(); 45719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 45819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Successors) { 45919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman IRBuilder<> Builder(TI); 46019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 46119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Successors == 1) { 46219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, 46319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Edge); 46419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Value *Count = Builder.CreateLoad(Counter); 46519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Count = Builder.CreateAdd(Count, 46619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 46719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateStore(Count, Counter); 46819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { 46919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Value *Sel = Builder.CreateSelect( 47019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman BI->getCondition(), 47119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantInt::get(Type::getInt64Ty(*Ctx), Edge), 47219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantInt::get(Type::getInt64Ty(*Ctx), Edge + 1)); 47319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SmallVector<Value *, 2> Idx; 47419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx))); 47519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Idx.push_back(Sel); 47619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Value *Counter = Builder.CreateInBoundsGEP(Counters, Idx); 47719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Value *Count = Builder.CreateLoad(Counter); 47819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Count = Builder.CreateAdd(Count, 47919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 48019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateStore(Count, Counter); 48119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } else { 48219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ComplexEdgePreds.insert(BB); 48319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0; i != Successors; ++i) 48419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ComplexEdgeSuccs.insert(TI->getSuccessor(i)); 48519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 48619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Edge += Successors; 48719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 48819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 48919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 49019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!ComplexEdgePreds.empty()) { 49119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *EdgeTable = 49219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman buildEdgeLookupTable(F, Counters, 49319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ComplexEdgePreds, ComplexEdgeSuccs); 49419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *EdgeState = getEdgeStateValue(); 49519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 49619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type *Int32Ty = Type::getInt32Ty(*Ctx); 49719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { 49819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator()); 49919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState); 50019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 50119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { 50219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // call runtime to perform increment 50319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman BasicBlock::iterator InsertPt = 50419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ComplexEdgeSuccs[i+1]->getFirstInsertionPt(); 50519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman IRBuilder<> Builder(InsertPt); 50619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Value *CounterPtrArray = 50719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, 50819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman i * ComplexEdgePreds.size()); 50919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateCall2(getIncrementIndirectCounterFunc(), 51019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EdgeState, CounterPtrArray); 51119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // clear the predecessor number 51219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState); 51319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 51419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 51519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 51619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman insertCounterWriteout(CountersBySP); 51719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 51819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Result; 51919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 52019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 52119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// All edges with successors that aren't branches are "complex", because it 52219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// requires complex logic to pick which counter to update. 52319bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanGlobalVariable *GCOVProfiler::buildEdgeLookupTable( 52419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Function *F, 52519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *Counters, 52619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const UniqueVector<BasicBlock *> &Preds, 52719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const UniqueVector<BasicBlock *> &Succs) { 52819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // TODO: support invoke, threads. We rely on the fact that nothing can modify 52919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // the whole-Module pred edge# between the time we set it and the time we next 53019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // read it. Threads and invoke make this untrue. 53119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 53219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]]. 53319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); 53419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ArrayType *EdgeTableTy = ArrayType::get( 53519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Int64PtrTy, Succs.size() * Preds.size()); 53619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 53719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant **EdgeTable = new Constant*[Succs.size() * Preds.size()]; 53819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *NullValue = Constant::getNullValue(Int64PtrTy); 53919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0, ie = Succs.size() * Preds.size(); i != ie; ++i) 54019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EdgeTable[i] = NullValue; 54119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 54219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned Edge = 0; 54319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 54419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman TerminatorInst *TI = BB->getTerminator(); 54519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 54619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) { 54719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (int i = 0; i != Successors; ++i) { 54819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman BasicBlock *Succ = TI->getSuccessor(i); 54919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman IRBuilder<> builder(Succ); 55019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Value *Counter = builder.CreateConstInBoundsGEP2_64(Counters, 0, 55119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Edge + i); 55219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EdgeTable[((Succs.idFor(Succ)-1) * Preds.size()) + 55319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman (Preds.idFor(BB)-1)] = cast<Constant>(Counter); 55419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 55519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 55619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Edge += Successors; 55719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 55819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 55919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ArrayRef<Constant*> V(&EdgeTable[0], Succs.size() * Preds.size()); 56019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *EdgeTableGV = 56119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman new GlobalVariable( 56219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman *M, EdgeTableTy, true, GlobalValue::InternalLinkage, 56319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantArray::get(EdgeTableTy, V), 56419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman "__llvm_gcda_edge_table"); 56519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EdgeTableGV->setUnnamedAddr(true); 56619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return EdgeTableGV; 56719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 56819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 56919bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanConstant *GCOVProfiler::getStartFileFunc() { 57019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 57119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type::getInt8PtrTy(*Ctx), false); 57219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return M->getOrInsertFunction("llvm_gcda_start_file", FTy); 57319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 57419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 57519bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanConstant *GCOVProfiler::getIncrementIndirectCounterFunc() { 57619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type *Args[] = { 57719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type::getInt32PtrTy(*Ctx), // uint32_t *predecessor 57819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type::getInt64PtrTy(*Ctx)->getPointerTo(), // uint64_t **state_table_row 57919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 58019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 58119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Args, false); 58219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return M->getOrInsertFunction("llvm_gcda_increment_indirect_counter", FTy); 58319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 58419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 58519bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanConstant *GCOVProfiler::getEmitFunctionFunc() { 58619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type *Args[2] = { 58719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type::getInt32Ty(*Ctx), // uint32_t ident 58819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type::getInt8PtrTy(*Ctx), // const char *function_name 58919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 59019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 59119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Args, false); 59219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); 59319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 59419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 59519bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanConstant *GCOVProfiler::getEmitArcsFunc() { 59619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type *Args[] = { 59719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type::getInt32Ty(*Ctx), // uint32_t num_counters 59819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Type::getInt64PtrTy(*Ctx), // uint64_t *counters 59919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 60019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 60119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Args, false); 60219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); 60319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 60419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 60519bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanConstant *GCOVProfiler::getEndFileFunc() { 60619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 60719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return M->getOrInsertFunction("llvm_gcda_end_file", FTy); 60819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 60919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 61019bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanGlobalVariable *GCOVProfiler::getEdgeStateValue() { 61119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred"); 61219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!GV) { 61319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false, 61419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalValue::InternalLinkage, 61519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantInt::get(Type::getInt32Ty(*Ctx), 61619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 0xffffffff), 61719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman "__llvm_gcov_global_state_pred"); 61819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GV->setUnnamedAddr(true); 61919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 62019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return GV; 62119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 62219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 62319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid GCOVProfiler::insertCounterWriteout( 62419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> &CountersBySP) { 62519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman FunctionType *WriteoutFTy = 62619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman FunctionType::get(Type::getVoidTy(*Ctx), false); 62719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Function *WriteoutF = Function::Create(WriteoutFTy, 62819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalValue::InternalLinkage, 62919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman "__llvm_gcov_writeout", M); 63019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman WriteoutF->setUnnamedAddr(true); 63119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); 63219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman IRBuilder<> Builder(BB); 63319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 63419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *StartFile = getStartFileFunc(); 63519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *EmitFunction = getEmitFunctionFunc(); 63619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *EmitArcs = getEmitArcsFunc(); 63719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Constant *EndFile = getEndFileFunc(); 63819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 63919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 64019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (CU_Nodes) { 64119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 64219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DICompileUnit compile_unit(CU_Nodes->getOperand(i)); 64319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman std::string FilenameGcda = mangleName(compile_unit, "gcda"); 64419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateCall(StartFile, 64519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateGlobalStringPtr(FilenameGcda)); 64619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (SmallVector<std::pair<GlobalVariable *, MDNode *>, 8>::iterator 64719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman I = CountersBySP.begin(), E = CountersBySP.end(); 64819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman I != E; ++I) { 64919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DISubprogram SP(I->second); 65019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman intptr_t ident = reinterpret_cast<intptr_t>(I->second); 65119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateCall2(EmitFunction, 65219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantInt::get(Type::getInt32Ty(*Ctx), ident), 65319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateGlobalStringPtr(SP.getName())); 65419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 65519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman GlobalVariable *GV = I->first; 65619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned Arcs = 65719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman cast<ArrayType>(GV->getType()->getElementType())->getNumElements(); 65819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateCall2(EmitArcs, 65919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ConstantInt::get(Type::getInt32Ty(*Ctx), Arcs), 66019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateConstGEP2_64(GV, 0, 0)); 66119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 66219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateCall(EndFile); 66319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 66419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 66519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Builder.CreateRetVoid(); 66619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 66719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman InsertProfilingShutdownCall(WriteoutF, M); 66819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 669