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#include "llvm/ADT/DenseMap.h"
1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ADT/Hashing.h"
19b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/STLExtras.h"
2006cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/ADT/Statistic.h"
21b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringExtras.h"
22b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringMap.h"
23b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/UniqueVector.h"
2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DebugInfo.h"
2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DebugLoc.h"
260b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IRBuilder.h"
2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/InstIterator.h"
280b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Instructions.h"
2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/IntrinsicInst.h"
300b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h"
31d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Pass.h"
32a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "llvm/Support/CommandLine.h"
3306cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Support/Debug.h"
3439c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling#include "llvm/Support/FileSystem.h"
35a11c3e25015a62c817e60ec4f955a7f3f3bb6c67Rafael Espindola#include "llvm/Support/Path.h"
3606cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Support/raw_ostream.h"
37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Transforms/GCOVProfiler.h"
38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Transforms/Instrumentation.h"
3906cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Transforms/Utils/ModuleUtils.h"
40c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky#include <algorithm>
41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include <memory>
42b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <string>
43b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <utility>
44b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyusing namespace llvm;
45b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "insert-gcov-profiling"
47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
48a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystatic cl::opt<std::string>
49a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyDefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden,
50a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky                   cl::ValueRequired);
514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> DefaultExitBlockBeforeBody("gcov-exit-block-before-body",
524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar                                                cl::init(false), cl::Hidden);
53a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky
54a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyGCOVOptions GCOVOptions::getDefault() {
55a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  GCOVOptions Options;
56a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  Options.EmitNotes = true;
57a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  Options.EmitData = true;
58a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  Options.UseCfgChecksum = false;
59a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  Options.NoRedZone = false;
60a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  Options.FunctionNamesInData = true;
614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  Options.ExitBlockBeforeBody = DefaultExitBlockBeforeBody;
62a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky
63a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  if (DefaultGCOVVersion.size() != 4) {
64a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky    llvm::report_fatal_error(std::string("Invalid -default-gcov-version: ") +
65a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky                             DefaultGCOVVersion);
66a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  }
67a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  memcpy(Options.Version, DefaultGCOVVersion.c_str(), 4);
68a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  return Options;
69a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky}
70a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky
71b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace {
72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass GCOVFunction;
73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass GCOVProfiler {
75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarpublic:
76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {}
77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GCOVProfiler(const GCOVOptions &Opts) : Options(Opts) {
78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    assert((Options.EmitNotes || Options.EmitData) &&
79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar           "GCOVProfiler asked to do nothing?");
80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    ReversedVersion[0] = Options.Version[3];
81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    ReversedVersion[1] = Options.Version[2];
82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    ReversedVersion[2] = Options.Version[1];
83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    ReversedVersion[3] = Options.Version[0];
84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    ReversedVersion[4] = '\0';
85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  bool runOnModule(Module &M);
87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarprivate:
89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Create the .gcno files for the Module based on DebugInfo.
90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void emitProfileNotes();
91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Modify the program to track transitions along edges and call into the
93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // profiling runtime to emit .gcda files when run.
94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  bool emitProfileArcs();
95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Get pointers to the functions in the runtime library.
97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Constant *getStartFileFunc();
98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Constant *getIncrementIndirectCounterFunc();
99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Constant *getEmitFunctionFunc();
100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Constant *getEmitArcsFunc();
101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Constant *getSummaryInfoFunc();
102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Constant *getEndFileFunc();
103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Create or retrieve an i32 state value that is used to represent the
105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // pred block number for certain non-trivial edges.
106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GlobalVariable *getEdgeStateValue();
107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Produce a table of pointers to counters, by predecessor and successor
109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // block number.
110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GlobalVariable *buildEdgeLookupTable(Function *F, GlobalVariable *Counter,
111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                       const UniqueVector<BasicBlock *> &Preds,
112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                       const UniqueVector<BasicBlock *> &Succs);
113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Add the function to write out all our counters to the global destructor
115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // list.
116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Function *
117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void insertIndirectCounterIncrement();
120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string mangleName(const DICompileUnit *CU, const char *NewStem);
12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GCOVOptions Options;
1244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Reversed, NUL-terminated copy of Options.Version.
126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  char ReversedVersion[5];
127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Checksum, produced by hash of EdgeDestinations
128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  SmallVector<uint32_t, 4> FileChecksums;
129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Module *M;
131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  LLVMContext *Ctx;
132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs;
133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar};
134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass GCOVProfilerLegacyPass : public ModulePass {
136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarpublic:
137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  static char ID;
138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GCOVProfilerLegacyPass()
139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      : GCOVProfilerLegacyPass(GCOVOptions::getDefault()) {}
140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GCOVProfilerLegacyPass(const GCOVOptions &Opts)
141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      : ModulePass(ID), Profiler(Opts) {
142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    initializeGCOVProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  const char *getPassName() const override { return "GCOV Profiler"; }
145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  bool runOnModule(Module &M) override { return Profiler.runOnModule(M); }
147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarprivate:
149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GCOVProfiler Profiler;
150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar};
151b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
152b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar GCOVProfilerLegacyPass::ID = 0;
154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarINITIALIZE_PASS(GCOVProfilerLegacyPass, "insert-gcov-profiling",
155b1928704201034c785a26296a49f69355eb56a05Nick Lewycky                "Insert instrumentation for GCOV profiling", false, false)
156b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
157a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) {
158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  return new GCOVProfilerLegacyPass(Options);
159a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky}
160b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
1616948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic StringRef getFunctionName(const DISubprogram *SP) {
1620c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  if (!SP->getLinkageName().empty())
1630c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    return SP->getLinkageName();
1640c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  return SP->getName();
1655d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky}
1665d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky
167b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace {
168b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  class GCOVRecord {
169b1928704201034c785a26296a49f69355eb56a05Nick Lewycky   protected:
170d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper    static const char *const LinesTag;
171d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper    static const char *const FunctionTag;
172d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper    static const char *const BlockTag;
173d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper    static const char *const EdgeTag;
174b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
1750c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    GCOVRecord() = default;
176b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
1771790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    void writeBytes(const char *Bytes, int Size) {
1781790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      os->write(Bytes, Size);
179b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
180b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
1811790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    void write(uint32_t i) {
1821790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      writeBytes(reinterpret_cast<char*>(&i), 4);
183b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
184b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
185b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    // Returns the length measured in 4-byte blocks that will be used to
186b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    // represent this string in a GCOV file
187619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper    static unsigned lengthOfGCOVString(StringRef s) {
188b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs
18917df2c3240837b4382898ead8c3ead407a338520Nick Lewycky      // padding out to the next 4-byte word. The length is measured in 4-byte
19017df2c3240837b4382898ead8c3ead407a338520Nick Lewycky      // words including padding, not bytes of actual string.
191d363ff334d796c7f3df834d928a10d88ed758454Nick Lewycky      return (s.size() / 4) + 1;
192b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
193b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
1941790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    void writeGCOVString(StringRef s) {
1951790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      uint32_t Len = lengthOfGCOVString(s);
1961790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      write(Len);
1971790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      writeBytes(s.data(), s.size());
198b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
199b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      // Write 1 to 4 bytes of NUL padding.
2007a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky      assert((unsigned)(4 - (s.size() % 4)) > 0);
2017a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky      assert((unsigned)(4 - (s.size() % 4)) <= 4);
2027a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky      writeBytes("\0\0\0\0", 4 - (s.size() % 4));
203b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
204b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
205b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    raw_ostream *os;
206b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  };
207d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper  const char *const GCOVRecord::LinesTag = "\0\0\x45\x01";
208d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper  const char *const GCOVRecord::FunctionTag = "\0\0\0\1";
209d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper  const char *const GCOVRecord::BlockTag = "\0\0\x41\x01";
210d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper  const char *const GCOVRecord::EdgeTag = "\0\0\x43\x01";
211b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
212b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  class GCOVFunction;
213b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  class GCOVBlock;
214b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
215b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  // Constructed only by requesting it from a GCOVBlock, this object stores a
21616c19a155c65fd41865562fe4e678ef32728510bDevang Patel  // list of line numbers and a single filename, representing lines that belong
21716c19a155c65fd41865562fe4e678ef32728510bDevang Patel  // to the block.
218b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  class GCOVLines : public GCOVRecord {
219b1928704201034c785a26296a49f69355eb56a05Nick Lewycky   public:
2201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    void addLine(uint32_t Line) {
221c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      assert(Line != 0 && "Line zero is not a valid real line number.");
2221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      Lines.push_back(Line);
223b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
224b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
225619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper    uint32_t length() const {
226bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky      // Here 2 = 1 for string length + 1 for '0' id#.
22716c19a155c65fd41865562fe4e678ef32728510bDevang Patel      return lengthOfGCOVString(Filename) + 2 + Lines.size();
228b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
229b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
23016c19a155c65fd41865562fe4e678ef32728510bDevang Patel    void writeOut() {
23116c19a155c65fd41865562fe4e678ef32728510bDevang Patel      write(0);
23216c19a155c65fd41865562fe4e678ef32728510bDevang Patel      writeGCOVString(Filename);
23316c19a155c65fd41865562fe4e678ef32728510bDevang Patel      for (int i = 0, e = Lines.size(); i != e; ++i)
23416c19a155c65fd41865562fe4e678ef32728510bDevang Patel        write(Lines[i]);
23516c19a155c65fd41865562fe4e678ef32728510bDevang Patel    }
236b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    GCOVLines(StringRef F, raw_ostream *os)
23816c19a155c65fd41865562fe4e678ef32728510bDevang Patel      : Filename(F) {
239b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      this->os = os;
240b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
241b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
242680018ff8965610b3f1c976b0be1dfd45116b218Devang Patel   private:
24316c19a155c65fd41865562fe4e678ef32728510bDevang Patel    StringRef Filename;
2441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    SmallVector<uint32_t, 32> Lines;
245b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  };
246b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
247c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky
248b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  // Represent a basic block in GCOV. Each block has a unique number in the
249b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  // function, number of lines belonging to each block, and a set of edges to
250b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  // other blocks.
251b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  class GCOVBlock : public GCOVRecord {
252b1928704201034c785a26296a49f69355eb56a05Nick Lewycky   public:
25368155d31cd0175be89e26ee68387cb411fca537bDevang Patel    GCOVLines &getFile(StringRef Filename) {
2541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      GCOVLines *&Lines = LinesByFile[Filename];
2551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      if (!Lines) {
25616c19a155c65fd41865562fe4e678ef32728510bDevang Patel        Lines = new GCOVLines(Filename, os);
257b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
2581790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      return *Lines;
259b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
260b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
2611790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    void addEdge(GCOVBlock &Successor) {
2621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      OutEdges.push_back(&Successor);
263b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
264b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
2651790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    void writeOut() {
2661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      uint32_t Len = 3;
267c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky      SmallVector<StringMapEntry<GCOVLines *> *, 32> SortedLinesByFile;
268de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      for (auto &I : LinesByFile) {
269de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        Len += I.second->length();
270de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        SortedLinesByFile.push_back(&I);
271b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
272b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
2731790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      writeBytes(LinesTag, 4);
2741790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      write(Len);
2751790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      write(Number);
276c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky
27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      std::sort(SortedLinesByFile.begin(), SortedLinesByFile.end(),
27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                [](StringMapEntry<GCOVLines *> *LHS,
27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                   StringMapEntry<GCOVLines *> *RHS) {
28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return LHS->getKey() < RHS->getKey();
28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      });
282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      for (auto &I : SortedLinesByFile)
283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        I->getValue()->writeOut();
2841790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      write(0);
2851790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      write(0);
286b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
287b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
288b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    ~GCOVBlock() {
2891790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      DeleteContainerSeconds(LinesByFile);
290b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
291b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
292ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    GCOVBlock(const GCOVBlock &RHS) : GCOVRecord(RHS), Number(RHS.Number) {
293ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      // Only allow copy before edges and lines have been added. After that,
294ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      // there are inter-block pointers (eg: edges) that won't take kindly to
295ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      // blocks being copied or moved around.
296ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      assert(LinesByFile.empty());
297ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      assert(OutEdges.empty());
298ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    }
299ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines
300b1928704201034c785a26296a49f69355eb56a05Nick Lewycky   private:
301b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    friend class GCOVFunction;
302b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
3031790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    GCOVBlock(uint32_t Number, raw_ostream *os)
3041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        : Number(Number) {
305b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      this->os = os;
306b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
307b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
3081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    uint32_t Number;
3091790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    StringMap<GCOVLines *> LinesByFile;
3101790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    SmallVector<GCOVBlock *, 4> OutEdges;
311b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  };
312b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
313b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  // A function has a unique identifier, a checksum (we leave as zero) and a
314b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  // set of blocks and a map of edges between blocks. This is the only GCOV
315b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  // object users can construct, the blocks and lines will be rooted here.
316b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  class GCOVFunction : public GCOVRecord {
317b1928704201034c785a26296a49f69355eb56a05Nick Lewycky   public:
318f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     GCOVFunction(const DISubprogram *SP, Function *F, raw_ostream *os,
319f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                  uint32_t Ident, bool UseCfgChecksum, bool ExitBlockBeforeBody)
320ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines         : SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0),
321ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines           ReturnBlock(1, os) {
322b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      this->os = os;
323b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      DEBUG(dbgs() << "Function: " << getFunctionName(SP) << "\n");
325ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines
326b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      uint32_t i = 0;
327ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      for (auto &BB : *F) {
3284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        // Skip index 1 if it's assigned to the ReturnBlock.
3294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        if (i == 1 && ExitBlockBeforeBody)
3304c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar          ++i;
3314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        Blocks.insert(std::make_pair(&BB, GCOVBlock(i++, os)));
332b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
3334c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      if (!ExitBlockBeforeBody)
3344c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        ReturnBlock.Number = i;
3351790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      std::string FunctionNameAndLine;
33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      raw_string_ostream FNLOS(FunctionNameAndLine);
3380c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      FNLOS << getFunctionName(SP) << SP->getLine();
33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      FNLOS.flush();
34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      FuncChecksum = hash_value(FunctionNameAndLine);
341b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
342b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
3431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    GCOVBlock &getBlock(BasicBlock *BB) {
344ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      return Blocks.find(BB)->second;
345b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
346b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
3471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    GCOVBlock &getReturnBlock() {
348ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      return ReturnBlock;
349a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky    }
350a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky
35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string getEdgeDestinations() {
35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      std::string EdgeDestinations;
35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      raw_string_ostream EDOS(EdgeDestinations);
35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Function *F = Blocks.begin()->first->getParent();
355f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      for (BasicBlock &I : *F) {
356f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        GCOVBlock &Block = getBlock(&I);
35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        for (int i = 0, e = Block.OutEdges.size(); i != e; ++i)
35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          EDOS << Block.OutEdges[i]->Number;
35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      }
36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return EdgeDestinations;
36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint32_t getFuncChecksum() {
36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return FuncChecksum;
36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void setCfgChecksum(uint32_t Checksum) {
36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      CfgChecksum = Checksum;
36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3711790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    void writeOut() {
37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      writeBytes(FunctionTag, 4);
37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) +
3740c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                          1 + lengthOfGCOVString(SP->getFilename()) + 1;
37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (UseCfgChecksum)
37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        ++BlockLen;
37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      write(BlockLen);
37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      write(Ident);
37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      write(FuncChecksum);
38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (UseCfgChecksum)
38136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        write(CfgChecksum);
38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      writeGCOVString(getFunctionName(SP));
3830c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      writeGCOVString(SP->getFilename());
3840c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      write(SP->getLine());
38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
386b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      // Emit count of blocks.
3871790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      writeBytes(BlockTag, 4);
3881790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      write(Blocks.size() + 1);
3891790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      for (int i = 0, e = Blocks.size() + 1; i != e; ++i) {
3901790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        write(0);  // No flags on our blocks.
391b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
392bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky      DEBUG(dbgs() << Blocks.size() << " blocks.\n");
393b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
394b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      // Emit edges between blocks.
395c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky      if (Blocks.empty()) return;
396c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky      Function *F = Blocks.begin()->first->getParent();
397f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      for (BasicBlock &I : *F) {
398f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        GCOVBlock &Block = getBlock(&I);
3991790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        if (Block.OutEdges.empty()) continue;
4001790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
4011790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        writeBytes(EdgeTag, 4);
4021790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        write(Block.OutEdges.size() * 2 + 1);
4031790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        write(Block.Number);
4041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) {
405bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky          DEBUG(dbgs() << Block.Number << " -> " << Block.OutEdges[i]->Number
406bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky                       << "\n");
4071790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky          write(Block.OutEdges[i]->Number);
4081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky          write(0);  // no flags
409b1928704201034c785a26296a49f69355eb56a05Nick Lewycky        }
410b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
411b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
412b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      // Emit lines for each block.
413f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      for (BasicBlock &I : *F)
414f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        getBlock(&I).writeOut();
415b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
416b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
417b1928704201034c785a26296a49f69355eb56a05Nick Lewycky   private:
4186948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar     const DISubprogram *SP;
41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint32_t Ident;
42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint32_t FuncChecksum;
42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool UseCfgChecksum;
42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint32_t CfgChecksum;
423ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    DenseMap<BasicBlock *, GCOVBlock> Blocks;
424ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    GCOVBlock ReturnBlock;
425b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  };
426b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
427b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
4286948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstd::string GCOVProfiler::mangleName(const DICompileUnit *CU,
4296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                                     const char *NewStem) {
430269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky  if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) {
431269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky    for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) {
432269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky      MDNode *N = GCov->getOperand(i);
433269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky      if (N->getNumOperands() != 2) continue;
434fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky      MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0));
435269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky      MDNode *CompileUnit = dyn_cast<MDNode>(N->getOperand(1));
436fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky      if (!GCovFile || !CompileUnit) continue;
437fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky      if (CompileUnit == CU) {
4386e5190c193f6267893daf6943af88e95039e739cBill Wendling        SmallString<128> Filename = GCovFile->getString();
4396e5190c193f6267893daf6943af88e95039e739cBill Wendling        sys::path::replace_extension(Filename, NewStem);
4406e5190c193f6267893daf6943af88e95039e739cBill Wendling        return Filename.str();
441fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky      }
442269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky    }
443269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky  }
444fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky
4450c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  SmallString<128> Filename = CU->getFilename();
446fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky  sys::path::replace_extension(Filename, NewStem);
44739c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling  StringRef FName = sys::path::filename(Filename);
44839c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling  SmallString<128> CurPath;
44939c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling  if (sys::fs::current_path(CurPath)) return FName;
4500c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  sys::path::append(CurPath, FName);
45139c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling  return CurPath.str();
452269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky}
453269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky
4540c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewyckybool GCOVProfiler::runOnModule(Module &M) {
4551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  this->M = &M;
4560c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky  Ctx = &M.getContext();
4570c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky
458a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  if (Options.EmitNotes) emitProfileNotes();
459a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  if (Options.EmitData) return emitProfileArcs();
460a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky  return false;
4610c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky}
4620c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky
463de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarPreservedAnalyses GCOVProfilerPass::run(Module &M,
464de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                        AnalysisManager<Module> &AM) {
465de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
466de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  GCOVProfiler Profiler(GCOVOpts);
467de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
468de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  if (!Profiler.runOnModule(M))
469de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    return PreservedAnalyses::all();
470de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
471de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  return PreservedAnalyses::none();
472de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
473de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
474de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic bool functionHasLines(Function &F) {
475dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Check whether this function actually has any source lines. Not only
476dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // do these waste space, they also can crash gcov.
477de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (auto &BB : F) {
478de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    for (auto &I : BB) {
479c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // Debug intrinsic locations correspond to the location of the
480c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // declaration, not necessarily any statements or expressions.
481de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (isa<DbgInfoIntrinsic>(&I)) continue;
482c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
483de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      const DebugLoc &Loc = I.getDebugLoc();
4840c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      if (!Loc)
4850c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar        continue;
486c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
487c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // Artificial lines such as calls to the global constructors.
4884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      if (Loc.getLine() == 0) continue;
489c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
490c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      return true;
491dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
492dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
493dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return false;
494dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
495dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
49664a0a33307723957bf2f15e3181a290853c6f833Nick Lewyckyvoid GCOVProfiler::emitProfileNotes() {
497f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
498bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky  if (!CU_Nodes) return;
499bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky
500bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky  for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
501bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky    // Each compile unit gets its own .gcno file. This means that whether we run
502bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky    // this pass over the original .o's as they're produced, or run it after
503bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky    // LTO, we'll generate the same .gcno files.
504bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky
5056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i));
506de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
507de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    // Skip module skeleton (and module) CUs.
508de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (CU->getDWOId())
509de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      continue;
510de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
51137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    std::error_code EC;
51237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    raw_fd_ostream out(mangleName(CU, "gcno"), EC, sys::fs::F_None);
51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string EdgeDestinations;
514bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky
51537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    unsigned FunctionIdent = 0;
516de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    for (auto &F : M->functions()) {
517de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      DISubprogram *SP = F.getSubprogram();
518de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (!SP) continue;
519dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (!functionHasLines(F)) continue;
52036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
52136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // gcov expects every function to start with an entry block that has a
52236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // single successor, so split the entry block to make sure of that.
523de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      BasicBlock &EntryBlock = F.getEntryBlock();
52436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      BasicBlock::iterator It = EntryBlock.begin();
52536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      while (isa<AllocaInst>(*It) || isa<DbgInfoIntrinsic>(*It))
52636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        ++It;
52736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      EntryBlock.splitBasicBlock(It);
52836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
529de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      Funcs.push_back(make_unique<GCOVFunction>(SP, &F, &out, FunctionIdent++,
5304c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar                                                Options.UseCfgChecksum,
5314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar                                                Options.ExitBlockBeforeBody));
532dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      GCOVFunction &Func = *Funcs.back();
533bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky
534de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      for (auto &BB : F) {
535de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        GCOVBlock &Block = Func.getBlock(&BB);
536de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        TerminatorInst *TI = BB.getTerminator();
537bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky        if (int successors = TI->getNumSuccessors()) {
538bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky          for (int i = 0; i != successors; ++i) {
539dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
540f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          }
541bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky        } else if (isa<ReturnInst>(TI)) {
542dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines          Block.addEdge(Func.getReturnBlock());
543bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky        }
544bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky
545bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky        uint32_t Line = 0;
546de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        for (auto &I : BB) {
547c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          // Debug intrinsic locations correspond to the location of the
548c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          // declaration, not necessarily any statements or expressions.
549de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar          if (isa<DbgInfoIntrinsic>(&I)) continue;
550c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
551de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar          const DebugLoc &Loc = I.getDebugLoc();
5520c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          if (!Loc)
5530c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar            continue;
554c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
555c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          // Artificial lines such as calls to the global constructors.
556c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines          if (Loc.getLine() == 0) continue;
557c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
558bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky          if (Line == Loc.getLine()) continue;
559bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky          Line = Loc.getLine();
5600c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          if (SP != getDISubprogram(Loc.getScope()))
5610c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar            continue;
562bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky
5630c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          GCOVLines &Lines = Block.getFile(SP->getFilename());
564bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky          Lines.addLine(Loc.getLine());
565b1928704201034c785a26296a49f69355eb56a05Nick Lewycky        }
566b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
567dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      EdgeDestinations += Func.getEdgeDestinations();
568b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
56936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
57036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    FileChecksums.push_back(hash_value(EdgeDestinations));
57136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    out.write("oncg", 4);
57236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    out.write(ReversedVersion, 4);
57336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    out.write(reinterpret_cast<char*>(&FileChecksums.back()), 4);
57436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
575dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (auto &Func : Funcs) {
57636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Func->setCfgChecksum(FileChecksums.back());
57736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Func->writeOut();
57836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
57936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
580bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky    out.write("\0\0\0\0\0\0\0\0", 8);  // EOF
581bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky    out.close();
582b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  }
583b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
584b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
585f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patelbool GCOVProfiler::emitProfileArcs() {
586f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
587f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel  if (!CU_Nodes) return false;
588f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel
58936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool Result = false;
59077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  bool InsertIndCounterIncrCode = false;
591f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel  for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
592f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel    SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP;
593de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    for (auto &F : M->functions()) {
594de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      DISubprogram *SP = F.getSubprogram();
595de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (!SP) continue;
596dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (!functionHasLines(F)) continue;
597f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      if (!Result) Result = true;
598f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      unsigned Edges = 0;
599de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      for (auto &BB : F) {
600de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        TerminatorInst *TI = BB.getTerminator();
601f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        if (isa<ReturnInst>(TI))
602f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          ++Edges;
603f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        else
604f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          Edges += TI->getNumSuccessors();
605f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      }
60636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
607f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      ArrayType *CounterTy =
6081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        ArrayType::get(Type::getInt64Ty(*Ctx), Edges);
609f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      GlobalVariable *Counters =
6101790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        new GlobalVariable(*M, CounterTy, false,
611b1928704201034c785a26296a49f69355eb56a05Nick Lewycky                           GlobalValue::InternalLinkage,
6121790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                           Constant::getNullValue(CounterTy),
613ce718ff9f42c7da092eaa01dd0242e8d5ba84713Hans Wennborg                           "__llvm_gcov_ctr");
6140c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      CountersBySP.push_back(std::make_pair(Counters, SP));
61536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
616f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      UniqueVector<BasicBlock *> ComplexEdgePreds;
617f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      UniqueVector<BasicBlock *> ComplexEdgeSuccs;
61836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
619f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      unsigned Edge = 0;
620de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      for (auto &BB : F) {
621de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        TerminatorInst *TI = BB.getTerminator();
622f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
623f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        if (Successors) {
624f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          if (Successors == 1) {
625de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            IRBuilder<> Builder(&*BB.getFirstInsertionPt());
626f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel            Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
627f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel                                                                Edge);
628f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel            Value *Count = Builder.CreateLoad(Counter);
629bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky            Count = Builder.CreateAdd(Count, Builder.getInt64(1));
630f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel            Builder.CreateStore(Count, Counter);
631f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
632f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling            IRBuilder<> Builder(BI);
633bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky            Value *Sel = Builder.CreateSelect(BI->getCondition(),
634bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky                                              Builder.getInt64(Edge),
635bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky                                              Builder.getInt64(Edge + 1));
636de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            Value *Counter = Builder.CreateInBoundsGEP(
637de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                Counters->getValueType(), Counters, {Builder.getInt64(0), Sel});
638f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel            Value *Count = Builder.CreateLoad(Counter);
639bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky            Count = Builder.CreateAdd(Count, Builder.getInt64(1));
640f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel            Builder.CreateStore(Count, Counter);
641f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          } else {
642de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            ComplexEdgePreds.insert(&BB);
643f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel            for (int i = 0; i != Successors; ++i)
644f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel              ComplexEdgeSuccs.insert(TI->getSuccessor(i));
645f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          }
646f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling
647f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          Edge += Successors;
648b1928704201034c785a26296a49f69355eb56a05Nick Lewycky        }
649b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
65036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
651f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      if (!ComplexEdgePreds.empty()) {
652f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        GlobalVariable *EdgeTable =
653de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar          buildEdgeLookupTable(&F, Counters,
6541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                               ComplexEdgePreds, ComplexEdgeSuccs);
655f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        GlobalVariable *EdgeState = getEdgeStateValue();
65636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
657f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) {
658f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar          IRBuilder<> Builder(&*ComplexEdgePreds[i + 1]->getFirstInsertionPt());
659bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky          Builder.CreateStore(Builder.getInt32(i), EdgeState);
660f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        }
661f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling
662f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
663f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling          // Call runtime to perform increment.
664f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar          IRBuilder<> Builder(&*ComplexEdgeSuccs[i + 1]->getFirstInsertionPt());
665f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel          Value *CounterPtrArray =
6661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky            Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
6671790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                                               i * ComplexEdgePreds.size());
668c7a884040e4ec7795515978a94803894ad08c4caBill Wendling
669c7a884040e4ec7795515978a94803894ad08c4caBill Wendling          // Build code to increment the counter.
67077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling          InsertIndCounterIncrCode = true;
6716948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar          Builder.CreateCall(getIncrementIndirectCounterFunc(),
6726948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                             {EdgeState, CounterPtrArray});
673f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        }
674b1928704201034c785a26296a49f69355eb56a05Nick Lewycky      }
675b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
6764a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling
677d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    Function *WriteoutF = insertCounterWriteout(CountersBySP);
678d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    Function *FlushF = insertFlush(CountersBySP);
679d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling
680d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    // Create a small bit of code that registers the "__llvm_gcov_writeout" to
68118764716861243c58a711a92190624dc2f6aafc9Bill Wendling    // be executed at exit and the "__llvm_gcov_flush" function to be executed
68218764716861243c58a711a92190624dc2f6aafc9Bill Wendling    // when "__gcov_flush" is called.
683d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
684d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
685d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling                                   "__llvm_gcov_init", M);
686de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
687d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    F->setLinkage(GlobalValue::InternalLinkage);
688d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    F->addFnAttr(Attribute::NoInline);
689d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    if (Options.NoRedZone)
690d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling      F->addFnAttr(Attribute::NoRedZone);
691d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling
692d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
693d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    IRBuilder<> Builder(BB);
694d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling
695d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
6968640c6a5227b75666e02424e2181289692138348Bill Wendling    Type *Params[] = {
6978640c6a5227b75666e02424e2181289692138348Bill Wendling      PointerType::get(FTy, 0),
6988640c6a5227b75666e02424e2181289692138348Bill Wendling      PointerType::get(FTy, 0)
6998640c6a5227b75666e02424e2181289692138348Bill Wendling    };
7008640c6a5227b75666e02424e2181289692138348Bill Wendling    FTy = FunctionType::get(Builder.getVoidTy(), Params, false);
7018640c6a5227b75666e02424e2181289692138348Bill Wendling
702d7da59004fc9262f33c96ad2736b36ff1235ce7bYuchen Wu    // Initialize the environment and register the local writeout and flush
7038640c6a5227b75666e02424e2181289692138348Bill Wendling    // functions.
7048640c6a5227b75666e02424e2181289692138348Bill Wendling    Constant *GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy);
7056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    Builder.CreateCall(GCOVInit, {WriteoutF, FlushF});
706d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    Builder.CreateRetVoid();
707d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling
708d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    appendToGlobalCtors(*M, F, 0);
709b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  }
71077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
71177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  if (InsertIndCounterIncrCode)
71277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling    insertIndirectCounterIncrement();
71377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
714f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel  return Result;
715b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
716b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
7171790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky// All edges with successors that aren't branches are "complex", because it
7181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky// requires complex logic to pick which counter to update.
7191790c9cbb6714e81eab1412909a2320acaecc43bNick LewyckyGlobalVariable *GCOVProfiler::buildEdgeLookupTable(
7201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    Function *F,
7211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    GlobalVariable *Counters,
7221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    const UniqueVector<BasicBlock *> &Preds,
7231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    const UniqueVector<BasicBlock *> &Succs) {
7241790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  // TODO: support invoke, threads. We rely on the fact that nothing can modify
7251790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  // the whole-Module pred edge# between the time we set it and the time we next
7261790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  // read it. Threads and invoke make this untrue.
7271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
7281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]].
7299e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer  size_t TableSize = Succs.size() * Preds.size();
730db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner  Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
7319e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer  ArrayType *EdgeTableTy = ArrayType::get(Int64PtrTy, TableSize);
7321790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
73336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<Constant * []> EdgeTable(new Constant *[TableSize]);
7341790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  Constant *NullValue = Constant::getNullValue(Int64PtrTy);
7359e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer  for (size_t i = 0; i != TableSize; ++i)
7361790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    EdgeTable[i] = NullValue;
7371790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
7381790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  unsigned Edge = 0;
739de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (BasicBlock &BB : *F) {
740de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    TerminatorInst *TI = BB.getTerminator();
7411790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
7427a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky    if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) {
7431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      for (int i = 0; i != Successors; ++i) {
7441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky        BasicBlock *Succ = TI->getSuccessor(i);
745bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky        IRBuilder<> Builder(Succ);
746bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky        Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
7471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                                                            Edge + i);
748f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        EdgeTable[((Succs.idFor(Succ) - 1) * Preds.size()) +
749de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                  (Preds.idFor(&BB) - 1)] = cast<Constant>(Counter);
7501790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      }
7511790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    }
7521790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    Edge += Successors;
7531790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  }
7541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
7551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  GlobalVariable *EdgeTableGV =
7561790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky      new GlobalVariable(
7571790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky          *M, EdgeTableTy, true, GlobalValue::InternalLinkage,
75837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines          ConstantArray::get(EdgeTableTy,
75937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                             makeArrayRef(&EdgeTable[0],TableSize)),
7601790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky          "__llvm_gcda_edge_table");
761de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  EdgeTableGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
7621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  return EdgeTableGV;
7631790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky}
7641790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
765b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getStartFileFunc() {
766d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky  Type *Args[] = {
767d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky    Type::getInt8PtrTy(*Ctx),  // const char *orig_filename
768d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky    Type::getInt8PtrTy(*Ctx),  // const char version[4]
76936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type::getInt32Ty(*Ctx),    // uint32_t checksum
770d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky  };
771d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
7721790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
7731790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky}
7741790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky
77577b19134104c3e96424dc010f2b69c3faf580e68Bill WendlingConstant *GCOVProfiler::getIncrementIndirectCounterFunc() {
77677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Type *Int32Ty = Type::getInt32Ty(*Ctx);
777c7a884040e4ec7795515978a94803894ad08c4caBill Wendling  Type *Int64Ty = Type::getInt64Ty(*Ctx);
77877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Type *Args[] = {
779b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow    Int32Ty->getPointerTo(),                // uint32_t *predecessor
780b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow    Int64Ty->getPointerTo()->getPointerTo() // uint64_t **counters
78177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  };
78277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
78377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  return M->getOrInsertFunction("__llvm_gcov_indirect_counter_increment", FTy);
784b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
785b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
786b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitFunctionFunc() {
78736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Type *Args[] = {
7885409a188328d9de3755febc23558d4fc1797d04eNick Lewycky    Type::getInt32Ty(*Ctx),    // uint32_t ident
7895409a188328d9de3755febc23558d4fc1797d04eNick Lewycky    Type::getInt8PtrTy(*Ctx),  // const char *function_name
79036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type::getInt32Ty(*Ctx),    // uint32_t func_checksum
79117d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky    Type::getInt8Ty(*Ctx),     // uint8_t use_extra_checksum
79236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type::getInt32Ty(*Ctx),    // uint32_t cfg_checksum
7935409a188328d9de3755febc23558d4fc1797d04eNick Lewycky  };
794c7a884040e4ec7795515978a94803894ad08c4caBill Wendling  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
7951790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  return M->getOrInsertFunction("llvm_gcda_emit_function", FTy);
796b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
797b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
798b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitArcsFunc() {
7995fdd6c8793462549e3593890ec61573da06e3346Jay Foad  Type *Args[] = {
800b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    Type::getInt32Ty(*Ctx),     // uint32_t num_counters
801b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    Type::getInt64PtrTy(*Ctx),  // uint64_t *counters
802b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  };
803d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
8041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
805b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
806b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
807f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen WuConstant *GCOVProfiler::getSummaryInfoFunc() {
808f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
809f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu  return M->getOrInsertFunction("llvm_gcda_summary_info", FTy);
810f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu}
811f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu
812b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEndFileFunc() {
813db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
8141790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
815b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
816b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
8171790c9cbb6714e81eab1412909a2320acaecc43bNick LewyckyGlobalVariable *GCOVProfiler::getEdgeStateValue() {
8181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred");
8191790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  if (!GV) {
8201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky    GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false,
8211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                            GlobalValue::InternalLinkage,
8221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                            ConstantInt::get(Type::getInt32Ty(*Ctx),
8231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                                             0xffffffff),
8241790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky                            "__llvm_gcov_global_state_pred");
825de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
8261790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  }
8271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  return GV;
8281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky}
829b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
830d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill WendlingFunction *GCOVProfiler::insertCounterWriteout(
83121b742ffce7bec3d71e09c7c6d901a756d55feb3Bill Wendling    ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
832253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
833253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
834253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  if (!WriteoutF)
835253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling    WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage,
836253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling                                 "__llvm_gcov_writeout", M);
837de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
838034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling  WriteoutF->addFnAttr(Attribute::NoInline);
839a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  if (Options.NoRedZone)
840034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling    WriteoutF->addFnAttr(Attribute::NoRedZone);
841253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling
842253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF);
8431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky  IRBuilder<> Builder(BB);
844b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
845b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  Constant *StartFile = getStartFileFunc();
846b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  Constant *EmitFunction = getEmitFunctionFunc();
847b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  Constant *EmitArcs = getEmitArcsFunc();
848f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu  Constant *SummaryInfo = getSummaryInfoFunc();
849b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  Constant *EndFile = getEndFileFunc();
850b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
851f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
852f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel  if (CU_Nodes) {
853f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel    for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
8546948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i));
855de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
856de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      // Skip module skeleton (and module) CUs.
857de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (CU->getDWOId())
858de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        continue;
859de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
860f2a2806baf3763d551a9f361124b608b2eed66faBill Wendling      std::string FilenameGcda = mangleName(CU, "gcda");
86136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      uint32_t CfgChecksum = FileChecksums.empty() ? 0 : FileChecksums[i];
8626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      Builder.CreateCall(StartFile,
8636948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                         {Builder.CreateGlobalStringPtr(FilenameGcda),
86436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                          Builder.CreateGlobalStringPtr(ReversedVersion),
8656948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                          Builder.getInt32(CfgChecksum)});
8668fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky      for (unsigned j = 0, e = CountersBySP.size(); j != e; ++j) {
8676948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        auto *SP = cast_or_null<DISubprogram>(CountersBySP[j].second);
86836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[j]->getFuncChecksum();
8696948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        Builder.CreateCall(
8706948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar            EmitFunction,
8716948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar            {Builder.getInt32(j),
8726948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar             Options.FunctionNamesInData
8736948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                 ? Builder.CreateGlobalStringPtr(getFunctionName(SP))
8746948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                 : Constant::getNullValue(Builder.getInt8PtrTy()),
8756948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar             Builder.getInt32(FuncChecksum),
8766948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar             Builder.getInt8(Options.UseCfgChecksum),
8776948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar             Builder.getInt32(CfgChecksum)});
87817d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky
8798fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky        GlobalVariable *GV = CountersBySP[j].first;
880f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel        unsigned Arcs =
881de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar          cast<ArrayType>(GV->getValueType())->getNumElements();
8826948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        Builder.CreateCall(EmitArcs, {Builder.getInt32(Arcs),
8836948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                                      Builder.CreateConstGEP2_64(GV, 0, 0)});
884f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel      }
8856948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      Builder.CreateCall(SummaryInfo, {});
8866948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      Builder.CreateCall(EndFile, {});
887b1928704201034c785a26296a49f69355eb56a05Nick Lewycky    }
888b1928704201034c785a26296a49f69355eb56a05Nick Lewycky  }
889b1928704201034c785a26296a49f69355eb56a05Nick Lewycky
8904a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling  Builder.CreateRetVoid();
891d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling  return WriteoutF;
892b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}
89377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
89477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendlingvoid GCOVProfiler::insertIndirectCounterIncrement() {
89577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Function *Fn =
89677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling    cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
897de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  Fn->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
89877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Fn->setLinkage(GlobalValue::InternalLinkage);
899034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling  Fn->addFnAttr(Attribute::NoInline);
900a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  if (Options.NoRedZone)
901034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling    Fn->addFnAttr(Attribute::NoRedZone);
90277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
90377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  // Create basic blocks for function.
90477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", Fn);
90577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  IRBuilder<> Builder(BB);
90677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
90777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn);
90877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  BasicBlock *CounterEnd = BasicBlock::Create(*Ctx, "", Fn);
90977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  BasicBlock *Exit = BasicBlock::Create(*Ctx, "exit", Fn);
91077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
91177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  // uint32_t pred = *predecessor;
91277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  // if (pred == 0xffffffff) return;
913f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  Argument *Arg = &*Fn->arg_begin();
91477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Arg->setName("predecessor");
91577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Value *Pred = Builder.CreateLoad(Arg, "pred");
916bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky  Value *Cond = Builder.CreateICmpEQ(Pred, Builder.getInt32(0xffffffff));
91777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  BranchInst::Create(Exit, PredNotNegOne, Cond, BB);
91877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
91977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Builder.SetInsertPoint(PredNotNegOne);
92077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
92177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  // uint64_t *counter = counters[pred];
92277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  // if (!counter) return;
923bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky  Value *ZExtPred = Builder.CreateZExt(Pred, Builder.getInt64Ty());
924f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  Arg = &*std::next(Fn->arg_begin());
92577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Arg->setName("counters");
9260c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  Value *GEP = Builder.CreateGEP(Type::getInt64PtrTy(*Ctx), Arg, ZExtPred);
92777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Value *Counter = Builder.CreateLoad(GEP, "counter");
92858591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky  Cond = Builder.CreateICmpEQ(Counter,
92958591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky                              Constant::getNullValue(
93058591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky                                  Builder.getInt64Ty()->getPointerTo()));
93177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Builder.CreateCondBr(Cond, Exit, CounterEnd);
93277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
93377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  // ++*counter;
93477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Builder.SetInsertPoint(CounterEnd);
93577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter),
936bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky                                 Builder.getInt64(1));
93777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Builder.CreateStore(Add, Counter);
93877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Builder.CreateBr(Exit);
93977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling
94077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  // Fill in the exit block.
94177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Builder.SetInsertPoint(Exit);
94277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling  Builder.CreateRetVoid();
94377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling}
944253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling
945d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill WendlingFunction *GCOVProfiler::
946253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill WendlinginsertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
947253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
948d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling  Function *FlushF = M->getFunction("__llvm_gcov_flush");
949253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  if (!FlushF)
950253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling    FlushF = Function::Create(FTy, GlobalValue::InternalLinkage,
951d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling                              "__llvm_gcov_flush", M);
952253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  else
953253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling    FlushF->setLinkage(GlobalValue::InternalLinkage);
954de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
955034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling  FlushF->addFnAttr(Attribute::NoInline);
956a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky  if (Options.NoRedZone)
957034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling    FlushF->addFnAttr(Attribute::NoRedZone);
958253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling
959253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF);
960253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling
961253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  // Write out the current counters.
962253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  Constant *WriteoutF = M->getFunction("__llvm_gcov_writeout");
963253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  assert(WriteoutF && "Need to create the writeout function first!");
964253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling
965253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  IRBuilder<> Builder(Entry);
9666948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  Builder.CreateCall(WriteoutF, {});
967253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling
968032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling  // Zero out the counters.
969de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  for (const auto &I : CountersBySP) {
970de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    GlobalVariable *GV = I.first;
971de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    Constant *Null = Constant::getNullValue(GV->getValueType());
972ec3fc2eac0e9203dd1094b9ce458e8c1b42b832fBill Wendling    Builder.CreateStore(Null, GV);
973032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling  }
974253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling
975253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  Type *RetTy = FlushF->getReturnType();
976253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  if (RetTy == Type::getVoidTy(*Ctx))
977253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling    Builder.CreateRetVoid();
978253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  else if (RetTy->isIntegerTy())
979d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    // Used if __llvm_gcov_flush was implicitly declared.
980253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling    Builder.CreateRet(ConstantInt::get(RetTy, 0));
981253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling  else
982d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling    report_fatal_error("invalid return type for __llvm_gcov_flush");
983d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling
984d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling  return FlushF;
985253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling}
986