1221337Sdim//===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===//
2221337Sdim//
3221337Sdim//                      The LLVM Compiler Infrastructure
4221337Sdim//
5221337Sdim// This file is distributed under the University of Illinois Open Source
6221337Sdim// License. See LICENSE.TXT for details.
7221337Sdim//
8221337Sdim//===----------------------------------------------------------------------===//
9221337Sdim//
10221337Sdim// This pass implements GCOV-style profiling. When this pass is run it emits
11221337Sdim// "gcno" files next to the existing source, and instruments the code that runs
12221337Sdim// to records the edges between blocks that run and emit a complementary "gcda"
13221337Sdim// file on exit.
14221337Sdim//
15221337Sdim//===----------------------------------------------------------------------===//
16221337Sdim
17221337Sdim#define DEBUG_TYPE "insert-gcov-profiling"
18221337Sdim
19252723Sdim#include "llvm/Transforms/Instrumentation.h"
20221337Sdim#include "llvm/ADT/DenseMap.h"
21245431Sdim#include "llvm/ADT/STLExtras.h"
22221337Sdim#include "llvm/ADT/Statistic.h"
23221337Sdim#include "llvm/ADT/StringExtras.h"
24221337Sdim#include "llvm/ADT/StringMap.h"
25221337Sdim#include "llvm/ADT/UniqueVector.h"
26252723Sdim#include "llvm/DebugInfo.h"
27252723Sdim#include "llvm/IR/IRBuilder.h"
28252723Sdim#include "llvm/IR/Instructions.h"
29252723Sdim#include "llvm/IR/Module.h"
30252723Sdim#include "llvm/Pass.h"
31252723Sdim#include "llvm/Support/CommandLine.h"
32245431Sdim#include "llvm/Support/Debug.h"
33245431Sdim#include "llvm/Support/DebugLoc.h"
34252723Sdim#include "llvm/Support/FileSystem.h"
35245431Sdim#include "llvm/Support/InstIterator.h"
36263509Sdim#include "llvm/Support/Path.h"
37245431Sdim#include "llvm/Support/raw_ostream.h"
38245431Sdim#include "llvm/Transforms/Utils/ModuleUtils.h"
39263509Sdim#include <algorithm>
40221337Sdim#include <string>
41221337Sdim#include <utility>
42221337Sdimusing namespace llvm;
43221337Sdim
44252723Sdimstatic cl::opt<std::string>
45252723SdimDefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden,
46252723Sdim                   cl::ValueRequired);
47252723Sdim
48252723SdimGCOVOptions GCOVOptions::getDefault() {
49252723Sdim  GCOVOptions Options;
50252723Sdim  Options.EmitNotes = true;
51252723Sdim  Options.EmitData = true;
52252723Sdim  Options.UseCfgChecksum = false;
53252723Sdim  Options.NoRedZone = false;
54252723Sdim  Options.FunctionNamesInData = true;
55252723Sdim
56252723Sdim  if (DefaultGCOVVersion.size() != 4) {
57252723Sdim    llvm::report_fatal_error(std::string("Invalid -default-gcov-version: ") +
58252723Sdim                             DefaultGCOVVersion);
59252723Sdim  }
60252723Sdim  memcpy(Options.Version, DefaultGCOVVersion.c_str(), 4);
61252723Sdim  return Options;
62252723Sdim}
63252723Sdim
64221337Sdimnamespace {
65221337Sdim  class GCOVProfiler : public ModulePass {
66221337Sdim  public:
67221337Sdim    static char ID;
68252723Sdim    GCOVProfiler() : ModulePass(ID), Options(GCOVOptions::getDefault()) {
69252723Sdim      ReversedVersion[0] = Options.Version[3];
70252723Sdim      ReversedVersion[1] = Options.Version[2];
71252723Sdim      ReversedVersion[2] = Options.Version[1];
72252723Sdim      ReversedVersion[3] = Options.Version[0];
73252723Sdim      ReversedVersion[4] = '\0';
74221337Sdim      initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
75221337Sdim    }
76252723Sdim    GCOVProfiler(const GCOVOptions &Options) : ModulePass(ID), Options(Options){
77252723Sdim      assert((Options.EmitNotes || Options.EmitData) &&
78252723Sdim             "GCOVProfiler asked to do nothing?");
79252723Sdim      ReversedVersion[0] = Options.Version[3];
80252723Sdim      ReversedVersion[1] = Options.Version[2];
81252723Sdim      ReversedVersion[2] = Options.Version[1];
82252723Sdim      ReversedVersion[3] = Options.Version[0];
83252723Sdim      ReversedVersion[4] = '\0';
84221337Sdim      initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
85221337Sdim    }
86221337Sdim    virtual const char *getPassName() const {
87221337Sdim      return "GCOV Profiler";
88221337Sdim    }
89252723Sdim
90221337Sdim  private:
91223017Sdim    bool runOnModule(Module &M);
92223017Sdim
93252723Sdim    // Create the .gcno files for the Module based on DebugInfo.
94252723Sdim    void emitProfileNotes();
95221337Sdim
96221337Sdim    // Modify the program to track transitions along edges and call into the
97221337Sdim    // profiling runtime to emit .gcda files when run.
98226890Sdim    bool emitProfileArcs();
99221337Sdim
100221337Sdim    // Get pointers to the functions in the runtime library.
101221337Sdim    Constant *getStartFileFunc();
102221337Sdim    Constant *getIncrementIndirectCounterFunc();
103221337Sdim    Constant *getEmitFunctionFunc();
104221337Sdim    Constant *getEmitArcsFunc();
105263509Sdim    Constant *getSummaryInfoFunc();
106252723Sdim    Constant *getDeleteWriteoutFunctionListFunc();
107252723Sdim    Constant *getDeleteFlushFunctionListFunc();
108221337Sdim    Constant *getEndFileFunc();
109221337Sdim
110221337Sdim    // Create or retrieve an i32 state value that is used to represent the
111221337Sdim    // pred block number for certain non-trivial edges.
112221337Sdim    GlobalVariable *getEdgeStateValue();
113221337Sdim
114221337Sdim    // Produce a table of pointers to counters, by predecessor and successor
115221337Sdim    // block number.
116221337Sdim    GlobalVariable *buildEdgeLookupTable(Function *F,
117221337Sdim                                         GlobalVariable *Counter,
118252723Sdim                                         const UniqueVector<BasicBlock *>&Preds,
119252723Sdim                                         const UniqueVector<BasicBlock*>&Succs);
120221337Sdim
121221337Sdim    // Add the function to write out all our counters to the global destructor
122221337Sdim    // list.
123252723Sdim    Function *insertCounterWriteout(ArrayRef<std::pair<GlobalVariable*,
124252723Sdim                                                       MDNode*> >);
125252723Sdim    Function *insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> >);
126245431Sdim    void insertIndirectCounterIncrement();
127221337Sdim
128245431Sdim    std::string mangleName(DICompileUnit CU, const char *NewStem);
129223017Sdim
130252723Sdim    GCOVOptions Options;
131221337Sdim
132252723Sdim    // Reversed, NUL-terminated copy of Options.Version.
133252723Sdim    char ReversedVersion[5];
134252723Sdim
135221337Sdim    Module *M;
136221337Sdim    LLVMContext *Ctx;
137221337Sdim  };
138221337Sdim}
139221337Sdim
140221337Sdimchar GCOVProfiler::ID = 0;
141221337SdimINITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling",
142221337Sdim                "Insert instrumentation for GCOV profiling", false, false)
143221337Sdim
144252723SdimModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) {
145252723Sdim  return new GCOVProfiler(Options);
146221337Sdim}
147221337Sdim
148252723Sdimstatic std::string getFunctionName(DISubprogram SP) {
149252723Sdim  if (!SP.getLinkageName().empty())
150252723Sdim    return SP.getLinkageName();
151252723Sdim  return SP.getName();
152252723Sdim}
153252723Sdim
154221337Sdimnamespace {
155221337Sdim  class GCOVRecord {
156221337Sdim   protected:
157263509Sdim    static const char *const LinesTag;
158263509Sdim    static const char *const FunctionTag;
159263509Sdim    static const char *const BlockTag;
160263509Sdim    static const char *const EdgeTag;
161221337Sdim
162221337Sdim    GCOVRecord() {}
163221337Sdim
164221337Sdim    void writeBytes(const char *Bytes, int Size) {
165221337Sdim      os->write(Bytes, Size);
166221337Sdim    }
167221337Sdim
168221337Sdim    void write(uint32_t i) {
169221337Sdim      writeBytes(reinterpret_cast<char*>(&i), 4);
170221337Sdim    }
171221337Sdim
172221337Sdim    // Returns the length measured in 4-byte blocks that will be used to
173221337Sdim    // represent this string in a GCOV file
174263509Sdim    static unsigned lengthOfGCOVString(StringRef s) {
175221337Sdim      // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs
176221337Sdim      // padding out to the next 4-byte word. The length is measured in 4-byte
177221337Sdim      // words including padding, not bytes of actual string.
178223017Sdim      return (s.size() / 4) + 1;
179221337Sdim    }
180221337Sdim
181221337Sdim    void writeGCOVString(StringRef s) {
182221337Sdim      uint32_t Len = lengthOfGCOVString(s);
183221337Sdim      write(Len);
184221337Sdim      writeBytes(s.data(), s.size());
185221337Sdim
186221337Sdim      // Write 1 to 4 bytes of NUL padding.
187221337Sdim      assert((unsigned)(4 - (s.size() % 4)) > 0);
188221337Sdim      assert((unsigned)(4 - (s.size() % 4)) <= 4);
189221337Sdim      writeBytes("\0\0\0\0", 4 - (s.size() % 4));
190221337Sdim    }
191221337Sdim
192221337Sdim    raw_ostream *os;
193221337Sdim  };
194263509Sdim  const char *const GCOVRecord::LinesTag = "\0\0\x45\x01";
195263509Sdim  const char *const GCOVRecord::FunctionTag = "\0\0\0\1";
196263509Sdim  const char *const GCOVRecord::BlockTag = "\0\0\x41\x01";
197263509Sdim  const char *const GCOVRecord::EdgeTag = "\0\0\x43\x01";
198221337Sdim
199221337Sdim  class GCOVFunction;
200221337Sdim  class GCOVBlock;
201221337Sdim
202221337Sdim  // Constructed only by requesting it from a GCOVBlock, this object stores a
203221337Sdim  // list of line numbers and a single filename, representing lines that belong
204221337Sdim  // to the block.
205221337Sdim  class GCOVLines : public GCOVRecord {
206221337Sdim   public:
207221337Sdim    void addLine(uint32_t Line) {
208221337Sdim      Lines.push_back(Line);
209221337Sdim    }
210221337Sdim
211263509Sdim    uint32_t length() const {
212235633Sdim      // Here 2 = 1 for string length + 1 for '0' id#.
213221337Sdim      return lengthOfGCOVString(Filename) + 2 + Lines.size();
214221337Sdim    }
215221337Sdim
216226890Sdim    void writeOut() {
217226890Sdim      write(0);
218226890Sdim      writeGCOVString(Filename);
219226890Sdim      for (int i = 0, e = Lines.size(); i != e; ++i)
220226890Sdim        write(Lines[i]);
221226890Sdim    }
222221337Sdim
223226890Sdim    GCOVLines(StringRef F, raw_ostream *os)
224226890Sdim      : Filename(F) {
225221337Sdim      this->os = os;
226221337Sdim    }
227221337Sdim
228226890Sdim   private:
229226890Sdim    StringRef Filename;
230221337Sdim    SmallVector<uint32_t, 32> Lines;
231221337Sdim  };
232221337Sdim
233263509Sdim
234263509Sdim  // Sorting function for deterministic behaviour in GCOVBlock::writeOut.
235263509Sdim  struct StringKeySort {
236263509Sdim    bool operator()(StringMapEntry<GCOVLines *> *LHS,
237263509Sdim                    StringMapEntry<GCOVLines *> *RHS) const {
238263509Sdim      return LHS->getKey() < RHS->getKey();
239263509Sdim    }
240263509Sdim  };
241263509Sdim
242221337Sdim  // Represent a basic block in GCOV. Each block has a unique number in the
243221337Sdim  // function, number of lines belonging to each block, and a set of edges to
244221337Sdim  // other blocks.
245221337Sdim  class GCOVBlock : public GCOVRecord {
246221337Sdim   public:
247226890Sdim    GCOVLines &getFile(StringRef Filename) {
248221337Sdim      GCOVLines *&Lines = LinesByFile[Filename];
249221337Sdim      if (!Lines) {
250221337Sdim        Lines = new GCOVLines(Filename, os);
251221337Sdim      }
252221337Sdim      return *Lines;
253221337Sdim    }
254221337Sdim
255221337Sdim    void addEdge(GCOVBlock &Successor) {
256221337Sdim      OutEdges.push_back(&Successor);
257221337Sdim    }
258221337Sdim
259221337Sdim    void writeOut() {
260221337Sdim      uint32_t Len = 3;
261263509Sdim      SmallVector<StringMapEntry<GCOVLines *> *, 32> SortedLinesByFile;
262221337Sdim      for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(),
263221337Sdim               E = LinesByFile.end(); I != E; ++I) {
264221337Sdim        Len += I->second->length();
265263509Sdim        SortedLinesByFile.push_back(&*I);
266221337Sdim      }
267221337Sdim
268221337Sdim      writeBytes(LinesTag, 4);
269221337Sdim      write(Len);
270221337Sdim      write(Number);
271263509Sdim
272263509Sdim      StringKeySort Sorter;
273263509Sdim      std::sort(SortedLinesByFile.begin(), SortedLinesByFile.end(), Sorter);
274263509Sdim      for (SmallVectorImpl<StringMapEntry<GCOVLines *> *>::iterator
275263509Sdim               I = SortedLinesByFile.begin(), E = SortedLinesByFile.end();
276263509Sdim           I != E; ++I)
277263509Sdim        (*I)->getValue()->writeOut();
278221337Sdim      write(0);
279221337Sdim      write(0);
280221337Sdim    }
281221337Sdim
282221337Sdim    ~GCOVBlock() {
283221337Sdim      DeleteContainerSeconds(LinesByFile);
284221337Sdim    }
285221337Sdim
286221337Sdim   private:
287221337Sdim    friend class GCOVFunction;
288221337Sdim
289221337Sdim    GCOVBlock(uint32_t Number, raw_ostream *os)
290221337Sdim        : Number(Number) {
291221337Sdim      this->os = os;
292221337Sdim    }
293221337Sdim
294221337Sdim    uint32_t Number;
295221337Sdim    StringMap<GCOVLines *> LinesByFile;
296221337Sdim    SmallVector<GCOVBlock *, 4> OutEdges;
297221337Sdim  };
298221337Sdim
299221337Sdim  // A function has a unique identifier, a checksum (we leave as zero) and a
300221337Sdim  // set of blocks and a map of edges between blocks. This is the only GCOV
301221337Sdim  // object users can construct, the blocks and lines will be rooted here.
302221337Sdim  class GCOVFunction : public GCOVRecord {
303221337Sdim   public:
304252723Sdim    GCOVFunction(DISubprogram SP, raw_ostream *os, uint32_t Ident,
305252723Sdim                 bool UseCfgChecksum) {
306221337Sdim      this->os = os;
307221337Sdim
308221337Sdim      Function *F = SP.getFunction();
309235633Sdim      DEBUG(dbgs() << "Function: " << F->getName() << "\n");
310221337Sdim      uint32_t i = 0;
311221337Sdim      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
312221337Sdim        Blocks[BB] = new GCOVBlock(i++, os);
313221337Sdim      }
314221337Sdim      ReturnBlock = new GCOVBlock(i++, os);
315221337Sdim
316221337Sdim      writeBytes(FunctionTag, 4);
317252723Sdim      uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) +
318221337Sdim          1 + lengthOfGCOVString(SP.getFilename()) + 1;
319252723Sdim      if (UseCfgChecksum)
320235633Sdim        ++BlockLen;
321221337Sdim      write(BlockLen);
322221337Sdim      write(Ident);
323235633Sdim      write(0);  // lineno checksum
324252723Sdim      if (UseCfgChecksum)
325235633Sdim        write(0);  // cfg checksum
326252723Sdim      writeGCOVString(getFunctionName(SP));
327221337Sdim      writeGCOVString(SP.getFilename());
328221337Sdim      write(SP.getLineNumber());
329221337Sdim    }
330221337Sdim
331221337Sdim    ~GCOVFunction() {
332221337Sdim      DeleteContainerSeconds(Blocks);
333221337Sdim      delete ReturnBlock;
334221337Sdim    }
335221337Sdim
336221337Sdim    GCOVBlock &getBlock(BasicBlock *BB) {
337221337Sdim      return *Blocks[BB];
338221337Sdim    }
339221337Sdim
340221337Sdim    GCOVBlock &getReturnBlock() {
341221337Sdim      return *ReturnBlock;
342221337Sdim    }
343221337Sdim
344221337Sdim    void writeOut() {
345221337Sdim      // Emit count of blocks.
346221337Sdim      writeBytes(BlockTag, 4);
347221337Sdim      write(Blocks.size() + 1);
348221337Sdim      for (int i = 0, e = Blocks.size() + 1; i != e; ++i) {
349221337Sdim        write(0);  // No flags on our blocks.
350221337Sdim      }
351235633Sdim      DEBUG(dbgs() << Blocks.size() << " blocks.\n");
352221337Sdim
353221337Sdim      // Emit edges between blocks.
354263509Sdim      if (Blocks.empty()) return;
355263509Sdim      Function *F = Blocks.begin()->first->getParent();
356263509Sdim      for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
357263509Sdim        GCOVBlock &Block = *Blocks[I];
358221337Sdim        if (Block.OutEdges.empty()) continue;
359221337Sdim
360221337Sdim        writeBytes(EdgeTag, 4);
361221337Sdim        write(Block.OutEdges.size() * 2 + 1);
362221337Sdim        write(Block.Number);
363221337Sdim        for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) {
364235633Sdim          DEBUG(dbgs() << Block.Number << " -> " << Block.OutEdges[i]->Number
365235633Sdim                       << "\n");
366221337Sdim          write(Block.OutEdges[i]->Number);
367221337Sdim          write(0);  // no flags
368221337Sdim        }
369221337Sdim      }
370221337Sdim
371221337Sdim      // Emit lines for each block.
372263509Sdim      for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
373263509Sdim        Blocks[I]->writeOut();
374221337Sdim      }
375221337Sdim    }
376221337Sdim
377221337Sdim   private:
378221337Sdim    DenseMap<BasicBlock *, GCOVBlock *> Blocks;
379221337Sdim    GCOVBlock *ReturnBlock;
380221337Sdim  };
381221337Sdim}
382221337Sdim
383245431Sdimstd::string GCOVProfiler::mangleName(DICompileUnit CU, const char *NewStem) {
384223017Sdim  if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) {
385223017Sdim    for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) {
386223017Sdim      MDNode *N = GCov->getOperand(i);
387223017Sdim      if (N->getNumOperands() != 2) continue;
388223017Sdim      MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0));
389223017Sdim      MDNode *CompileUnit = dyn_cast<MDNode>(N->getOperand(1));
390223017Sdim      if (!GCovFile || !CompileUnit) continue;
391223017Sdim      if (CompileUnit == CU) {
392223017Sdim        SmallString<128> Filename = GCovFile->getString();
393223017Sdim        sys::path::replace_extension(Filename, NewStem);
394223017Sdim        return Filename.str();
395223017Sdim      }
396223017Sdim    }
397223017Sdim  }
398223017Sdim
399223017Sdim  SmallString<128> Filename = CU.getFilename();
400223017Sdim  sys::path::replace_extension(Filename, NewStem);
401252723Sdim  StringRef FName = sys::path::filename(Filename);
402252723Sdim  SmallString<128> CurPath;
403252723Sdim  if (sys::fs::current_path(CurPath)) return FName;
404252723Sdim  sys::path::append(CurPath, FName.str());
405252723Sdim  return CurPath.str();
406221337Sdim}
407221337Sdim
408221337Sdimbool GCOVProfiler::runOnModule(Module &M) {
409221337Sdim  this->M = &M;
410221337Sdim  Ctx = &M.getContext();
411221337Sdim
412252723Sdim  if (Options.EmitNotes) emitProfileNotes();
413252723Sdim  if (Options.EmitData) return emitProfileArcs();
414221337Sdim  return false;
415221337Sdim}
416221337Sdim
417252723Sdimvoid GCOVProfiler::emitProfileNotes() {
418226890Sdim  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
419235633Sdim  if (!CU_Nodes) return;
420235633Sdim
421235633Sdim  for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
422235633Sdim    // Each compile unit gets its own .gcno file. This means that whether we run
423235633Sdim    // this pass over the original .o's as they're produced, or run it after
424235633Sdim    // LTO, we'll generate the same .gcno files.
425235633Sdim
426235633Sdim    DICompileUnit CU(CU_Nodes->getOperand(i));
427235633Sdim    std::string ErrorInfo;
428235633Sdim    raw_fd_ostream out(mangleName(CU, "gcno").c_str(), ErrorInfo,
429263509Sdim                       sys::fs::F_Binary);
430252723Sdim    out.write("oncg", 4);
431252723Sdim    out.write(ReversedVersion, 4);
432252723Sdim    out.write("MVLL", 4);
433235633Sdim
434235633Sdim    DIArray SPs = CU.getSubprograms();
435235633Sdim    for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
436235633Sdim      DISubprogram SP(SPs.getElement(i));
437263509Sdim      assert((!SP || SP.isSubprogram()) &&
438263509Sdim        "A MDNode in subprograms of a CU should be null or a DISubprogram.");
439263509Sdim      if (!SP)
440263509Sdim        continue;
441235633Sdim
442235633Sdim      Function *F = SP.getFunction();
443235633Sdim      if (!F) continue;
444252723Sdim      GCOVFunction Func(SP, &out, i, Options.UseCfgChecksum);
445235633Sdim
446235633Sdim      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
447235633Sdim        GCOVBlock &Block = Func.getBlock(BB);
448235633Sdim        TerminatorInst *TI = BB->getTerminator();
449235633Sdim        if (int successors = TI->getNumSuccessors()) {
450235633Sdim          for (int i = 0; i != successors; ++i) {
451235633Sdim            Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
452226890Sdim          }
453235633Sdim        } else if (isa<ReturnInst>(TI)) {
454235633Sdim          Block.addEdge(Func.getReturnBlock());
455221337Sdim        }
456235633Sdim
457235633Sdim        uint32_t Line = 0;
458235633Sdim        for (BasicBlock::iterator I = BB->begin(), IE = BB->end();
459235633Sdim             I != IE; ++I) {
460235633Sdim          const DebugLoc &Loc = I->getDebugLoc();
461235633Sdim          if (Loc.isUnknown()) continue;
462235633Sdim          if (Line == Loc.getLine()) continue;
463235633Sdim          Line = Loc.getLine();
464235633Sdim          if (SP != getDISubprogram(Loc.getScope(*Ctx))) continue;
465235633Sdim
466235633Sdim          GCOVLines &Lines = Block.getFile(SP.getFilename());
467235633Sdim          Lines.addLine(Loc.getLine());
468235633Sdim        }
469221337Sdim      }
470235633Sdim      Func.writeOut();
471221337Sdim    }
472235633Sdim    out.write("\0\0\0\0\0\0\0\0", 8);  // EOF
473235633Sdim    out.close();
474221337Sdim  }
475221337Sdim}
476221337Sdim
477226890Sdimbool GCOVProfiler::emitProfileArcs() {
478226890Sdim  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
479226890Sdim  if (!CU_Nodes) return false;
480221337Sdim
481226890Sdim  bool Result = false;
482245431Sdim  bool InsertIndCounterIncrCode = false;
483226890Sdim  for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
484226890Sdim    DICompileUnit CU(CU_Nodes->getOperand(i));
485226890Sdim    DIArray SPs = CU.getSubprograms();
486226890Sdim    SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP;
487226890Sdim    for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
488226890Sdim      DISubprogram SP(SPs.getElement(i));
489263509Sdim      assert((!SP || SP.isSubprogram()) &&
490263509Sdim        "A MDNode in subprograms of a CU should be null or a DISubprogram.");
491263509Sdim      if (!SP)
492263509Sdim        continue;
493226890Sdim      Function *F = SP.getFunction();
494226890Sdim      if (!F) continue;
495226890Sdim      if (!Result) Result = true;
496226890Sdim      unsigned Edges = 0;
497226890Sdim      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
498226890Sdim        TerminatorInst *TI = BB->getTerminator();
499226890Sdim        if (isa<ReturnInst>(TI))
500226890Sdim          ++Edges;
501226890Sdim        else
502226890Sdim          Edges += TI->getNumSuccessors();
503226890Sdim      }
504226890Sdim
505226890Sdim      ArrayType *CounterTy =
506221337Sdim        ArrayType::get(Type::getInt64Ty(*Ctx), Edges);
507226890Sdim      GlobalVariable *Counters =
508221337Sdim        new GlobalVariable(*M, CounterTy, false,
509221337Sdim                           GlobalValue::InternalLinkage,
510221337Sdim                           Constant::getNullValue(CounterTy),
511245431Sdim                           "__llvm_gcov_ctr");
512226890Sdim      CountersBySP.push_back(std::make_pair(Counters, (MDNode*)SP));
513226890Sdim
514226890Sdim      UniqueVector<BasicBlock *> ComplexEdgePreds;
515226890Sdim      UniqueVector<BasicBlock *> ComplexEdgeSuccs;
516226890Sdim
517226890Sdim      unsigned Edge = 0;
518226890Sdim      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
519226890Sdim        TerminatorInst *TI = BB->getTerminator();
520226890Sdim        int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
521226890Sdim        if (Successors) {
522226890Sdim          if (Successors == 1) {
523263509Sdim            IRBuilder<> Builder(BB->getFirstInsertionPt());
524226890Sdim            Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
525226890Sdim                                                                Edge);
526226890Sdim            Value *Count = Builder.CreateLoad(Counter);
527252723Sdim            Count = Builder.CreateAdd(Count, Builder.getInt64(1));
528226890Sdim            Builder.CreateStore(Count, Counter);
529226890Sdim          } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
530263509Sdim            IRBuilder<> Builder(BI);
531252723Sdim            Value *Sel = Builder.CreateSelect(BI->getCondition(),
532252723Sdim                                              Builder.getInt64(Edge),
533252723Sdim                                              Builder.getInt64(Edge + 1));
534226890Sdim            SmallVector<Value *, 2> Idx;
535252723Sdim            Idx.push_back(Builder.getInt64(0));
536226890Sdim            Idx.push_back(Sel);
537226890Sdim            Value *Counter = Builder.CreateInBoundsGEP(Counters, Idx);
538226890Sdim            Value *Count = Builder.CreateLoad(Counter);
539252723Sdim            Count = Builder.CreateAdd(Count, Builder.getInt64(1));
540226890Sdim            Builder.CreateStore(Count, Counter);
541226890Sdim          } else {
542226890Sdim            ComplexEdgePreds.insert(BB);
543226890Sdim            for (int i = 0; i != Successors; ++i)
544226890Sdim              ComplexEdgeSuccs.insert(TI->getSuccessor(i));
545226890Sdim          }
546263509Sdim
547226890Sdim          Edge += Successors;
548221337Sdim        }
549221337Sdim      }
550226890Sdim
551226890Sdim      if (!ComplexEdgePreds.empty()) {
552226890Sdim        GlobalVariable *EdgeTable =
553221337Sdim          buildEdgeLookupTable(F, Counters,
554221337Sdim                               ComplexEdgePreds, ComplexEdgeSuccs);
555226890Sdim        GlobalVariable *EdgeState = getEdgeStateValue();
556226890Sdim
557226890Sdim        for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) {
558263509Sdim          IRBuilder<> Builder(ComplexEdgePreds[i + 1]->getFirstInsertionPt());
559252723Sdim          Builder.CreateStore(Builder.getInt32(i), EdgeState);
560226890Sdim        }
561263509Sdim
562226890Sdim        for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
563263509Sdim          // Call runtime to perform increment.
564263509Sdim          IRBuilder<> Builder(ComplexEdgeSuccs[i+1]->getFirstInsertionPt());
565226890Sdim          Value *CounterPtrArray =
566221337Sdim            Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
567221337Sdim                                               i * ComplexEdgePreds.size());
568245431Sdim
569245431Sdim          // Build code to increment the counter.
570245431Sdim          InsertIndCounterIncrCode = true;
571226890Sdim          Builder.CreateCall2(getIncrementIndirectCounterFunc(),
572226890Sdim                              EdgeState, CounterPtrArray);
573226890Sdim        }
574221337Sdim      }
575221337Sdim    }
576245431Sdim
577252723Sdim    Function *WriteoutF = insertCounterWriteout(CountersBySP);
578252723Sdim    Function *FlushF = insertFlush(CountersBySP);
579252723Sdim
580252723Sdim    // Create a small bit of code that registers the "__llvm_gcov_writeout" to
581252723Sdim    // be executed at exit and the "__llvm_gcov_flush" function to be executed
582252723Sdim    // when "__gcov_flush" is called.
583252723Sdim    FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
584252723Sdim    Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
585252723Sdim                                   "__llvm_gcov_init", M);
586252723Sdim    F->setUnnamedAddr(true);
587252723Sdim    F->setLinkage(GlobalValue::InternalLinkage);
588252723Sdim    F->addFnAttr(Attribute::NoInline);
589252723Sdim    if (Options.NoRedZone)
590252723Sdim      F->addFnAttr(Attribute::NoRedZone);
591252723Sdim
592252723Sdim    BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
593252723Sdim    IRBuilder<> Builder(BB);
594252723Sdim
595252723Sdim    FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
596252723Sdim    Type *Params[] = {
597252723Sdim      PointerType::get(FTy, 0),
598252723Sdim      PointerType::get(FTy, 0)
599252723Sdim    };
600252723Sdim    FTy = FunctionType::get(Builder.getVoidTy(), Params, false);
601252723Sdim
602263509Sdim    // Initialize the environment and register the local writeout and flush
603252723Sdim    // functions.
604252723Sdim    Constant *GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy);
605252723Sdim    Builder.CreateCall2(GCOVInit, WriteoutF, FlushF);
606252723Sdim    Builder.CreateRetVoid();
607252723Sdim
608252723Sdim    appendToGlobalCtors(*M, F, 0);
609221337Sdim  }
610245431Sdim
611245431Sdim  if (InsertIndCounterIncrCode)
612245431Sdim    insertIndirectCounterIncrement();
613245431Sdim
614226890Sdim  return Result;
615221337Sdim}
616221337Sdim
617221337Sdim// All edges with successors that aren't branches are "complex", because it
618221337Sdim// requires complex logic to pick which counter to update.
619221337SdimGlobalVariable *GCOVProfiler::buildEdgeLookupTable(
620221337Sdim    Function *F,
621221337Sdim    GlobalVariable *Counters,
622221337Sdim    const UniqueVector<BasicBlock *> &Preds,
623221337Sdim    const UniqueVector<BasicBlock *> &Succs) {
624221337Sdim  // TODO: support invoke, threads. We rely on the fact that nothing can modify
625221337Sdim  // the whole-Module pred edge# between the time we set it and the time we next
626221337Sdim  // read it. Threads and invoke make this untrue.
627221337Sdim
628221337Sdim  // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]].
629252723Sdim  size_t TableSize = Succs.size() * Preds.size();
630226890Sdim  Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
631252723Sdim  ArrayType *EdgeTableTy = ArrayType::get(Int64PtrTy, TableSize);
632221337Sdim
633252723Sdim  OwningArrayPtr<Constant *> EdgeTable(new Constant*[TableSize]);
634221337Sdim  Constant *NullValue = Constant::getNullValue(Int64PtrTy);
635252723Sdim  for (size_t i = 0; i != TableSize; ++i)
636221337Sdim    EdgeTable[i] = NullValue;
637221337Sdim
638221337Sdim  unsigned Edge = 0;
639221337Sdim  for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
640221337Sdim    TerminatorInst *TI = BB->getTerminator();
641221337Sdim    int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
642221337Sdim    if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) {
643221337Sdim      for (int i = 0; i != Successors; ++i) {
644221337Sdim        BasicBlock *Succ = TI->getSuccessor(i);
645252723Sdim        IRBuilder<> Builder(Succ);
646252723Sdim        Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
647221337Sdim                                                            Edge + i);
648221337Sdim        EdgeTable[((Succs.idFor(Succ)-1) * Preds.size()) +
649221337Sdim                  (Preds.idFor(BB)-1)] = cast<Constant>(Counter);
650221337Sdim      }
651221337Sdim    }
652221337Sdim    Edge += Successors;
653221337Sdim  }
654221337Sdim
655252723Sdim  ArrayRef<Constant*> V(&EdgeTable[0], TableSize);
656221337Sdim  GlobalVariable *EdgeTableGV =
657221337Sdim      new GlobalVariable(
658221337Sdim          *M, EdgeTableTy, true, GlobalValue::InternalLinkage,
659224145Sdim          ConstantArray::get(EdgeTableTy, V),
660221337Sdim          "__llvm_gcda_edge_table");
661221337Sdim  EdgeTableGV->setUnnamedAddr(true);
662221337Sdim  return EdgeTableGV;
663221337Sdim}
664221337Sdim
665221337SdimConstant *GCOVProfiler::getStartFileFunc() {
666252723Sdim  Type *Args[] = {
667252723Sdim    Type::getInt8PtrTy(*Ctx),  // const char *orig_filename
668252723Sdim    Type::getInt8PtrTy(*Ctx),  // const char version[4]
669252723Sdim  };
670252723Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
671221337Sdim  return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
672221337Sdim}
673221337Sdim
674221337SdimConstant *GCOVProfiler::getIncrementIndirectCounterFunc() {
675245431Sdim  Type *Int32Ty = Type::getInt32Ty(*Ctx);
676245431Sdim  Type *Int64Ty = Type::getInt64Ty(*Ctx);
677224145Sdim  Type *Args[] = {
678245431Sdim    Int32Ty->getPointerTo(),                // uint32_t *predecessor
679245431Sdim    Int64Ty->getPointerTo()->getPointerTo() // uint64_t **counters
680221337Sdim  };
681245431Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
682245431Sdim  return M->getOrInsertFunction("__llvm_gcov_indirect_counter_increment", FTy);
683221337Sdim}
684221337Sdim
685221337SdimConstant *GCOVProfiler::getEmitFunctionFunc() {
686252723Sdim  Type *Args[3] = {
687223017Sdim    Type::getInt32Ty(*Ctx),    // uint32_t ident
688223017Sdim    Type::getInt8PtrTy(*Ctx),  // const char *function_name
689252723Sdim    Type::getInt8Ty(*Ctx),     // uint8_t use_extra_checksum
690223017Sdim  };
691245431Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
692221337Sdim  return M->getOrInsertFunction("llvm_gcda_emit_function", FTy);
693221337Sdim}
694221337Sdim
695221337SdimConstant *GCOVProfiler::getEmitArcsFunc() {
696224145Sdim  Type *Args[] = {
697221337Sdim    Type::getInt32Ty(*Ctx),     // uint32_t num_counters
698221337Sdim    Type::getInt64PtrTy(*Ctx),  // uint64_t *counters
699221337Sdim  };
700252723Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
701221337Sdim  return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
702221337Sdim}
703221337Sdim
704263509SdimConstant *GCOVProfiler::getSummaryInfoFunc() {
705263509Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
706263509Sdim  return M->getOrInsertFunction("llvm_gcda_summary_info", FTy);
707263509Sdim}
708263509Sdim
709252723SdimConstant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() {
710252723Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
711252723Sdim  return M->getOrInsertFunction("llvm_delete_writeout_function_list", FTy);
712252723Sdim}
713252723Sdim
714252723SdimConstant *GCOVProfiler::getDeleteFlushFunctionListFunc() {
715252723Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
716252723Sdim  return M->getOrInsertFunction("llvm_delete_flush_function_list", FTy);
717252723Sdim}
718252723Sdim
719221337SdimConstant *GCOVProfiler::getEndFileFunc() {
720226890Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
721221337Sdim  return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
722221337Sdim}
723221337Sdim
724221337SdimGlobalVariable *GCOVProfiler::getEdgeStateValue() {
725221337Sdim  GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred");
726221337Sdim  if (!GV) {
727221337Sdim    GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false,
728221337Sdim                            GlobalValue::InternalLinkage,
729221337Sdim                            ConstantInt::get(Type::getInt32Ty(*Ctx),
730221337Sdim                                             0xffffffff),
731221337Sdim                            "__llvm_gcov_global_state_pred");
732221337Sdim    GV->setUnnamedAddr(true);
733221337Sdim  }
734221337Sdim  return GV;
735221337Sdim}
736221337Sdim
737252723SdimFunction *GCOVProfiler::insertCounterWriteout(
738245431Sdim    ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
739245431Sdim  FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
740245431Sdim  Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
741245431Sdim  if (!WriteoutF)
742245431Sdim    WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage,
743245431Sdim                                 "__llvm_gcov_writeout", M);
744221337Sdim  WriteoutF->setUnnamedAddr(true);
745252723Sdim  WriteoutF->addFnAttr(Attribute::NoInline);
746252723Sdim  if (Options.NoRedZone)
747252723Sdim    WriteoutF->addFnAttr(Attribute::NoRedZone);
748245431Sdim
749245431Sdim  BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF);
750221337Sdim  IRBuilder<> Builder(BB);
751221337Sdim
752221337Sdim  Constant *StartFile = getStartFileFunc();
753221337Sdim  Constant *EmitFunction = getEmitFunctionFunc();
754221337Sdim  Constant *EmitArcs = getEmitArcsFunc();
755263509Sdim  Constant *SummaryInfo = getSummaryInfoFunc();
756221337Sdim  Constant *EndFile = getEndFileFunc();
757221337Sdim
758226890Sdim  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
759226890Sdim  if (CU_Nodes) {
760226890Sdim    for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
761245431Sdim      DICompileUnit CU(CU_Nodes->getOperand(i));
762245431Sdim      std::string FilenameGcda = mangleName(CU, "gcda");
763252723Sdim      Builder.CreateCall2(StartFile,
764252723Sdim                          Builder.CreateGlobalStringPtr(FilenameGcda),
765252723Sdim                          Builder.CreateGlobalStringPtr(ReversedVersion));
766252723Sdim      for (unsigned j = 0, e = CountersBySP.size(); j != e; ++j) {
767252723Sdim        DISubprogram SP(CountersBySP[j].second);
768252723Sdim        Builder.CreateCall3(
769252723Sdim            EmitFunction, Builder.getInt32(j),
770252723Sdim            Options.FunctionNamesInData ?
771252723Sdim              Builder.CreateGlobalStringPtr(getFunctionName(SP)) :
772252723Sdim              Constant::getNullValue(Builder.getInt8PtrTy()),
773252723Sdim            Builder.getInt8(Options.UseCfgChecksum));
774252723Sdim
775252723Sdim        GlobalVariable *GV = CountersBySP[j].first;
776226890Sdim        unsigned Arcs =
777221337Sdim          cast<ArrayType>(GV->getType()->getElementType())->getNumElements();
778226890Sdim        Builder.CreateCall2(EmitArcs,
779252723Sdim                            Builder.getInt32(Arcs),
780226890Sdim                            Builder.CreateConstGEP2_64(GV, 0, 0));
781226890Sdim      }
782263509Sdim      Builder.CreateCall(SummaryInfo);
783226890Sdim      Builder.CreateCall(EndFile);
784221337Sdim    }
785221337Sdim  }
786221337Sdim
787245431Sdim  Builder.CreateRetVoid();
788252723Sdim  return WriteoutF;
789221337Sdim}
790245431Sdim
791245431Sdimvoid GCOVProfiler::insertIndirectCounterIncrement() {
792245431Sdim  Function *Fn =
793245431Sdim    cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
794245431Sdim  Fn->setUnnamedAddr(true);
795245431Sdim  Fn->setLinkage(GlobalValue::InternalLinkage);
796252723Sdim  Fn->addFnAttr(Attribute::NoInline);
797252723Sdim  if (Options.NoRedZone)
798252723Sdim    Fn->addFnAttr(Attribute::NoRedZone);
799245431Sdim
800245431Sdim  // Create basic blocks for function.
801245431Sdim  BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", Fn);
802245431Sdim  IRBuilder<> Builder(BB);
803245431Sdim
804245431Sdim  BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn);
805245431Sdim  BasicBlock *CounterEnd = BasicBlock::Create(*Ctx, "", Fn);
806245431Sdim  BasicBlock *Exit = BasicBlock::Create(*Ctx, "exit", Fn);
807245431Sdim
808245431Sdim  // uint32_t pred = *predecessor;
809245431Sdim  // if (pred == 0xffffffff) return;
810245431Sdim  Argument *Arg = Fn->arg_begin();
811245431Sdim  Arg->setName("predecessor");
812245431Sdim  Value *Pred = Builder.CreateLoad(Arg, "pred");
813252723Sdim  Value *Cond = Builder.CreateICmpEQ(Pred, Builder.getInt32(0xffffffff));
814245431Sdim  BranchInst::Create(Exit, PredNotNegOne, Cond, BB);
815245431Sdim
816245431Sdim  Builder.SetInsertPoint(PredNotNegOne);
817245431Sdim
818245431Sdim  // uint64_t *counter = counters[pred];
819245431Sdim  // if (!counter) return;
820252723Sdim  Value *ZExtPred = Builder.CreateZExt(Pred, Builder.getInt64Ty());
821245431Sdim  Arg = llvm::next(Fn->arg_begin());
822245431Sdim  Arg->setName("counters");
823245431Sdim  Value *GEP = Builder.CreateGEP(Arg, ZExtPred);
824245431Sdim  Value *Counter = Builder.CreateLoad(GEP, "counter");
825245431Sdim  Cond = Builder.CreateICmpEQ(Counter,
826252723Sdim                              Constant::getNullValue(
827252723Sdim                                  Builder.getInt64Ty()->getPointerTo()));
828245431Sdim  Builder.CreateCondBr(Cond, Exit, CounterEnd);
829245431Sdim
830245431Sdim  // ++*counter;
831245431Sdim  Builder.SetInsertPoint(CounterEnd);
832245431Sdim  Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter),
833252723Sdim                                 Builder.getInt64(1));
834245431Sdim  Builder.CreateStore(Add, Counter);
835245431Sdim  Builder.CreateBr(Exit);
836245431Sdim
837245431Sdim  // Fill in the exit block.
838245431Sdim  Builder.SetInsertPoint(Exit);
839245431Sdim  Builder.CreateRetVoid();
840245431Sdim}
841245431Sdim
842252723SdimFunction *GCOVProfiler::
843245431SdiminsertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
844245431Sdim  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
845252723Sdim  Function *FlushF = M->getFunction("__llvm_gcov_flush");
846245431Sdim  if (!FlushF)
847245431Sdim    FlushF = Function::Create(FTy, GlobalValue::InternalLinkage,
848252723Sdim                              "__llvm_gcov_flush", M);
849245431Sdim  else
850245431Sdim    FlushF->setLinkage(GlobalValue::InternalLinkage);
851245431Sdim  FlushF->setUnnamedAddr(true);
852252723Sdim  FlushF->addFnAttr(Attribute::NoInline);
853252723Sdim  if (Options.NoRedZone)
854252723Sdim    FlushF->addFnAttr(Attribute::NoRedZone);
855245431Sdim
856245431Sdim  BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF);
857245431Sdim
858245431Sdim  // Write out the current counters.
859245431Sdim  Constant *WriteoutF = M->getFunction("__llvm_gcov_writeout");
860245431Sdim  assert(WriteoutF && "Need to create the writeout function first!");
861245431Sdim
862245431Sdim  IRBuilder<> Builder(Entry);
863245431Sdim  Builder.CreateCall(WriteoutF);
864245431Sdim
865245431Sdim  // Zero out the counters.
866245431Sdim  for (ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator
867245431Sdim         I = CountersBySP.begin(), E = CountersBySP.end();
868245431Sdim       I != E; ++I) {
869245431Sdim    GlobalVariable *GV = I->first;
870245431Sdim    Constant *Null = Constant::getNullValue(GV->getType()->getElementType());
871245431Sdim    Builder.CreateStore(Null, GV);
872245431Sdim  }
873245431Sdim
874245431Sdim  Type *RetTy = FlushF->getReturnType();
875245431Sdim  if (RetTy == Type::getVoidTy(*Ctx))
876245431Sdim    Builder.CreateRetVoid();
877245431Sdim  else if (RetTy->isIntegerTy())
878252723Sdim    // Used if __llvm_gcov_flush was implicitly declared.
879245431Sdim    Builder.CreateRet(ConstantInt::get(RetTy, 0));
880245431Sdim  else
881252723Sdim    report_fatal_error("invalid return type for __llvm_gcov_flush");
882252723Sdim
883252723Sdim  return FlushF;
884245431Sdim}
885