Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This pass implements GCOV-style profiling. When this pass is run it emits
10
// "gcno" files next to the existing source, and instruments the code that runs
11
// to records the edges between blocks that run and emit a complementary "gcda"
12
// file on exit.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "llvm/ADT/DenseMap.h"
17
#include "llvm/ADT/Hashing.h"
18
#include "llvm/ADT/STLExtras.h"
19
#include "llvm/ADT/Sequence.h"
20
#include "llvm/ADT/Statistic.h"
21
#include "llvm/ADT/StringExtras.h"
22
#include "llvm/ADT/StringMap.h"
23
#include "llvm/Analysis/EHPersonalities.h"
24
#include "llvm/Analysis/TargetLibraryInfo.h"
25
#include "llvm/IR/CFG.h"
26
#include "llvm/IR/DebugInfo.h"
27
#include "llvm/IR/DebugLoc.h"
28
#include "llvm/IR/IRBuilder.h"
29
#include "llvm/IR/InstIterator.h"
30
#include "llvm/IR/Instructions.h"
31
#include "llvm/IR/IntrinsicInst.h"
32
#include "llvm/IR/Module.h"
33
#include "llvm/Pass.h"
34
#include "llvm/Support/CommandLine.h"
35
#include "llvm/Support/Debug.h"
36
#include "llvm/Support/FileSystem.h"
37
#include "llvm/Support/Path.h"
38
#include "llvm/Support/Regex.h"
39
#include "llvm/Support/raw_ostream.h"
40
#include "llvm/Transforms/Instrumentation.h"
41
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
42
#include "llvm/Transforms/Utils/ModuleUtils.h"
43
#include <algorithm>
44
#include <memory>
45
#include <string>
46
#include <utility>
47
using namespace llvm;
48
49
#define DEBUG_TYPE "insert-gcov-profiling"
50
51
static cl::opt<std::string>
52
DefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden,
53
                   cl::ValueRequired);
54
static cl::opt<bool> DefaultExitBlockBeforeBody("gcov-exit-block-before-body",
55
                                                cl::init(false), cl::Hidden);
56
57
21
GCOVOptions GCOVOptions::getDefault() {
58
21
  GCOVOptions Options;
59
21
  Options.EmitNotes = true;
60
21
  Options.EmitData = true;
61
21
  Options.UseCfgChecksum = false;
62
21
  Options.NoRedZone = false;
63
21
  Options.FunctionNamesInData = true;
64
21
  Options.ExitBlockBeforeBody = DefaultExitBlockBeforeBody;
65
21
66
21
  if (DefaultGCOVVersion.size() != 4) {
67
2
    llvm::report_fatal_error(std::string("Invalid -default-gcov-version: ") +
68
2
                             DefaultGCOVVersion);
69
2
  }
70
19
  memcpy(Options.Version, DefaultGCOVVersion.c_str(), 4);
71
19
  return Options;
72
19
}
73
74
namespace {
75
class GCOVFunction;
76
77
class GCOVProfiler {
78
public:
79
0
  GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {}
80
33
  GCOVProfiler(const GCOVOptions &Opts) : Options(Opts) {
81
33
    assert((Options.EmitNotes || Options.EmitData) &&
82
33
           "GCOVProfiler asked to do nothing?");
83
33
    ReversedVersion[0] = Options.Version[3];
84
33
    ReversedVersion[1] = Options.Version[2];
85
33
    ReversedVersion[2] = Options.Version[1];
86
33
    ReversedVersion[3] = Options.Version[0];
87
33
    ReversedVersion[4] = '\0';
88
33
  }
89
  bool runOnModule(Module &M, const TargetLibraryInfo &TLI);
90
91
private:
92
  // Create the .gcno files for the Module based on DebugInfo.
93
  void emitProfileNotes();
94
95
  // Modify the program to track transitions along edges and call into the
96
  // profiling runtime to emit .gcda files when run.
97
  bool emitProfileArcs();
98
99
  bool isFunctionInstrumented(const Function &F);
100
  std::vector<Regex> createRegexesFromString(StringRef RegexesStr);
101
  static bool doesFilenameMatchARegex(StringRef Filename,
102
                                      std::vector<Regex> &Regexes);
103
104
  // Get pointers to the functions in the runtime library.
105
  FunctionCallee getStartFileFunc();
106
  FunctionCallee getEmitFunctionFunc();
107
  FunctionCallee getEmitArcsFunc();
108
  FunctionCallee getSummaryInfoFunc();
109
  FunctionCallee getEndFileFunc();
110
111
  // Add the function to write out all our counters to the global destructor
112
  // list.
113
  Function *
114
  insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
115
  Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
116
117
  void AddFlushBeforeForkAndExec();
118
119
  enum class GCovFileType { GCNO, GCDA };
120
  std::string mangleName(const DICompileUnit *CU, GCovFileType FileType);
121
122
  GCOVOptions Options;
123
124
  // Reversed, NUL-terminated copy of Options.Version.
125
  char ReversedVersion[5];
126
  // Checksum, produced by hash of EdgeDestinations
127
  SmallVector<uint32_t, 4> FileChecksums;
128
129
  Module *M;
130
  const TargetLibraryInfo *TLI;
131
  LLVMContext *Ctx;
132
  SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs;
133
  std::vector<Regex> FilterRe;
134
  std::vector<Regex> ExcludeRe;
135
  StringMap<bool> InstrumentedFiles;
136
};
137
138
class GCOVProfilerLegacyPass : public ModulePass {
139
public:
140
  static char ID;
141
  GCOVProfilerLegacyPass()
142
11
      : GCOVProfilerLegacyPass(GCOVOptions::getDefault()) {}
143
  GCOVProfilerLegacyPass(const GCOVOptions &Opts)
144
22
      : ModulePass(ID), Profiler(Opts) {
145
22
    initializeGCOVProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
146
22
  }
147
0
  StringRef getPassName() const override { return "GCOV Profiler"; }
148
149
22
  bool runOnModule(Module &M) override {
150
22
    auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
151
22
    return Profiler.runOnModule(M, TLI);
152
22
  }
153
154
22
  void getAnalysisUsage(AnalysisUsage &AU) const override {
155
22
    AU.addRequired<TargetLibraryInfoWrapperPass>();
156
22
  }
157
158
private:
159
  GCOVProfiler Profiler;
160
};
161
}
162
163
char GCOVProfilerLegacyPass::ID = 0;
164
11.0k
INITIALIZE_PASS_BEGIN(
165
11.0k
    GCOVProfilerLegacyPass, "insert-gcov-profiling",
166
11.0k
    "Insert instrumentation for GCOV profiling", false, false)
167
11.0k
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
168
11.0k
INITIALIZE_PASS_END(
169
    GCOVProfilerLegacyPass, "insert-gcov-profiling",
170
    "Insert instrumentation for GCOV profiling", false, false)
171
172
12
ModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) {
173
12
  return new GCOVProfilerLegacyPass(Options);
174
12
}
175
176
140
static StringRef getFunctionName(const DISubprogram *SP) {
177
140
  if (!SP->getLinkageName().empty())
178
28
    return SP->getLinkageName();
179
112
  return SP->getName();
180
112
}
181
182
/// Extract a filename for a DISubprogram.
183
///
184
/// Prefer relative paths in the coverage notes. Clang also may split
185
/// up absolute paths into a directory and filename component. When
186
/// the relative path doesn't exist, reconstruct the absolute path.
187
108
static SmallString<128> getFilename(const DISubprogram *SP) {
188
108
  SmallString<128> Path;
189
108
  StringRef RelPath = SP->getFilename();
190
108
  if (sys::fs::exists(RelPath))
191
2
    Path = RelPath;
192
106
  else
193
106
    sys::path::append(Path, SP->getDirectory(), SP->getFilename());
194
108
  return Path;
195
108
}
196
197
namespace {
198
  class GCOVRecord {
199
   protected:
200
    static const char *const LinesTag;
201
    static const char *const FunctionTag;
202
    static const char *const BlockTag;
203
    static const char *const EdgeTag;
204
205
    GCOVRecord() = default;
206
207
1.90k
    void writeBytes(const char *Bytes, int Size) {
208
1.90k
      os->write(Bytes, Size);
209
1.90k
    }
210
211
1.35k
    void write(uint32_t i) {
212
1.35k
      writeBytes(reinterpret_cast<char*>(&i), 4);
213
1.35k
    }
214
215
    // Returns the length measured in 4-byte blocks that will be used to
216
    // represent this string in a GCOV file
217
300
    static unsigned lengthOfGCOVString(StringRef s) {
218
300
      // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs
219
300
      // padding out to the next 4-byte word. The length is measured in 4-byte
220
300
      // words including padding, not bytes of actual string.
221
300
      return (s.size() / 4) + 1;
222
300
    }
223
224
150
    void writeGCOVString(StringRef s) {
225
150
      uint32_t Len = lengthOfGCOVString(s);
226
150
      write(Len);
227
150
      writeBytes(s.data(), s.size());
228
150
229
150
      // Write 1 to 4 bytes of NUL padding.
230
150
      assert((unsigned)(4 - (s.size() % 4)) > 0);
231
150
      assert((unsigned)(4 - (s.size() % 4)) <= 4);
232
150
      writeBytes("\0\0\0\0", 4 - (s.size() % 4));
233
150
    }
234
235
    raw_ostream *os;
236
  };
237
  const char *const GCOVRecord::LinesTag = "\0\0\x45\x01";
238
  const char *const GCOVRecord::FunctionTag = "\0\0\0\1";
239
  const char *const GCOVRecord::BlockTag = "\0\0\x41\x01";
240
  const char *const GCOVRecord::EdgeTag = "\0\0\x43\x01";
241
242
  class GCOVFunction;
243
  class GCOVBlock;
244
245
  // Constructed only by requesting it from a GCOVBlock, this object stores a
246
  // list of line numbers and a single filename, representing lines that belong
247
  // to the block.
248
  class GCOVLines : public GCOVRecord {
249
   public:
250
110
    void addLine(uint32_t Line) {
251
110
      assert(Line != 0 && "Line zero is not a valid real line number.");
252
110
      Lines.push_back(Line);
253
110
    }
254
255
84
    uint32_t length() const {
256
84
      // Here 2 = 1 for string length + 1 for '0' id#.
257
84
      return lengthOfGCOVString(Filename) + 2 + Lines.size();
258
84
    }
259
260
84
    void writeOut() {
261
84
      write(0);
262
84
      writeGCOVString(Filename);
263
194
      for (int i = 0, e = Lines.size(); i != e; 
++i110
)
264
110
        write(Lines[i]);
265
84
    }
266
267
    GCOVLines(StringRef F, raw_ostream *os)
268
84
      : Filename(F) {
269
84
      this->os = os;
270
84
    }
271
272
   private:
273
    std::string Filename;
274
    SmallVector<uint32_t, 32> Lines;
275
  };
276
277
278
  // Represent a basic block in GCOV. Each block has a unique number in the
279
  // function, number of lines belonging to each block, and a set of edges to
280
  // other blocks.
281
  class GCOVBlock : public GCOVRecord {
282
   public:
283
110
    GCOVLines &getFile(StringRef Filename) {
284
110
      return LinesByFile.try_emplace(Filename, Filename, os).first->second;
285
110
    }
286
287
94
    void addEdge(GCOVBlock &Successor) {
288
94
      OutEdges.push_back(&Successor);
289
94
    }
290
291
90
    void writeOut() {
292
90
      uint32_t Len = 3;
293
90
      SmallVector<StringMapEntry<GCOVLines> *, 32> SortedLinesByFile;
294
90
      for (auto &I : LinesByFile) {
295
84
        Len += I.second.length();
296
84
        SortedLinesByFile.push_back(&I);
297
84
      }
298
90
299
90
      writeBytes(LinesTag, 4);
300
90
      write(Len);
301
90
      write(Number);
302
90
303
90
      llvm::sort(SortedLinesByFile, [](StringMapEntry<GCOVLines> *LHS,
304
90
                                       StringMapEntry<GCOVLines> *RHS) {
305
0
        return LHS->getKey() < RHS->getKey();
306
0
      });
307
90
      for (auto &I : SortedLinesByFile)
308
84
        I->getValue().writeOut();
309
90
      write(0);
310
90
      write(0);
311
90
    }
312
313
180
    GCOVBlock(const GCOVBlock &RHS) : GCOVRecord(RHS), Number(RHS.Number) {
314
180
      // Only allow copy before edges and lines have been added. After that,
315
180
      // there are inter-block pointers (eg: edges) that won't take kindly to
316
180
      // blocks being copied or moved around.
317
180
      assert(LinesByFile.empty());
318
180
      assert(OutEdges.empty());
319
180
    }
320
321
   private:
322
    friend class GCOVFunction;
323
324
    GCOVBlock(uint32_t Number, raw_ostream *os)
325
123
        : Number(Number) {
326
123
      this->os = os;
327
123
    }
328
329
    uint32_t Number;
330
    StringMap<GCOVLines> LinesByFile;
331
    SmallVector<GCOVBlock *, 4> OutEdges;
332
  };
333
334
  // A function has a unique identifier, a checksum (we leave as zero) and a
335
  // set of blocks and a map of edges between blocks. This is the only GCOV
336
  // object users can construct, the blocks and lines will be rooted here.
337
  class GCOVFunction : public GCOVRecord {
338
   public:
339
     GCOVFunction(const DISubprogram *SP, Function *F, raw_ostream *os,
340
                  uint32_t Ident, bool UseCfgChecksum, bool ExitBlockBeforeBody)
341
         : SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0),
342
33
           ReturnBlock(1, os) {
343
33
      this->os = os;
344
33
345
33
      LLVM_DEBUG(dbgs() << "Function: " << getFunctionName(SP) << "\n");
346
33
347
33
      uint32_t i = 0;
348
90
      for (auto &BB : *F) {
349
90
        // Skip index 1 if it's assigned to the ReturnBlock.
350
90
        if (i == 1 && 
ExitBlockBeforeBody33
)
351
2
          ++i;
352
90
        Blocks.insert(std::make_pair(&BB, GCOVBlock(i++, os)));
353
90
      }
354
33
      if (!ExitBlockBeforeBody)
355
31
        ReturnBlock.Number = i;
356
33
357
33
      std::string FunctionNameAndLine;
358
33
      raw_string_ostream FNLOS(FunctionNameAndLine);
359
33
      FNLOS << getFunctionName(SP) << SP->getLine();
360
33
      FNLOS.flush();
361
33
      FuncChecksum = hash_value(FunctionNameAndLine);
362
33
    }
363
364
454
    GCOVBlock &getBlock(BasicBlock *BB) {
365
454
      return Blocks.find(BB)->second;
366
454
    }
367
368
33
    GCOVBlock &getReturnBlock() {
369
33
      return ReturnBlock;
370
33
    }
371
372
33
    std::string getEdgeDestinations() {
373
33
      std::string EdgeDestinations;
374
33
      raw_string_ostream EDOS(EdgeDestinations);
375
33
      Function *F = Blocks.begin()->first->getParent();
376
90
      for (BasicBlock &I : *F) {
377
90
        GCOVBlock &Block = getBlock(&I);
378
184
        for (int i = 0, e = Block.OutEdges.size(); i != e; 
++i94
)
379
94
          EDOS << Block.OutEdges[i]->Number;
380
90
      }
381
33
      return EdgeDestinations;
382
33
    }
383
384
33
    uint32_t getFuncChecksum() {
385
33
      return FuncChecksum;
386
33
    }
387
388
33
    void setCfgChecksum(uint32_t Checksum) {
389
33
      CfgChecksum = Checksum;
390
33
    }
391
392
33
    void writeOut() {
393
33
      writeBytes(FunctionTag, 4);
394
33
      SmallString<128> Filename = getFilename(SP);
395
33
      uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) +
396
33
                          1 + lengthOfGCOVString(Filename) + 1;
397
33
      if (UseCfgChecksum)
398
0
        ++BlockLen;
399
33
      write(BlockLen);
400
33
      write(Ident);
401
33
      write(FuncChecksum);
402
33
      if (UseCfgChecksum)
403
0
        write(CfgChecksum);
404
33
      writeGCOVString(getFunctionName(SP));
405
33
      writeGCOVString(Filename);
406
33
      write(SP->getLine());
407
33
408
33
      // Emit count of blocks.
409
33
      writeBytes(BlockTag, 4);
410
33
      write(Blocks.size() + 1);
411
156
      for (int i = 0, e = Blocks.size() + 1; i != e; 
++i123
) {
412
123
        write(0);  // No flags on our blocks.
413
123
      }
414
33
      LLVM_DEBUG(dbgs() << Blocks.size() << " blocks.\n");
415
33
416
33
      // Emit edges between blocks.
417
33
      if (Blocks.empty()) 
return0
;
418
33
      Function *F = Blocks.begin()->first->getParent();
419
90
      for (BasicBlock &I : *F) {
420
90
        GCOVBlock &Block = getBlock(&I);
421
90
        if (Block.OutEdges.empty()) 
continue2
;
422
88
423
88
        writeBytes(EdgeTag, 4);
424
88
        write(Block.OutEdges.size() * 2 + 1);
425
88
        write(Block.Number);
426
182
        for (int i = 0, e = Block.OutEdges.size(); i != e; 
++i94
) {
427
94
          LLVM_DEBUG(dbgs() << Block.Number << " -> "
428
94
                            << Block.OutEdges[i]->Number << "\n");
429
94
          write(Block.OutEdges[i]->Number);
430
94
          write(0);  // no flags
431
94
        }
432
88
      }
433
33
434
33
      // Emit lines for each block.
435
33
      for (BasicBlock &I : *F)
436
90
        getBlock(&I).writeOut();
437
33
    }
438
439
   private:
440
     const DISubprogram *SP;
441
    uint32_t Ident;
442
    uint32_t FuncChecksum;
443
    bool UseCfgChecksum;
444
    uint32_t CfgChecksum;
445
    DenseMap<BasicBlock *, GCOVBlock> Blocks;
446
    GCOVBlock ReturnBlock;
447
  };
448
}
449
450
// RegexesStr is a string containing differents regex separated by a semi-colon.
451
// For example "foo\..*$;bar\..*$".
452
66
std::vector<Regex> GCOVProfiler::createRegexesFromString(StringRef RegexesStr) {
453
66
  std::vector<Regex> Regexes;
454
77
  while (!RegexesStr.empty()) {
455
11
    std::pair<StringRef, StringRef> HeadTail = RegexesStr.split(';');
456
11
    if (!HeadTail.first.empty()) {
457
11
      Regex Re(HeadTail.first);
458
11
      std::string Err;
459
11
      if (!Re.isValid(Err)) {
460
0
        Ctx->emitError(Twine("Regex ") + HeadTail.first +
461
0
                       " is not valid: " + Err);
462
0
      }
463
11
      Regexes.emplace_back(std::move(Re));
464
11
    }
465
11
    RegexesStr = HeadTail.second;
466
11
  }
467
66
  return Regexes;
468
66
}
469
470
bool GCOVProfiler::doesFilenameMatchARegex(StringRef Filename,
471
23
                                           std::vector<Regex> &Regexes) {
472
27
  for (Regex &Re : Regexes) {
473
27
    if (Re.match(Filename)) {
474
11
      return true;
475
11
    }
476
27
  }
477
23
  
return false12
;
478
23
}
479
480
102
bool GCOVProfiler::isFunctionInstrumented(const Function &F) {
481
102
  if (FilterRe.empty() && 
ExcludeRe.empty()78
) {
482
60
    return true;
483
60
  }
484
42
  SmallString<128> Filename = getFilename(F.getSubprogram());
485
42
  auto It = InstrumentedFiles.find(Filename);
486
42
  if (It != InstrumentedFiles.end()) {
487
21
    return It->second;
488
21
  }
489
21
490
21
  SmallString<256> RealPath;
491
21
  StringRef RealFilename;
492
21
493
21
  // Path can be
494
21
  // /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/*.h so for
495
21
  // such a case we must get the real_path.
496
21
  if (sys::fs::real_path(Filename, RealPath)) {
497
0
    // real_path can fail with path like "foo.c".
498
0
    RealFilename = Filename;
499
21
  } else {
500
21
    RealFilename = RealPath;
501
21
  }
502
21
503
21
  bool ShouldInstrument;
504
21
  if (FilterRe.empty()) {
505
9
    ShouldInstrument = !doesFilenameMatchARegex(RealFilename, ExcludeRe);
506
12
  } else if (ExcludeRe.empty()) {
507
6
    ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe);
508
6
  } else {
509
6
    ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe) &&
510
6
                       
!doesFilenameMatchARegex(RealFilename, ExcludeRe)2
;
511
6
  }
512
21
  InstrumentedFiles[Filename] = ShouldInstrument;
513
21
  return ShouldInstrument;
514
21
}
515
516
std::string GCOVProfiler::mangleName(const DICompileUnit *CU,
517
57
                                     GCovFileType OutputType) {
518
57
  bool Notes = OutputType == GCovFileType::GCNO;
519
57
520
57
  if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) {
521
53
    for (int i = 0, e = GCov->getNumOperands(); i != e; 
++i0
) {
522
53
      MDNode *N = GCov->getOperand(i);
523
53
      bool ThreeElement = N->getNumOperands() == 3;
524
53
      if (!ThreeElement && 
N->getNumOperands() != 232
)
525
0
        continue;
526
53
      if (dyn_cast<MDNode>(N->getOperand(ThreeElement ? 
221
:
132
)) != CU)
527
0
        continue;
528
53
529
53
      if (ThreeElement) {
530
21
        // These nodes have no mangling to apply, it's stored mangled in the
531
21
        // bitcode.
532
21
        MDString *NotesFile = dyn_cast<MDString>(N->getOperand(0));
533
21
        MDString *DataFile = dyn_cast<MDString>(N->getOperand(1));
534
21
        if (!NotesFile || !DataFile)
535
0
          continue;
536
21
        return Notes ? 
NotesFile->getString()10
:
DataFile->getString()11
;
537
21
      }
538
32
539
32
      MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0));
540
32
      if (!GCovFile)
541
0
        continue;
542
32
543
32
      SmallString<128> Filename = GCovFile->getString();
544
32
      sys::path::replace_extension(Filename, Notes ? 
"gcno"16
:
"gcda"16
);
545
32
      return Filename.str();
546
32
    }
547
53
  }
548
57
549
57
  SmallString<128> Filename = CU->getFilename();
550
4
  sys::path::replace_extension(Filename, Notes ? 
"gcno"0
: "gcda");
551
4
  StringRef FName = sys::path::filename(Filename);
552
4
  SmallString<128> CurPath;
553
4
  if (sys::fs::current_path(CurPath)) 
return FName0
;
554
4
  sys::path::append(CurPath, FName);
555
4
  return CurPath.str();
556
4
}
557
558
33
bool GCOVProfiler::runOnModule(Module &M, const TargetLibraryInfo &TLI) {
559
33
  this->M = &M;
560
33
  this->TLI = &TLI;
561
33
  Ctx = &M.getContext();
562
33
563
33
  AddFlushBeforeForkAndExec();
564
33
565
33
  FilterRe = createRegexesFromString(Options.Filter);
566
33
  ExcludeRe = createRegexesFromString(Options.Exclude);
567
33
568
33
  if (Options.EmitNotes) 
emitProfileNotes()28
;
569
33
  if (Options.EmitData) return emitProfileArcs();
570
0
  return false;
571
0
}
572
573
PreservedAnalyses GCOVProfilerPass::run(Module &M,
574
11
                                        ModuleAnalysisManager &AM) {
575
11
576
11
  GCOVProfiler Profiler(GCOVOpts);
577
11
578
11
  auto &TLI = AM.getResult<TargetLibraryAnalysis>(M);
579
11
  if (!Profiler.runOnModule(M, TLI))
580
1
    return PreservedAnalyses::all();
581
10
582
10
  return PreservedAnalyses::none();
583
10
}
584
585
106
static bool functionHasLines(Function &F) {
586
106
  // Check whether this function actually has any source lines. Not only
587
106
  // do these waste space, they also can crash gcov.
588
125
  for (auto &BB : F) {
589
183
    for (auto &I : BB) {
590
183
      // Debug intrinsic locations correspond to the location of the
591
183
      // declaration, not necessarily any statements or expressions.
592
183
      if (isa<DbgInfoIntrinsic>(&I)) 
continue6
;
593
177
594
177
      const DebugLoc &Loc = I.getDebugLoc();
595
177
      if (!Loc)
596
75
        continue;
597
102
598
102
      // Artificial lines such as calls to the global constructors.
599
102
      if (Loc.getLine() == 0) 
continue0
;
600
102
601
102
      return true;
602
102
    }
603
125
  }
604
106
  
return false4
;
605
106
}
606
607
76
static bool isUsingScopeBasedEH(Function &F) {
608
76
  if (!F.hasPersonalityFn()) return false;
609
0
610
0
  EHPersonality Personality = classifyEHPersonality(F.getPersonalityFn());
611
0
  return isScopedEHPersonality(Personality);
612
0
}
613
614
50
static bool shouldKeepInEntry(BasicBlock::iterator It) {
615
50
  if (isa<AllocaInst>(*It)) 
return true15
;
616
35
  if (isa<DbgInfoIntrinsic>(*It)) 
return true2
;
617
33
  if (auto *II = dyn_cast<IntrinsicInst>(It)) {
618
0
    if (II->getIntrinsicID() == llvm::Intrinsic::localescape) return true;
619
33
  }
620
33
621
33
  return false;
622
33
}
623
624
33
void GCOVProfiler::AddFlushBeforeForkAndExec() {
625
33
  SmallVector<Instruction *, 2> ForkAndExecs;
626
81
  for (auto &F : M->functions()) {
627
278
    for (auto &I : instructions(F)) {
628
278
      if (CallInst *CI = dyn_cast<CallInst>(&I)) {
629
46
        if (Function *Callee = CI->getCalledFunction()) {
630
46
          LibFunc LF;
631
46
          if (TLI->getLibFunc(*Callee, LF) &&
632
46
              
(0
LF == LibFunc_fork0
||
LF == LibFunc_execl0
||
633
0
               LF == LibFunc_execle || LF == LibFunc_execlp ||
634
0
               LF == LibFunc_execv || LF == LibFunc_execvp ||
635
0
               LF == LibFunc_execve || LF == LibFunc_execvpe ||
636
0
               LF == LibFunc_execvP)) {
637
0
            ForkAndExecs.push_back(&I);
638
0
          }
639
46
        }
640
46
      }
641
278
    }
642
81
  }
643
33
644
33
  // We need to split the block after the fork/exec call
645
33
  // because else the counters for the lines after will be
646
33
  // the same as before the call.
647
33
  for (auto I : ForkAndExecs) {
648
0
    IRBuilder<> Builder(I);
649
0
    FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {}, false);
650
0
    FunctionCallee GCOVFlush = M->getOrInsertFunction("__gcov_flush", FTy);
651
0
    Builder.CreateCall(GCOVFlush);
652
0
    I->getParent()->splitBasicBlock(I);
653
0
  }
654
33
}
655
656
28
void GCOVProfiler::emitProfileNotes() {
657
28
  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
658
28
  if (!CU_Nodes) 
return0
;
659
28
660
56
  
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); 28
i != e;
++i28
) {
661
28
    // Each compile unit gets its own .gcno file. This means that whether we run
662
28
    // this pass over the original .o's as they're produced, or run it after
663
28
    // LTO, we'll generate the same .gcno files.
664
28
665
28
    auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i));
666
28
667
28
    // Skip module skeleton (and module) CUs.
668
28
    if (CU->getDWOId())
669
2
      continue;
670
26
671
26
    std::error_code EC;
672
26
    raw_fd_ostream out(mangleName(CU, GCovFileType::GCNO), EC, sys::fs::F_None);
673
26
    if (EC) {
674
0
      Ctx->emitError(Twine("failed to open coverage notes file for writing: ") +
675
0
                     EC.message());
676
0
      continue;
677
0
    }
678
26
679
26
    std::string EdgeDestinations;
680
26
681
26
    unsigned FunctionIdent = 0;
682
70
    for (auto &F : M->functions()) {
683
70
      DISubprogram *SP = F.getSubprogram();
684
70
      if (!SP) 
continue22
;
685
48
      if (!functionHasLines(F) || 
!isFunctionInstrumented(F)46
)
686
15
        continue;
687
33
      // TODO: Functions using scope-based EH are currently not supported.
688
33
      if (isUsingScopeBasedEH(F)) 
continue0
;
689
33
690
33
      // gcov expects every function to start with an entry block that has a
691
33
      // single successor, so split the entry block to make sure of that.
692
33
      BasicBlock &EntryBlock = F.getEntryBlock();
693
33
      BasicBlock::iterator It = EntryBlock.begin();
694
50
      while (shouldKeepInEntry(It))
695
17
        ++It;
696
33
      EntryBlock.splitBasicBlock(It);
697
33
698
33
      Funcs.push_back(make_unique<GCOVFunction>(SP, &F, &out, FunctionIdent++,
699
33
                                                Options.UseCfgChecksum,
700
33
                                                Options.ExitBlockBeforeBody));
701
33
      GCOVFunction &Func = *Funcs.back();
702
33
703
33
      // Add the function line number to the lines of the entry block
704
33
      // to have a counter for the function definition.
705
33
      uint32_t Line = SP->getLine();
706
33
      auto Filename = getFilename(SP);
707
33
      Func.getBlock(&EntryBlock).getFile(Filename).addLine(Line);
708
33
709
90
      for (auto &BB : F) {
710
90
        GCOVBlock &Block = Func.getBlock(&BB);
711
90
        Instruction *TI = BB.getTerminator();
712
90
        if (int successors = TI->getNumSuccessors()) {
713
116
          for (int i = 0; i != successors; 
++i61
) {
714
61
            Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
715
61
          }
716
55
        } else 
if (35
isa<ReturnInst>(TI)35
) {
717
33
          Block.addEdge(Func.getReturnBlock());
718
33
        }
719
90
720
184
        for (auto &I : BB) {
721
184
          // Debug intrinsic locations correspond to the location of the
722
184
          // declaration, not necessarily any statements or expressions.
723
184
          if (isa<DbgInfoIntrinsic>(&I)) 
continue8
;
724
176
725
176
          const DebugLoc &Loc = I.getDebugLoc();
726
176
          if (!Loc)
727
29
            continue;
728
147
729
147
          // Artificial lines such as calls to the global constructors.
730
147
          if (Loc.getLine() == 0 || Loc.isImplicitCode())
731
0
            continue;
732
147
733
147
          if (Line == Loc.getLine()) 
continue70
;
734
77
          Line = Loc.getLine();
735
77
          if (SP != getDISubprogram(Loc.getScope()))
736
0
            continue;
737
77
738
77
          GCOVLines &Lines = Block.getFile(Filename);
739
77
          Lines.addLine(Loc.getLine());
740
77
        }
741
90
        Line = 0;
742
90
      }
743
33
      EdgeDestinations += Func.getEdgeDestinations();
744
33
    }
745
26
746
26
    FileChecksums.push_back(hash_value(EdgeDestinations));
747
26
    out.write("oncg", 4);
748
26
    out.write(ReversedVersion, 4);
749
26
    out.write(reinterpret_cast<char*>(&FileChecksums.back()), 4);
750
26
751
33
    for (auto &Func : Funcs) {
752
33
      Func->setCfgChecksum(FileChecksums.back());
753
33
      Func->writeOut();
754
33
    }
755
26
756
26
    out.write("\0\0\0\0\0\0\0\0", 8);  // EOF
757
26
    out.close();
758
26
  }
759
28
}
760
761
33
bool GCOVProfiler::emitProfileArcs() {
762
33
  NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
763
33
  if (!CU_Nodes) 
return false0
;
764
33
765
33
  bool Result = false;
766
66
  for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; 
++i33
) {
767
33
    SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP;
768
81
    for (auto &F : M->functions()) {
769
81
      DISubprogram *SP = F.getSubprogram();
770
81
      if (!SP) 
continue23
;
771
58
      if (!functionHasLines(F) || 
!isFunctionInstrumented(F)56
)
772
15
        continue;
773
43
      // TODO: Functions using scope-based EH are currently not supported.
774
43
      if (isUsingScopeBasedEH(F)) 
continue0
;
775
43
      if (!Result) 
Result = true30
;
776
43
777
43
      DenseMap<std::pair<BasicBlock *, BasicBlock *>, unsigned> EdgeToCounter;
778
43
      unsigned Edges = 0;
779
115
      for (auto &BB : F) {
780
115
        Instruction *TI = BB.getTerminator();
781
115
        if (isa<ReturnInst>(TI)) {
782
43
          EdgeToCounter[{&BB, nullptr}] = Edges++;
783
72
        } else {
784
86
          for (BasicBlock *Succ : successors(TI)) {
785
86
            EdgeToCounter[{&BB, Succ}] = Edges++;
786
86
          }
787
72
        }
788
115
      }
789
43
790
43
      ArrayType *CounterTy =
791
43
        ArrayType::get(Type::getInt64Ty(*Ctx), Edges);
792
43
      GlobalVariable *Counters =
793
43
        new GlobalVariable(*M, CounterTy, false,
794
43
                           GlobalValue::InternalLinkage,
795
43
                           Constant::getNullValue(CounterTy),
796
43
                           "__llvm_gcov_ctr");
797
43
      CountersBySP.push_back(std::make_pair(Counters, SP));
798
43
799
43
      // If a BB has several predecessors, use a PHINode to select
800
43
      // the correct counter.
801
115
      for (auto &BB : F) {
802
115
        const unsigned EdgeCount =
803
115
            std::distance(pred_begin(&BB), pred_end(&BB));
804
115
        if (EdgeCount) {
805
70
          // The phi node must be at the begin of the BB.
806
70
          IRBuilder<> BuilderForPhi(&*BB.begin());
807
70
          Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
808
70
          PHINode *Phi = BuilderForPhi.CreatePHI(Int64PtrTy, EdgeCount);
809
86
          for (BasicBlock *Pred : predecessors(&BB)) {
810
86
            auto It = EdgeToCounter.find({Pred, &BB});
811
86
            assert(It != EdgeToCounter.end());
812
86
            const unsigned Edge = It->second;
813
86
            Value *EdgeCounter = BuilderForPhi.CreateConstInBoundsGEP2_64(
814
86
                Counters->getValueType(), Counters, 0, Edge);
815
86
            Phi->addIncoming(EdgeCounter, Pred);
816
86
          }
817
70
818
70
          // Skip phis, landingpads.
819
70
          IRBuilder<> Builder(&*BB.getFirstInsertionPt());
820
70
          Value *Count = Builder.CreateLoad(Builder.getInt64Ty(), Phi);
821
70
          Count = Builder.CreateAdd(Count, Builder.getInt64(1));
822
70
          Builder.CreateStore(Count, Phi);
823
70
824
70
          Instruction *TI = BB.getTerminator();
825
70
          if (isa<ReturnInst>(TI)) {
826
36
            auto It = EdgeToCounter.find({&BB, nullptr});
827
36
            assert(It != EdgeToCounter.end());
828
36
            const unsigned Edge = It->second;
829
36
            Value *Counter = Builder.CreateConstInBoundsGEP2_64(
830
36
                Counters->getValueType(), Counters, 0, Edge);
831
36
            Value *Count = Builder.CreateLoad(Builder.getInt64Ty(), Counter);
832
36
            Count = Builder.CreateAdd(Count, Builder.getInt64(1));
833
36
            Builder.CreateStore(Count, Counter);
834
36
          }
835
70
        }
836
115
      }
837
43
    }
838
33
839
33
    Function *WriteoutF = insertCounterWriteout(CountersBySP);
840
33
    Function *FlushF = insertFlush(CountersBySP);
841
33
842
33
    // Create a small bit of code that registers the "__llvm_gcov_writeout" to
843
33
    // be executed at exit and the "__llvm_gcov_flush" function to be executed
844
33
    // when "__gcov_flush" is called.
845
33
    FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
846
33
    Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
847
33
                                   "__llvm_gcov_init", M);
848
33
    F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
849
33
    F->setLinkage(GlobalValue::InternalLinkage);
850
33
    F->addFnAttr(Attribute::NoInline);
851
33
    if (Options.NoRedZone)
852
3
      F->addFnAttr(Attribute::NoRedZone);
853
33
854
33
    BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
855
33
    IRBuilder<> Builder(BB);
856
33
857
33
    FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
858
33
    Type *Params[] = {
859
33
      PointerType::get(FTy, 0),
860
33
      PointerType::get(FTy, 0)
861
33
    };
862
33
    FTy = FunctionType::get(Builder.getVoidTy(), Params, false);
863
33
864
33
    // Initialize the environment and register the local writeout and flush
865
33
    // functions.
866
33
    FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy);
867
33
    Builder.CreateCall(GCOVInit, {WriteoutF, FlushF});
868
33
    Builder.CreateRetVoid();
869
33
870
33
    appendToGlobalCtors(*M, F, 0);
871
33
  }
872
33
873
33
  return Result;
874
33
}
875
876
33
FunctionCallee GCOVProfiler::getStartFileFunc() {
877
33
  Type *Args[] = {
878
33
    Type::getInt8PtrTy(*Ctx),  // const char *orig_filename
879
33
    Type::getInt8PtrTy(*Ctx),  // const char version[4]
880
33
    Type::getInt32Ty(*Ctx),    // uint32_t checksum
881
33
  };
882
33
  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
883
33
  AttributeList AL;
884
33
  if (auto AK = TLI->getExtAttrForI32Param(false))
885
0
    AL = AL.addParamAttribute(*Ctx, 2, AK);
886
33
  FunctionCallee Res = M->getOrInsertFunction("llvm_gcda_start_file", FTy, AL);
887
33
  return Res;
888
33
}
889
890
33
FunctionCallee GCOVProfiler::getEmitFunctionFunc() {
891
33
  Type *Args[] = {
892
33
    Type::getInt32Ty(*Ctx),    // uint32_t ident
893
33
    Type::getInt8PtrTy(*Ctx),  // const char *function_name
894
33
    Type::getInt32Ty(*Ctx),    // uint32_t func_checksum
895
33
    Type::getInt8Ty(*Ctx),     // uint8_t use_extra_checksum
896
33
    Type::getInt32Ty(*Ctx),    // uint32_t cfg_checksum
897
33
  };
898
33
  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
899
33
  AttributeList AL;
900
33
  if (auto AK = TLI->getExtAttrForI32Param(false)) {
901
0
    AL = AL.addParamAttribute(*Ctx, 0, AK);
902
0
    AL = AL.addParamAttribute(*Ctx, 2, AK);
903
0
    AL = AL.addParamAttribute(*Ctx, 3, AK);
904
0
    AL = AL.addParamAttribute(*Ctx, 4, AK);
905
0
  }
906
33
  return M->getOrInsertFunction("llvm_gcda_emit_function", FTy);
907
33
}
908
909
33
FunctionCallee GCOVProfiler::getEmitArcsFunc() {
910
33
  Type *Args[] = {
911
33
    Type::getInt32Ty(*Ctx),     // uint32_t num_counters
912
33
    Type::getInt64PtrTy(*Ctx),  // uint64_t *counters
913
33
  };
914
33
  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
915
33
  AttributeList AL;
916
33
  if (auto AK = TLI->getExtAttrForI32Param(false))
917
0
    AL = AL.addParamAttribute(*Ctx, 0, AK);
918
33
  return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy, AL);
919
33
}
920
921
33
FunctionCallee GCOVProfiler::getSummaryInfoFunc() {
922
33
  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
923
33
  return M->getOrInsertFunction("llvm_gcda_summary_info", FTy);
924
33
}
925
926
33
FunctionCallee GCOVProfiler::getEndFileFunc() {
927
33
  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
928
33
  return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
929
33
}
930
931
Function *GCOVProfiler::insertCounterWriteout(
932
33
    ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
933
33
  FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
934
33
  Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
935
33
  if (!WriteoutF)
936
33
    WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage,
937
33
                                 "__llvm_gcov_writeout", M);
938
33
  WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
939
33
  WriteoutF->addFnAttr(Attribute::NoInline);
940
33
  if (Options.NoRedZone)
941
3
    WriteoutF->addFnAttr(Attribute::NoRedZone);
942
33
943
33
  BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF);
944
33
  IRBuilder<> Builder(BB);
945
33
946
33
  FunctionCallee StartFile = getStartFileFunc();
947
33
  FunctionCallee EmitFunction = getEmitFunctionFunc();
948
33
  FunctionCallee EmitArcs = getEmitArcsFunc();
949
33
  FunctionCallee SummaryInfo = getSummaryInfoFunc();
950
33
  FunctionCallee EndFile = getEndFileFunc();
951
33
952
33
  NamedMDNode *CUNodes = M->getNamedMetadata("llvm.dbg.cu");
953
33
  if (!CUNodes) {
954
0
    Builder.CreateRetVoid();
955
0
    return WriteoutF;
956
0
  }
957
33
958
33
  // Collect the relevant data into a large constant data structure that we can
959
33
  // walk to write out everything.
960
33
  StructType *StartFileCallArgsTy = StructType::create(
961
33
      {Builder.getInt8PtrTy(), Builder.getInt8PtrTy(), Builder.getInt32Ty()});
962
33
  StructType *EmitFunctionCallArgsTy = StructType::create(
963
33
      {Builder.getInt32Ty(), Builder.getInt8PtrTy(), Builder.getInt32Ty(),
964
33
       Builder.getInt8Ty(), Builder.getInt32Ty()});
965
33
  StructType *EmitArcsCallArgsTy = StructType::create(
966
33
      {Builder.getInt32Ty(), Builder.getInt64Ty()->getPointerTo()});
967
33
  StructType *FileInfoTy =
968
33
      StructType::create({StartFileCallArgsTy, Builder.getInt32Ty(),
969
33
                          EmitFunctionCallArgsTy->getPointerTo(),
970
33
                          EmitArcsCallArgsTy->getPointerTo()});
971
33
972
33
  Constant *Zero32 = Builder.getInt32(0);
973
33
  // Build an explicit array of two zeros for use in ConstantExpr GEP building.
974
33
  Constant *TwoZero32s[] = {Zero32, Zero32};
975
33
976
33
  SmallVector<Constant *, 8> FileInfos;
977
33
  for (int i : llvm::seq<int>(0, CUNodes->getNumOperands())) {
978
33
    auto *CU = cast<DICompileUnit>(CUNodes->getOperand(i));
979
33
980
33
    // Skip module skeleton (and module) CUs.
981
33
    if (CU->getDWOId())
982
2
      continue;
983
31
984
31
    std::string FilenameGcda = mangleName(CU, GCovFileType::GCDA);
985
31
    uint32_t CfgChecksum = FileChecksums.empty() ? 
05
:
FileChecksums[i]26
;
986
31
    auto *StartFileCallArgs = ConstantStruct::get(
987
31
        StartFileCallArgsTy, {Builder.CreateGlobalStringPtr(FilenameGcda),
988
31
                              Builder.CreateGlobalStringPtr(ReversedVersion),
989
31
                              Builder.getInt32(CfgChecksum)});
990
31
991
31
    SmallVector<Constant *, 8> EmitFunctionCallArgsArray;
992
31
    SmallVector<Constant *, 8> EmitArcsCallArgsArray;
993
43
    for (int j : llvm::seq<int>(0, CountersBySP.size())) {
994
43
      auto *SP = cast_or_null<DISubprogram>(CountersBySP[j].second);
995
43
      uint32_t FuncChecksum = Funcs.empty() ? 
010
:
Funcs[j]->getFuncChecksum()33
;
996
43
      EmitFunctionCallArgsArray.push_back(ConstantStruct::get(
997
43
          EmitFunctionCallArgsTy,
998
43
          {Builder.getInt32(j),
999
43
           Options.FunctionNamesInData
1000
43
               ? 
Builder.CreateGlobalStringPtr(getFunctionName(SP))41
1001
43
               : 
Constant::getNullValue(Builder.getInt8PtrTy())2
,
1002
43
           Builder.getInt32(FuncChecksum),
1003
43
           Builder.getInt8(Options.UseCfgChecksum),
1004
43
           Builder.getInt32(CfgChecksum)}));
1005
43
1006
43
      GlobalVariable *GV = CountersBySP[j].first;
1007
43
      unsigned Arcs = cast<ArrayType>(GV->getValueType())->getNumElements();
1008
43
      EmitArcsCallArgsArray.push_back(ConstantStruct::get(
1009
43
          EmitArcsCallArgsTy,
1010
43
          {Builder.getInt32(Arcs), ConstantExpr::getInBoundsGetElementPtr(
1011
43
                                       GV->getValueType(), GV, TwoZero32s)}));
1012
43
    }
1013
31
    // Create global arrays for the two emit calls.
1014
31
    int CountersSize = CountersBySP.size();
1015
31
    assert(CountersSize == (int)EmitFunctionCallArgsArray.size() &&
1016
31
           "Mismatched array size!");
1017
31
    assert(CountersSize == (int)EmitArcsCallArgsArray.size() &&
1018
31
           "Mismatched array size!");
1019
31
    auto *EmitFunctionCallArgsArrayTy =
1020
31
        ArrayType::get(EmitFunctionCallArgsTy, CountersSize);
1021
31
    auto *EmitFunctionCallArgsArrayGV = new GlobalVariable(
1022
31
        *M, EmitFunctionCallArgsArrayTy, /*isConstant*/ true,
1023
31
        GlobalValue::InternalLinkage,
1024
31
        ConstantArray::get(EmitFunctionCallArgsArrayTy,
1025
31
                           EmitFunctionCallArgsArray),
1026
31
        Twine("__llvm_internal_gcov_emit_function_args.") + Twine(i));
1027
31
    auto *EmitArcsCallArgsArrayTy =
1028
31
        ArrayType::get(EmitArcsCallArgsTy, CountersSize);
1029
31
    EmitFunctionCallArgsArrayGV->setUnnamedAddr(
1030
31
        GlobalValue::UnnamedAddr::Global);
1031
31
    auto *EmitArcsCallArgsArrayGV = new GlobalVariable(
1032
31
        *M, EmitArcsCallArgsArrayTy, /*isConstant*/ true,
1033
31
        GlobalValue::InternalLinkage,
1034
31
        ConstantArray::get(EmitArcsCallArgsArrayTy, EmitArcsCallArgsArray),
1035
31
        Twine("__llvm_internal_gcov_emit_arcs_args.") + Twine(i));
1036
31
    EmitArcsCallArgsArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1037
31
1038
31
    FileInfos.push_back(ConstantStruct::get(
1039
31
        FileInfoTy,
1040
31
        {StartFileCallArgs, Builder.getInt32(CountersSize),
1041
31
         ConstantExpr::getInBoundsGetElementPtr(EmitFunctionCallArgsArrayTy,
1042
31
                                                EmitFunctionCallArgsArrayGV,
1043
31
                                                TwoZero32s),
1044
31
         ConstantExpr::getInBoundsGetElementPtr(
1045
31
             EmitArcsCallArgsArrayTy, EmitArcsCallArgsArrayGV, TwoZero32s)}));
1046
31
  }
1047
33
1048
33
  // If we didn't find anything to actually emit, bail on out.
1049
33
  if (FileInfos.empty()) {
1050
2
    Builder.CreateRetVoid();
1051
2
    return WriteoutF;
1052
2
  }
1053
31
1054
31
  // To simplify code, we cap the number of file infos we write out to fit
1055
31
  // easily in a 32-bit signed integer. This gives consistent behavior between
1056
31
  // 32-bit and 64-bit systems without requiring (potentially very slow) 64-bit
1057
31
  // operations on 32-bit systems. It also seems unreasonable to try to handle
1058
31
  // more than 2 billion files.
1059
31
  if ((int64_t)FileInfos.size() > (int64_t)INT_MAX)
1060
31
    
FileInfos.resize(INT_MAX)0
;
1061
31
1062
31
  // Create a global for the entire data structure so we can walk it more
1063
31
  // easily.
1064
31
  auto *FileInfoArrayTy = ArrayType::get(FileInfoTy, FileInfos.size());
1065
31
  auto *FileInfoArrayGV = new GlobalVariable(
1066
31
      *M, FileInfoArrayTy, /*isConstant*/ true, GlobalValue::InternalLinkage,
1067
31
      ConstantArray::get(FileInfoArrayTy, FileInfos),
1068
31
      "__llvm_internal_gcov_emit_file_info");
1069
31
  FileInfoArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1070
31
1071
31
  // Create the CFG for walking this data structure.
1072
31
  auto *FileLoopHeader =
1073
31
      BasicBlock::Create(*Ctx, "file.loop.header", WriteoutF);
1074
31
  auto *CounterLoopHeader =
1075
31
      BasicBlock::Create(*Ctx, "counter.loop.header", WriteoutF);
1076
31
  auto *FileLoopLatch = BasicBlock::Create(*Ctx, "file.loop.latch", WriteoutF);
1077
31
  auto *ExitBB = BasicBlock::Create(*Ctx, "exit", WriteoutF);
1078
31
1079
31
  // We always have at least one file, so just branch to the header.
1080
31
  Builder.CreateBr(FileLoopHeader);
1081
31
1082
31
  // The index into the files structure is our loop induction variable.
1083
31
  Builder.SetInsertPoint(FileLoopHeader);
1084
31
  PHINode *IV =
1085
31
      Builder.CreatePHI(Builder.getInt32Ty(), /*NumReservedValues*/ 2);
1086
31
  IV->addIncoming(Builder.getInt32(0), BB);
1087
31
  auto *FileInfoPtr = Builder.CreateInBoundsGEP(
1088
31
      FileInfoArrayTy, FileInfoArrayGV, {Builder.getInt32(0), IV});
1089
31
  auto *StartFileCallArgsPtr =
1090
31
      Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 0);
1091
31
  auto *StartFileCall = Builder.CreateCall(
1092
31
      StartFile,
1093
31
      {Builder.CreateLoad(StartFileCallArgsTy->getElementType(0),
1094
31
                          Builder.CreateStructGEP(StartFileCallArgsTy,
1095
31
                                                  StartFileCallArgsPtr, 0)),
1096
31
       Builder.CreateLoad(StartFileCallArgsTy->getElementType(1),
1097
31
                          Builder.CreateStructGEP(StartFileCallArgsTy,
1098
31
                                                  StartFileCallArgsPtr, 1)),
1099
31
       Builder.CreateLoad(StartFileCallArgsTy->getElementType(2),
1100
31
                          Builder.CreateStructGEP(StartFileCallArgsTy,
1101
31
                                                  StartFileCallArgsPtr, 2))});
1102
31
  if (auto AK = TLI->getExtAttrForI32Param(false))
1103
0
    StartFileCall->addParamAttr(2, AK);
1104
31
  auto *NumCounters =
1105
31
      Builder.CreateLoad(FileInfoTy->getElementType(1),
1106
31
                         Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 1));
1107
31
  auto *EmitFunctionCallArgsArray =
1108
31
      Builder.CreateLoad(FileInfoTy->getElementType(2),
1109
31
                         Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 2));
1110
31
  auto *EmitArcsCallArgsArray =
1111
31
      Builder.CreateLoad(FileInfoTy->getElementType(3),
1112
31
                         Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 3));
1113
31
  auto *EnterCounterLoopCond =
1114
31
      Builder.CreateICmpSLT(Builder.getInt32(0), NumCounters);
1115
31
  Builder.CreateCondBr(EnterCounterLoopCond, CounterLoopHeader, FileLoopLatch);
1116
31
1117
31
  Builder.SetInsertPoint(CounterLoopHeader);
1118
31
  auto *JV = Builder.CreatePHI(Builder.getInt32Ty(), /*NumReservedValues*/ 2);
1119
31
  JV->addIncoming(Builder.getInt32(0), FileLoopHeader);
1120
31
  auto *EmitFunctionCallArgsPtr = Builder.CreateInBoundsGEP(
1121
31
      EmitFunctionCallArgsTy, EmitFunctionCallArgsArray, JV);
1122
31
  auto *EmitFunctionCall = Builder.CreateCall(
1123
31
      EmitFunction,
1124
31
      {Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(0),
1125
31
                          Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1126
31
                                                  EmitFunctionCallArgsPtr, 0)),
1127
31
       Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(1),
1128
31
                          Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1129
31
                                                  EmitFunctionCallArgsPtr, 1)),
1130
31
       Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(2),
1131
31
                          Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1132
31
                                                  EmitFunctionCallArgsPtr, 2)),
1133
31
       Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(3),
1134
31
                          Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1135
31
                                                  EmitFunctionCallArgsPtr, 3)),
1136
31
       Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(4),
1137
31
                          Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1138
31
                                                  EmitFunctionCallArgsPtr,
1139
31
                                                  4))});
1140
31
  if (auto AK = TLI->getExtAttrForI32Param(false)) {
1141
0
    EmitFunctionCall->addParamAttr(0, AK);
1142
0
    EmitFunctionCall->addParamAttr(2, AK);
1143
0
    EmitFunctionCall->addParamAttr(3, AK);
1144
0
    EmitFunctionCall->addParamAttr(4, AK);
1145
0
  }
1146
31
  auto *EmitArcsCallArgsPtr =
1147
31
      Builder.CreateInBoundsGEP(EmitArcsCallArgsTy, EmitArcsCallArgsArray, JV);
1148
31
  auto *EmitArcsCall = Builder.CreateCall(
1149
31
      EmitArcs,
1150
31
      {Builder.CreateLoad(
1151
31
           EmitArcsCallArgsTy->getElementType(0),
1152
31
           Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 0)),
1153
31
       Builder.CreateLoad(EmitArcsCallArgsTy->getElementType(1),
1154
31
                          Builder.CreateStructGEP(EmitArcsCallArgsTy,
1155
31
                                                  EmitArcsCallArgsPtr, 1))});
1156
31
  if (auto AK = TLI->getExtAttrForI32Param(false))
1157
0
    EmitArcsCall->addParamAttr(0, AK);
1158
31
  auto *NextJV = Builder.CreateAdd(JV, Builder.getInt32(1));
1159
31
  auto *CounterLoopCond = Builder.CreateICmpSLT(NextJV, NumCounters);
1160
31
  Builder.CreateCondBr(CounterLoopCond, CounterLoopHeader, FileLoopLatch);
1161
31
  JV->addIncoming(NextJV, CounterLoopHeader);
1162
31
1163
31
  Builder.SetInsertPoint(FileLoopLatch);
1164
31
  Builder.CreateCall(SummaryInfo, {});
1165
31
  Builder.CreateCall(EndFile, {});
1166
31
  auto *NextIV = Builder.CreateAdd(IV, Builder.getInt32(1));
1167
31
  auto *FileLoopCond =
1168
31
      Builder.CreateICmpSLT(NextIV, Builder.getInt32(FileInfos.size()));
1169
31
  Builder.CreateCondBr(FileLoopCond, FileLoopHeader, ExitBB);
1170
31
  IV->addIncoming(NextIV, FileLoopLatch);
1171
31
1172
31
  Builder.SetInsertPoint(ExitBB);
1173
31
  Builder.CreateRetVoid();
1174
31
1175
31
  return WriteoutF;
1176
31
}
1177
1178
Function *GCOVProfiler::
1179
33
insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
1180
33
  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
1181
33
  Function *FlushF = M->getFunction("__llvm_gcov_flush");
1182
33
  if (!FlushF)
1183
33
    FlushF = Function::Create(FTy, GlobalValue::InternalLinkage,
1184
33
                              "__llvm_gcov_flush", M);
1185
0
  else
1186
0
    FlushF->setLinkage(GlobalValue::InternalLinkage);
1187
33
  FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1188
33
  FlushF->addFnAttr(Attribute::NoInline);
1189
33
  if (Options.NoRedZone)
1190
3
    FlushF->addFnAttr(Attribute::NoRedZone);
1191
33
1192
33
  BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF);
1193
33
1194
33
  // Write out the current counters.
1195
33
  Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
1196
33
  assert(WriteoutF && "Need to create the writeout function first!");
1197
33
1198
33
  IRBuilder<> Builder(Entry);
1199
33
  Builder.CreateCall(WriteoutF, {});
1200
33
1201
33
  // Zero out the counters.
1202
43
  for (const auto &I : CountersBySP) {
1203
43
    GlobalVariable *GV = I.first;
1204
43
    Constant *Null = Constant::getNullValue(GV->getValueType());
1205
43
    Builder.CreateStore(Null, GV);
1206
43
  }
1207
33
1208
33
  Type *RetTy = FlushF->getReturnType();
1209
33
  if (RetTy == Type::getVoidTy(*Ctx))
1210
33
    Builder.CreateRetVoid();
1211
0
  else if (RetTy->isIntegerTy())
1212
0
    // Used if __llvm_gcov_flush was implicitly declared.
1213
0
    Builder.CreateRet(ConstantInt::get(RetTy, 0));
1214
0
  else
1215
0
    report_fatal_error("invalid return type for __llvm_gcov_flush");
1216
33
1217
33
  return FlushF;
1218
33
}