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