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