LLVM 24.0.0git
GCOVProfiling.cpp
Go to the documentation of this file.
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
17#include "llvm/ADT/Hashing.h"
18#include "llvm/ADT/MapVector.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/Sequence.h"
21#include "llvm/ADT/StringMap.h"
25#include "llvm/IR/DebugInfo.h"
26#include "llvm/IR/DebugLoc.h"
28#include "llvm/IR/IRBuilder.h"
31#include "llvm/IR/Module.h"
33#include "llvm/Support/CRC.h"
34#include "llvm/Support/Debug.h"
36#include "llvm/Support/Path.h"
37#include "llvm/Support/Regex.h"
44#include <algorithm>
45#include <memory>
46#include <string>
47#include <utility>
48
49using namespace llvm;
51
52#define DEBUG_TYPE "insert-gcov-profiling"
53
54enum : uint32_t {
56
57 GCOV_TAG_FUNCTION = 0x01000000,
58 GCOV_TAG_BLOCKS = 0x01410000,
59 GCOV_TAG_ARCS = 0x01430000,
60 GCOV_TAG_LINES = 0x01450000,
61};
62
63// Returns the number of words which will be used to represent this string.
64static unsigned wordsOfString(StringRef s) {
65 // Length + NUL-terminated string + 0~3 padding NULs.
66 return (s.size() / 4) + 2;
67}
68
69static GCOVOptions getDefaultOptions(const InstrumentationOptions &Opts) {
71 Options.EmitNotes = true;
72 Options.UseAbsolutePathsInNotes = false;
73 Options.EmitData = true;
74 Options.NoRedZone = false;
75 Options.Atomic = Opts.gcov_atomic_counter;
76
77 if (Opts.default_gcov_version.size() != 4) {
78 reportFatalUsageError(Twine("Invalid -default-gcov-version: ") +
79 Opts.default_gcov_version);
80 }
81 memcpy(Options.Version, Opts.default_gcov_version.data(), 4);
82 return Options;
83}
84
85namespace {
86class GCOVFunction;
87
88class GCOVProfiler {
89public:
90 GCOVProfiler(const GCOVOptions &Opts, vfs::FileSystem &VFS)
91 : Options(Opts), VFS(VFS) {}
92 bool
93 runOnModule(Module &M, function_ref<BlockFrequencyInfo *(Function &F)> GetBFI,
94 function_ref<BranchProbabilityInfo *(Function &F)> GetBPI,
95 std::function<const TargetLibraryInfo &(Function &F)> GetTLI);
96
97 void write(uint32_t i) {
98 char Bytes[4];
99 endian::write32(Bytes, i, Endian);
100 os->write(Bytes, 4);
101 }
102 void writeString(StringRef s) {
103 write(wordsOfString(s) - 1);
104 os->write(s.data(), s.size());
105 os->write_zeros(4 - s.size() % 4);
106 }
107 void writeBytes(const char *Bytes, int Size) { os->write(Bytes, Size); }
108 SmallString<128> getFilename(const DIScope *SP);
109
110private:
111 // Create the .gcno files for the Module based on DebugInfo.
112 bool
113 emitProfileNotes(NamedMDNode *CUNode, bool HasExecOrFork,
114 function_ref<BlockFrequencyInfo *(Function &F)> GetBFI,
115 function_ref<BranchProbabilityInfo *(Function &F)> GetBPI,
116 function_ref<const TargetLibraryInfo &(Function &F)> GetTLI);
117
118 Function *createInternalFunction(FunctionType *FTy, StringRef Name,
119 StringRef MangledType = "");
120
121 void emitGlobalConstructor(
122 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP);
123 void emitModuleInitFunctionPtrs(
124 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP);
125
126 bool isFunctionInstrumented(const Function &F);
127 std::vector<Regex> createRegexesFromString(StringRef RegexesStr);
128 static bool doesFilenameMatchARegex(StringRef Filename,
129 std::vector<Regex> &Regexes);
130
131 // Get pointers to the functions in the runtime library.
132 FunctionCallee getStartFileFunc(const TargetLibraryInfo *TLI);
133 FunctionCallee getEmitFunctionFunc(const TargetLibraryInfo *TLI);
134 FunctionCallee getEmitArcsFunc(const TargetLibraryInfo *TLI);
135 FunctionCallee getSummaryInfoFunc();
136 FunctionCallee getEndFileFunc();
137
138 // Add the function to write out all our counters to the global destructor
139 // list.
140 Function *
141 insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
142 Function *insertReset(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
143
144 bool AddFlushBeforeForkAndExec();
145
146 enum class GCovFileType { GCNO, GCDA };
147 std::string mangleName(const DICompileUnit *CU, GCovFileType FileType);
148
149 GCOVOptions Options;
150 llvm::endianness Endian;
151 raw_ostream *os;
152 int Version = 0;
153
154 // Checksum, produced by hash of EdgeDestinations
155 SmallVector<uint32_t, 4> FileChecksums;
156
157 Module *M = nullptr;
158 std::function<const TargetLibraryInfo &(Function &F)> GetTLI;
159 LLVMContext *Ctx = nullptr;
161 std::vector<Regex> FilterRe;
162 std::vector<Regex> ExcludeRe;
163 DenseSet<const BasicBlock *> ExecBlocks;
164 StringMap<bool> InstrumentedFiles;
165 vfs::FileSystem &VFS;
166};
167
168struct BBInfo {
169 BBInfo *Group;
170 uint32_t Index;
171 uint32_t Rank = 0;
172
173 BBInfo(unsigned Index) : Group(this), Index(Index) {}
174 std::string infoString() const {
175 return (Twine("Index=") + Twine(Index)).str();
176 }
177};
178
179struct Edge {
180 // This class implements the CFG edges. Note the CFG can be a multi-graph.
181 // So there might be multiple edges with same SrcBB and DestBB.
182 const BasicBlock *SrcBB;
183 const BasicBlock *DestBB;
184 uint64_t Weight;
185 BasicBlock *Place = nullptr;
186 uint32_t SrcNumber, DstNumber;
187 bool InMST = false;
188 bool Removed = false;
189 bool IsCritical = false;
190
191 Edge(const BasicBlock *Src, const BasicBlock *Dest, uint64_t W = 1)
192 : SrcBB(Src), DestBB(Dest), Weight(W) {}
193
194 // Return the information string of an edge.
195 std::string infoString() const {
196 return (Twine(Removed ? "-" : " ") + (InMST ? " " : "*") +
197 (IsCritical ? "c" : " ") + " W=" + Twine(Weight))
198 .str();
199 }
200};
201}
202
204 if (!SP->getLinkageName().empty())
205 return SP->getLinkageName();
206 return SP->getName();
207}
208
209/// Extract a filename for a DIScope.
210///
211/// Unless -fprofile-abs-path has been passed, prefer relative paths in the
212/// coverage notes. Clang also may split up absolute paths into a directory and
213/// filename component. When the relative path doesn't exist, reconstruct the
214/// absolute path.
215SmallString<128> GCOVProfiler::getFilename(const DIScope *SP) {
216 SmallString<128> Path;
217 StringRef RelPath = SP->getFilename();
218 if (VFS.exists(RelPath)) {
219 Path = RelPath;
220 if (Options.UseAbsolutePathsInNotes) {
221 VFS.makeAbsolute(Path);
222 sys::path::remove_dots(Path, true);
223 }
224 } else {
225 sys::path::append(Path, SP->getDirectory(), SP->getFilename());
226 }
227 return Path;
228}
229
230namespace {
231 class GCOVRecord {
232 protected:
233 GCOVProfiler *P;
234
235 GCOVRecord(GCOVProfiler *P) : P(P) {}
236
237 void write(uint32_t i) { P->write(i); }
238 void writeString(StringRef s) { P->writeString(s); }
239 void writeBytes(const char *Bytes, int Size) { P->writeBytes(Bytes, Size); }
240 };
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 StringRef getFilename() { return Filename; }
251
252 void addLine(uint32_t Line) {
253 assert(Line != 0 && "Line zero is not a valid real line number.");
254 Lines.push_back(Line);
255 }
256
257 uint32_t length() const {
258 return 1 + wordsOfString(Filename) + Lines.size();
259 }
260
261 void writeOut() {
262 write(0);
264 for (uint32_t L : Lines)
265 write(L);
266 }
267
268 GCOVLines(GCOVProfiler *P, StringRef F)
269 : GCOVRecord(P), Filename(std::string(F)) {}
270
271 private:
272 std::string Filename;
273 SmallVector<uint32_t, 32> Lines;
274 };
275
276
277 // Represent a basic block in GCOV. Each block has a unique number in the
278 // function, number of lines belonging to each block, and a set of edges to
279 // other blocks.
280 class GCOVBlock : public GCOVRecord {
281 public:
282 GCOVLines &getFile(StringRef Filename) {
283 if (Lines.empty() || Lines.back().getFilename() != Filename)
284 Lines.emplace_back(P, Filename);
285 return Lines.back();
286 }
287
288 void addEdge(GCOVBlock &Successor, uint32_t Flags) {
289 OutEdges.emplace_back(&Successor, Flags);
290 }
291
292 void writeOut() {
293 uint32_t Len = 3;
294
295 for (auto &L : Lines)
296 Len += L.length();
297
299 write(Len);
300 write(Number);
301
302 for (auto &L : Lines)
303 L.writeOut();
304 write(0);
305 write(0);
306 }
307
308 GCOVBlock(const GCOVBlock &RHS) : GCOVRecord(RHS), Number(RHS.Number) {
309 // Only allow copy before edges and lines have been added. After that,
310 // there are inter-block pointers (eg: edges) that won't take kindly to
311 // blocks being copied or moved around.
312 assert(Lines.empty());
313 assert(OutEdges.empty());
314 }
315
316 uint32_t Number;
318
319 private:
320 friend class GCOVFunction;
321
322 GCOVBlock(GCOVProfiler *P, uint32_t Number)
323 : GCOVRecord(P), Number(Number) {}
324
326 };
327
328 // A function has a unique identifier, a checksum (we leave as zero) and a
329 // set of blocks and a map of edges between blocks. This is the only GCOV
330 // object users can construct, the blocks and lines will be rooted here.
331 class GCOVFunction : public GCOVRecord {
332 public:
333 GCOVFunction(GCOVProfiler *P, Function *F, const DISubprogram *SP,
334 unsigned EndLine, uint32_t Ident, int Version)
335 : GCOVRecord(P), SP(SP), EndLine(EndLine), Ident(Ident),
336 Version(Version), EntryBlock(P, 0), ReturnBlock(P, 1) {
337 LLVM_DEBUG(dbgs() << "Function: " << getFunctionName(SP) << "\n");
338 uint32_t i = 2;
339 for (BasicBlock &BB : *F)
340 Blocks.insert(std::make_pair(&BB, GCOVBlock(P, i++)));
341
342 std::string FunctionNameAndLine;
343 raw_string_ostream FNLOS(FunctionNameAndLine);
344 FNLOS << getFunctionName(SP) << SP->getLine();
345 FuncChecksum = hash_value(FunctionNameAndLine);
346 }
347
348 GCOVBlock &getBlock(const BasicBlock *BB) {
349 return Blocks.find(const_cast<BasicBlock *>(BB))->second;
350 }
351
352 GCOVBlock &getEntryBlock() { return EntryBlock; }
353 GCOVBlock &getReturnBlock() {
354 return ReturnBlock;
355 }
356
357 uint32_t getFuncChecksum() const {
358 return FuncChecksum;
359 }
360
361 void writeOut(uint32_t CfgChecksum) {
363 SmallString<128> Filename = P->getFilename(SP);
364 uint32_t BlockLen = 3 + wordsOfString(getFunctionName(SP));
365 BlockLen += 1 + wordsOfString(Filename) + 4;
366
367 write(BlockLen);
368 write(Ident);
369 write(FuncChecksum);
370 write(CfgChecksum);
372
373 write(SP->isArtificial()); // artificial
375 write(SP->getLine()); // start_line
376 write(0); // start_column
377 // EndLine is the last line with !dbg. It is not the } line as in GCC,
378 // but good enough.
379 write(EndLine);
380 write(0); // end_column
381
382 // Emit count of blocks.
384 write(1);
385 write(Blocks.size() + 2);
386 LLVM_DEBUG(dbgs() << (Blocks.size() + 1) << " blocks\n");
387
388 // Emit edges between blocks.
389 const uint32_t Outgoing = EntryBlock.OutEdges.size();
390 if (Outgoing) {
392 write(Outgoing * 2 + 1);
393 write(EntryBlock.Number);
394 for (const auto &E : EntryBlock.OutEdges) {
395 write(E.first->Number);
396 write(E.second);
397 }
398 }
399 for (auto &It : Blocks) {
400 const GCOVBlock &Block = It.second;
401 if (Block.OutEdges.empty()) continue;
402
404 write(Block.OutEdges.size() * 2 + 1);
405 write(Block.Number);
406 for (const auto &E : Block.OutEdges) {
407 write(E.first->Number);
408 write(E.second);
409 }
410 }
411
412 // Emit lines for each block.
413 for (auto &It : Blocks)
414 It.second.writeOut();
415 }
416
417 public:
418 const DISubprogram *SP;
419 unsigned EndLine;
420 uint32_t Ident;
421 uint32_t FuncChecksum;
422 int Version;
423 MapVector<BasicBlock *, GCOVBlock> Blocks;
424 GCOVBlock EntryBlock;
425 GCOVBlock ReturnBlock;
426 };
427}
428
429// RegexesStr is a string containing differents regex separated by a semi-colon.
430// For example "foo\..*$;bar\..*$".
431std::vector<Regex> GCOVProfiler::createRegexesFromString(StringRef RegexesStr) {
432 std::vector<Regex> Regexes;
433 while (!RegexesStr.empty()) {
434 std::pair<StringRef, StringRef> HeadTail = RegexesStr.split(';');
435 if (!HeadTail.first.empty()) {
436 Regex Re(HeadTail.first);
437 std::string Err;
438 if (!Re.isValid(Err)) {
439 Ctx->emitError(Twine("Regex ") + HeadTail.first +
440 " is not valid: " + Err);
441 }
442 Regexes.emplace_back(std::move(Re));
443 }
444 RegexesStr = HeadTail.second;
445 }
446 return Regexes;
447}
448
449bool GCOVProfiler::doesFilenameMatchARegex(StringRef Filename,
450 std::vector<Regex> &Regexes) {
451 for (Regex &Re : Regexes)
452 if (Re.match(Filename))
453 return true;
454 return false;
455}
456
457bool GCOVProfiler::isFunctionInstrumented(const Function &F) {
458 if (FilterRe.empty() && ExcludeRe.empty()) {
459 return true;
460 }
461 SmallString<128> Filename = getFilename(F.getSubprogram());
462 auto It = InstrumentedFiles.find(Filename);
463 if (It != InstrumentedFiles.end()) {
464 return It->second;
465 }
466
467 SmallString<256> RealPath;
468 StringRef RealFilename;
469
470 // Path can be
471 // /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/*.h so for
472 // such a case we must get the real_path.
473 if (VFS.getRealPath(Filename, RealPath)) {
474 // real_path can fail with path like "foo.c".
475 RealFilename = Filename;
476 } else {
477 RealFilename = RealPath;
478 }
479
480 bool ShouldInstrument;
481 if (FilterRe.empty()) {
482 ShouldInstrument = !doesFilenameMatchARegex(RealFilename, ExcludeRe);
483 } else if (ExcludeRe.empty()) {
484 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe);
485 } else {
486 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe) &&
487 !doesFilenameMatchARegex(RealFilename, ExcludeRe);
488 }
489 InstrumentedFiles[Filename] = ShouldInstrument;
490 return ShouldInstrument;
491}
492
493std::string GCOVProfiler::mangleName(const DICompileUnit *CU,
494 GCovFileType OutputType) {
495 bool Notes = OutputType == GCovFileType::GCNO;
496
497 if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) {
498 for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) {
499 MDNode *N = GCov->getOperand(i);
500 bool ThreeElement = N->getNumOperands() == 3;
501 if (!ThreeElement && N->getNumOperands() != 2)
502 continue;
503 if (dyn_cast<MDNode>(N->getOperand(ThreeElement ? 2 : 1)) != CU)
504 continue;
505
506 if (ThreeElement) {
507 // These nodes have no mangling to apply, it's stored mangled in the
508 // bitcode.
509 MDString *NotesFile = dyn_cast<MDString>(N->getOperand(0));
510 MDString *DataFile = dyn_cast<MDString>(N->getOperand(1));
511 if (!NotesFile || !DataFile)
512 continue;
513 return std::string(Notes ? NotesFile->getString()
514 : DataFile->getString());
515 }
516
517 MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0));
518 if (!GCovFile)
519 continue;
520
521 SmallString<128> Filename = GCovFile->getString();
522 sys::path::replace_extension(Filename, Notes ? "gcno" : "gcda");
523 return std::string(Filename);
524 }
525 }
526
527 SmallString<128> Filename = CU->getFilename();
528 sys::path::replace_extension(Filename, Notes ? "gcno" : "gcda");
529 StringRef FName = sys::path::filename(Filename);
530 ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory();
531 if (!CWD)
532 return std::string(FName);
533 SmallString<128> CurPath{*CWD};
534 sys::path::append(CurPath, FName);
535 return std::string(CurPath);
536}
537
538bool GCOVProfiler::runOnModule(
539 Module &M, function_ref<BlockFrequencyInfo *(Function &F)> GetBFI,
540 function_ref<BranchProbabilityInfo *(Function &F)> GetBPI,
541 std::function<const TargetLibraryInfo &(Function &F)> GetTLI) {
542 this->M = &M;
543 this->GetTLI = std::move(GetTLI);
544 Ctx = &M.getContext();
545
546 NamedMDNode *CUNode = M.getNamedMetadata("llvm.dbg.cu");
547 if (!CUNode || (!Options.EmitNotes && !Options.EmitData))
548 return false;
549
550 bool HasExecOrFork = AddFlushBeforeForkAndExec();
551
552 FilterRe = createRegexesFromString(Options.Filter);
553 ExcludeRe = createRegexesFromString(Options.Exclude);
554 emitProfileNotes(CUNode, HasExecOrFork, GetBFI, GetBPI, this->GetTLI);
555 return true;
556}
557
560
561 const InstrumentationOptions &Opts = getInstrumentationOptions(M);
562 GCOVProfiler Profiler(GCOVOpts ? *GCOVOpts : getDefaultOptions(Opts), *VFS);
565
566 auto GetBFI = [&FAM](Function &F) {
567 return &FAM.getResult<BlockFrequencyAnalysis>(F);
568 };
569 auto GetBPI = [&FAM](Function &F) {
570 return &FAM.getResult<BranchProbabilityAnalysis>(F);
571 };
572 auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & {
573 return FAM.getResult<TargetLibraryAnalysis>(F);
574 };
575
576 if (!Profiler.runOnModule(M, GetBFI, GetBPI, GetTLI))
577 return PreservedAnalyses::all();
578
580}
581
582static bool functionHasLines(const Function &F, unsigned &EndLine) {
583 // Check whether this function actually has any source lines. Not only
584 // do these waste space, they also can crash gcov.
585 EndLine = 0;
586 for (const auto &BB : F) {
587 for (const auto &I : BB) {
588 const DebugLoc &Loc = I.getDebugLoc();
589 if (!Loc)
590 continue;
591
592 // Artificial lines such as calls to the global constructors.
593 if (Loc.getLine() == 0) continue;
594 EndLine = std::max(EndLine, Loc.getLine());
595
596 return true;
597 }
598 }
599 return false;
600}
601
603 if (!F.hasPersonalityFn()) return false;
604
605 EHPersonality Personality = classifyEHPersonality(F.getPersonalityFn());
606 return isScopedEHPersonality(Personality);
607}
608
609bool GCOVProfiler::AddFlushBeforeForkAndExec() {
610 const TargetLibraryInfo *TLI = nullptr;
613 for (auto &F : M->functions()) {
614 TLI = TLI == nullptr ? &GetTLI(F) : TLI;
615 for (auto &I : instructions(F)) {
616 if (CallInst *CI = dyn_cast<CallInst>(&I)) {
617 if (Function *Callee = CI->getCalledFunction()) {
618 LibFunc LF = TLI->getLibFunc(*Callee);
619 if (LF != NotLibFunc) {
620 if (LF == LibFunc_fork) {
621#if !defined(_WIN32)
622 Forks.push_back(CI);
623#endif
624 } else if (LF == LibFunc_execl || LF == LibFunc_execle ||
625 LF == LibFunc_execlp || LF == LibFunc_execv ||
626 LF == LibFunc_execvp || LF == LibFunc_execve ||
627 LF == LibFunc_execvpe || LF == LibFunc_execvP) {
628 Execs.push_back(CI);
629 }
630 }
631 }
632 }
633 }
634 }
635
636 for (auto *F : Forks) {
637 IRBuilder<> Builder(F);
638 BasicBlock *Parent = F->getParent();
639 auto NextInst = ++F->getIterator();
640
641 // We've a fork so just reset the counters in the child process
642 FunctionType *FTy = FunctionType::get(Builder.getInt32Ty(), {}, false);
643 FunctionCallee GCOVFork = M->getOrInsertFunction(
644 "__gcov_fork", FTy,
645 TLI->getAttrList(Ctx, {}, /*Signed=*/true, /*Ret=*/true));
646 F->setCalledFunction(GCOVFork);
647
648 // We split just after the fork to have a counter for the lines after
649 // Anyway there's a bug:
650 // void foo() { fork(); }
651 // void bar() { foo(); blah(); }
652 // then "blah();" will be called 2 times but showed as 1
653 // because "blah()" belongs to the same block as "foo();"
654 Parent->splitBasicBlock(NextInst);
655
656 // back() is a br instruction with a debug location
657 // equals to the one from NextAfterFork
658 // So to avoid to have two debug locs on two blocks just change it
659 DebugLoc Loc = F->getDebugLoc();
660 Parent->back().setDebugLoc(Loc);
661 }
662
663 for (auto *E : Execs) {
664 IRBuilder<> Builder(E);
665 BasicBlock *Parent = E->getParent();
666 auto NextInst = ++E->getIterator();
667
668 // Since the process is replaced by a new one we need to write out gcdas
669 // No need to reset the counters since they'll be lost after the exec**
670 FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {}, false);
671 FunctionCallee WriteoutF =
672 M->getOrInsertFunction("llvm_writeout_files", FTy);
673 Builder.CreateCall(WriteoutF);
674
675 DebugLoc Loc = E->getDebugLoc();
676 Builder.SetInsertPoint(&*NextInst);
677 // If the exec** fails we must reset the counters since they've been
678 // dumped
679 FunctionCallee ResetF = M->getOrInsertFunction("llvm_reset_counters", FTy);
680 Builder.CreateCall(ResetF)->setDebugLoc(Loc);
681 ExecBlocks.insert(Parent);
682 Parent->splitBasicBlock(NextInst);
683 Parent->back().setDebugLoc(Loc);
684 }
685
686 return !Forks.empty() || !Execs.empty();
687}
688
690 const DenseSet<const BasicBlock *> &ExecBlocks) {
691 if (E.InMST || E.Removed)
692 return nullptr;
693
694 BasicBlock *SrcBB = const_cast<BasicBlock *>(E.SrcBB);
695 BasicBlock *DestBB = const_cast<BasicBlock *>(E.DestBB);
696 // For a fake edge, instrument the real BB.
697 if (SrcBB == nullptr)
698 return DestBB;
699 if (DestBB == nullptr)
700 return SrcBB;
701
702 auto CanInstrument = [](BasicBlock *BB) -> BasicBlock * {
703 // There are basic blocks (such as catchswitch) cannot be instrumented.
704 // If the returned first insertion point is the end of BB, skip this BB.
705 if (BB->getFirstInsertionPt() == BB->end())
706 return nullptr;
707 return BB;
708 };
709
710 // Instrument the SrcBB if it has a single successor,
711 // otherwise, the DestBB if this is not a critical edge.
712 Instruction *TI = SrcBB->getTerminator();
713 if (TI->getNumSuccessors() <= 1 && !ExecBlocks.count(SrcBB))
714 return CanInstrument(SrcBB);
715 if (!E.IsCritical)
716 return CanInstrument(DestBB);
717
718 // Some IndirectBr critical edges cannot be split by the previous
719 // SplitIndirectBrCriticalEdges call. Bail out.
720 const unsigned SuccNum = GetSuccessorNumber(SrcBB, DestBB);
721 BasicBlock *InstrBB =
722 isa<IndirectBrInst>(TI) ? nullptr : SplitCriticalEdge(TI, SuccNum);
723 if (!InstrBB)
724 return nullptr;
725
726 MST.addEdge(SrcBB, InstrBB, 0);
727 MST.addEdge(InstrBB, DestBB, 0).InMST = true;
728 E.Removed = true;
729
730 return CanInstrument(InstrBB);
731}
732
733#ifndef NDEBUG
735 size_t ID = 0;
736 for (const auto &E : make_pointee_range(MST.allEdges())) {
737 GCOVBlock &Src = E.SrcBB ? GF.getBlock(E.SrcBB) : GF.getEntryBlock();
738 GCOVBlock &Dst = E.DestBB ? GF.getBlock(E.DestBB) : GF.getReturnBlock();
739 dbgs() << " Edge " << ID++ << ": " << Src.Number << "->" << Dst.Number
740 << E.infoString() << "\n";
741 }
742}
743#endif
744
745bool GCOVProfiler::emitProfileNotes(
746 NamedMDNode *CUNode, bool HasExecOrFork,
747 function_ref<BlockFrequencyInfo *(Function &F)> GetBFI,
748 function_ref<BranchProbabilityInfo *(Function &F)> GetBPI,
749 function_ref<const TargetLibraryInfo &(Function &F)> GetTLI) {
750 {
751 uint8_t c3 = Options.Version[0];
752 uint8_t c2 = Options.Version[1];
753 uint8_t c1 = Options.Version[2];
754 Version = c3 >= 'A' ? (c3 - 'A') * 100 + (c2 - '0') * 10 + c1 - '0'
755 : (c3 - '0') * 10 + c1 - '0';
756 }
757 // Emit .gcno files that are compatible with GCC 11.1.
758 if (Version < 111) {
759 Version = 111;
760 memcpy(Options.Version, "B11*", 4);
761 }
762
763 bool EmitGCDA = Options.EmitData;
764 for (unsigned i = 0, e = CUNode->getNumOperands(); i != e; ++i) {
765 // Each compile unit gets its own .gcno file. This means that whether we run
766 // this pass over the original .o's as they're produced, or run it after
767 // LTO, we'll generate the same .gcno files.
768
769 auto *CU = cast<DICompileUnit>(CUNode->getOperand(i));
770
771 // Skip module skeleton (and module) CUs.
772 if (CU->getDWOId())
773 continue;
774
775 std::vector<uint8_t> EdgeDestinations;
777
778 Endian = M->getDataLayout().isLittleEndian() ? llvm::endianness::little
780 unsigned FunctionIdent = 0;
781 for (auto &F : M->functions()) {
782 DISubprogram *SP = F.getSubprogram();
783 unsigned EndLine;
784 if (!SP) continue;
785 if (!functionHasLines(F, EndLine) || !isFunctionInstrumented(F))
786 continue;
787 // TODO: Functions using scope-based EH are currently not supported.
788 if (isUsingScopeBasedEH(F)) continue;
789 if (F.hasFnAttribute(llvm::Attribute::NoProfile))
790 continue;
791 if (F.hasFnAttribute(llvm::Attribute::SkipProfile))
792 continue;
793
794 // Add the function line number to the lines of the entry block
795 // to have a counter for the function definition.
796 uint32_t Line = SP->getLine();
797 auto Filename = getFilename(SP);
798
799 BranchProbabilityInfo *BPI = GetBPI(F);
800 BlockFrequencyInfo *BFI = GetBFI(F);
801
802 // Split indirectbr critical edges here before computing the MST rather
803 // than later in getInstrBB() to avoid invalidating it.
804 SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI,
805 BFI);
806
807 CFGMST<Edge, BBInfo> MST(F, /*InstrumentFuncEntry=*/false,
808 /*InstrumentLoopEntries=*/false, BPI, BFI);
809
810 // getInstrBB can split basic blocks and push elements to AllEdges.
811 for (size_t I : llvm::seq<size_t>(0, MST.numEdges())) {
812 auto &E = *MST.allEdges()[I];
813 // For now, disable spanning tree optimization when fork or exec* is
814 // used.
815 if (HasExecOrFork)
816 E.InMST = false;
817 E.Place = getInstrBB(MST, E, ExecBlocks);
818 }
819 // Basic blocks in F are finalized at this point.
820 BasicBlock &EntryBlock = F.getEntryBlock();
821 Funcs.push_back(std::make_unique<GCOVFunction>(this, &F, SP, EndLine,
822 FunctionIdent++, Version));
823 GCOVFunction &Func = *Funcs.back();
824
825 // Some non-tree edges are IndirectBr which cannot be split. Ignore them
826 // as well.
827 llvm::erase_if(MST.allEdges(), [](std::unique_ptr<Edge> &E) {
828 return E->Removed || (!E->InMST && !E->Place);
829 });
830 const size_t Measured =
831 std::stable_partition(
832 MST.allEdges().begin(), MST.allEdges().end(),
833 [](std::unique_ptr<Edge> &E) { return E->Place; }) -
834 MST.allEdges().begin();
835 for (size_t I : llvm::seq<size_t>(0, Measured)) {
836 Edge &E = *MST.allEdges()[I];
837 GCOVBlock &Src =
838 E.SrcBB ? Func.getBlock(E.SrcBB) : Func.getEntryBlock();
839 GCOVBlock &Dst =
840 E.DestBB ? Func.getBlock(E.DestBB) : Func.getReturnBlock();
841 E.SrcNumber = Src.Number;
842 E.DstNumber = Dst.Number;
843 }
844 std::stable_sort(
845 MST.allEdges().begin(), MST.allEdges().begin() + Measured,
846 [](const std::unique_ptr<Edge> &L, const std::unique_ptr<Edge> &R) {
847 return L->SrcNumber != R->SrcNumber ? L->SrcNumber < R->SrcNumber
848 : L->DstNumber < R->DstNumber;
849 });
850
851 for (const Edge &E : make_pointee_range(MST.allEdges())) {
852 GCOVBlock &Src =
853 E.SrcBB ? Func.getBlock(E.SrcBB) : Func.getEntryBlock();
854 GCOVBlock &Dst =
855 E.DestBB ? Func.getBlock(E.DestBB) : Func.getReturnBlock();
856 Src.addEdge(Dst, E.Place ? 0 : uint32_t(GCOV_ARC_ON_TREE));
857 }
858
859 // Artificial functions such as global initializers
860 if (!SP->isArtificial())
861 Func.getBlock(&EntryBlock).getFile(Filename).addLine(Line);
862
863 LLVM_DEBUG(dumpEdges(MST, Func));
864
865 for (auto &GB : Func.Blocks) {
866 const BasicBlock &BB = *GB.first;
867 auto &Block = GB.second;
868 for (auto Succ : Block.OutEdges) {
869 uint32_t Idx = Succ.first->Number;
870 do EdgeDestinations.push_back(Idx & 255);
871 while ((Idx >>= 8) > 0);
872 }
873
874 for (const auto &I : BB) {
875 const DebugLoc &Loc = I.getDebugLoc();
876 if (!Loc)
877 continue;
878
879 // Artificial lines such as calls to the global constructors.
880 if (Loc.getLine() == 0 || Loc.isImplicitCode())
881 continue;
882
883 if (Line == Loc.getLine()) continue;
884 Line = Loc.getLine();
885 MDNode *Scope = Loc.getScope();
886 if (SP != getDISubprogram(Scope))
887 continue;
888
889 GCOVLines &Lines = Block.getFile(getFilename(Loc->getScope()));
890 Lines.addLine(Loc.getLine());
891 }
892 Line = 0;
893 }
894 if (EmitGCDA) {
895 DISubprogram *SP = F.getSubprogram();
896 ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(*Ctx), Measured);
897 GlobalVariable *Counters = new GlobalVariable(
898 *M, CounterTy, false, GlobalValue::InternalLinkage,
899 Constant::getNullValue(CounterTy), "__llvm_gcov_ctr");
900 const llvm::Triple &Triple = M->getTargetTriple();
901 if (Triple.getObjectFormat() == llvm::Triple::XCOFF)
902 Counters->setSection("__llvm_gcov_ctr_section");
903 CountersBySP.emplace_back(Counters, SP);
904
905 for (size_t I : llvm::seq<size_t>(0, Measured)) {
906 const Edge &E = *MST.allEdges()[I];
907 IRBuilder<> Builder(E.Place->getFirstInsertionPt());
908 Value *V = Builder.CreateConstInBoundsGEP2_64(
909 Counters->getValueType(), Counters, 0, I);
910 // Disable sanitizers to decrease size bloat. We don't expect
911 // sanitizers to catch interesting issues.
912 Instruction *Inst;
913 if (Options.Atomic) {
914 Inst = Builder.CreateAtomicRMW(AtomicRMWInst::Add, V,
915 Builder.getInt64(1), MaybeAlign(),
916 AtomicOrdering::Monotonic);
917 } else {
918 LoadInst *OldCount =
919 Builder.CreateLoad(Builder.getInt64Ty(), V, "gcov_ctr");
920 OldCount->setNoSanitizeMetadata();
921 Value *NewCount = Builder.CreateAdd(OldCount, Builder.getInt64(1));
922 Inst = Builder.CreateStore(NewCount, V);
923 }
924 Inst->setNoSanitizeMetadata();
925 }
926 }
927 }
928
929 char Tmp[4];
930 JamCRC JC;
931 JC.update(EdgeDestinations);
932 uint32_t Stamp = JC.getCRC();
933 FileChecksums.push_back(Stamp);
934
935 if (Options.EmitNotes) {
936 std::error_code EC;
937 raw_fd_ostream out(mangleName(CU, GCovFileType::GCNO), EC,
939 if (EC) {
940 Ctx->emitError(
941 Twine("failed to open coverage notes file for writing: ") +
942 EC.message());
943 continue;
944 }
945 os = &out;
946 if (Endian == llvm::endianness::big) {
947 out.write("gcno", 4);
948 out.write(Options.Version, 4);
949 } else {
950 out.write("oncg", 4);
951 std::reverse_copy(Options.Version, Options.Version + 4, Tmp);
952 out.write(Tmp, 4);
953 }
954 write(Stamp);
955 writeString("."); // unuseful current_working_directory
956 write(0); // unuseful has_unexecuted_blocks
957
958 for (auto &Func : Funcs)
959 Func->writeOut(Stamp);
960
961 write(0);
962 write(0);
963 out.close();
964 }
965
966 if (EmitGCDA) {
967 const llvm::Triple &Triple = M->getTargetTriple();
968 if (Triple.getObjectFormat() == llvm::Triple::XCOFF)
969 emitModuleInitFunctionPtrs(CountersBySP);
970 else
971 emitGlobalConstructor(CountersBySP);
972 EmitGCDA = false;
973 }
974 }
975 return true;
976}
977
978Function *GCOVProfiler::createInternalFunction(FunctionType *FTy,
979 StringRef Name,
980 StringRef MangledType /*=""*/) {
982 FTy, GlobalValue::InternalLinkage, 0, Name, M);
983 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
984 F->addFnAttr(Attribute::NoUnwind);
985 if (Options.NoRedZone)
986 F->addFnAttr(Attribute::NoRedZone);
987 if (!MangledType.empty())
988 setKCFIType(*M, *F, MangledType);
989 return F;
990}
991
992void GCOVProfiler::emitGlobalConstructor(
993 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) {
994 Function *WriteoutF = insertCounterWriteout(CountersBySP);
995 Function *ResetF = insertReset(CountersBySP);
996
997 // Create a small bit of code that registers the "__llvm_gcov_writeout" to
998 // be executed at exit and the "__llvm_gcov_reset" function to be executed
999 // when "__gcov_flush" is called.
1000 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
1001 Function *F = createInternalFunction(FTy, "__llvm_gcov_init", "_ZTSFvvE");
1002 F->addFnAttr(Attribute::NoInline);
1003
1004 BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
1005 IRBuilder<> Builder(BB);
1006
1007 FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
1008 auto *PFTy = PointerType::get(*Ctx, 0);
1009 FTy = FunctionType::get(Builder.getVoidTy(), {PFTy, PFTy}, false);
1010
1011 // Initialize the environment and register the local writeout, flush and
1012 // reset functions.
1013 FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy);
1014 Builder.CreateCall(GCOVInit, {WriteoutF, ResetF});
1015 Builder.CreateRetVoid();
1016
1017 appendToGlobalCtors(*M, F, 0);
1018}
1019
1020void GCOVProfiler::emitModuleInitFunctionPtrs(
1021 SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) {
1022 Function *WriteoutF = insertCounterWriteout(CountersBySP);
1023 Function *ResetF = insertReset(CountersBySP);
1024
1025 // Instead of creating a function call and add it to the constructors list,
1026 // create a global variable in the __llvm_covinit section so the functions
1027 // can be registered by a constructor in the runtime.
1028
1029 auto &Ctx = M->getContext();
1030
1031 Type *InitFuncDataTy[] = {
1032#define COVINIT_FUNC(Type, LLVMType, Name, Init) LLVMType,
1034 };
1035
1036 auto STy = StructType::get(Ctx, ArrayRef(InitFuncDataTy));
1037
1038 Constant *InitFuncPtrs[] = {
1039#define COVINIT_FUNC(Type, LLVMType, Name, Init) Init,
1041 };
1042
1043 auto *CovInitGV =
1044 new GlobalVariable(*M, STy, false, GlobalValue::PrivateLinkage, nullptr,
1045 "__llvm_covinit_functions");
1046 CovInitGV->setInitializer(ConstantStruct::get(STy, InitFuncPtrs));
1047 CovInitGV->setVisibility(GlobalValue::VisibilityTypes::DefaultVisibility);
1048 CovInitGV->setSection(getInstrProfSectionName(
1049 IPSK_covinit, M->getTargetTriple().getObjectFormat()));
1050 CovInitGV->setAlignment(Align(INSTR_PROF_DATA_ALIGNMENT));
1051 CovInitGV->setConstant(true);
1052}
1053
1054FunctionCallee GCOVProfiler::getStartFileFunc(const TargetLibraryInfo *TLI) {
1055 Type *Args[] = {
1056 PointerType::getUnqual(*Ctx), // const char *orig_filename
1057 Type::getInt32Ty(*Ctx), // uint32_t version
1058 Type::getInt32Ty(*Ctx), // uint32_t checksum
1059 };
1060 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
1061 return M->getOrInsertFunction("llvm_gcda_start_file", FTy,
1062 TLI->getAttrList(Ctx, {1, 2}, /*Signed=*/false));
1063}
1064
1065FunctionCallee GCOVProfiler::getEmitFunctionFunc(const TargetLibraryInfo *TLI) {
1066 Type *Args[] = {
1067 Type::getInt32Ty(*Ctx), // uint32_t ident
1068 Type::getInt32Ty(*Ctx), // uint32_t func_checksum
1069 Type::getInt32Ty(*Ctx), // uint32_t cfg_checksum
1070 };
1071 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
1072 return M->getOrInsertFunction("llvm_gcda_emit_function", FTy,
1073 TLI->getAttrList(Ctx, {0, 1, 2}, /*Signed=*/false));
1074}
1075
1076FunctionCallee GCOVProfiler::getEmitArcsFunc(const TargetLibraryInfo *TLI) {
1077 Type *Args[] = {
1078 Type::getInt32Ty(*Ctx), // uint32_t num_counters
1079 PointerType::getUnqual(*Ctx), // uint64_t *counters
1080 };
1081 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
1082 return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy,
1083 TLI->getAttrList(Ctx, {0}, /*Signed=*/false));
1084}
1085
1086FunctionCallee GCOVProfiler::getSummaryInfoFunc() {
1087 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
1088 return M->getOrInsertFunction("llvm_gcda_summary_info", FTy);
1089}
1090
1091FunctionCallee GCOVProfiler::getEndFileFunc() {
1092 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
1093 return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
1094}
1095
1096Function *GCOVProfiler::insertCounterWriteout(
1097 ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
1098 FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
1099 Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
1100 if (!WriteoutF)
1101 WriteoutF =
1102 createInternalFunction(WriteoutFTy, "__llvm_gcov_writeout", "_ZTSFvvE");
1103 WriteoutF->addFnAttr(Attribute::NoInline);
1104
1105 BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF);
1106 IRBuilder<> Builder(BB);
1107
1108 auto *TLI = &GetTLI(*WriteoutF);
1109
1110 FunctionCallee StartFile = getStartFileFunc(TLI);
1111 FunctionCallee EmitFunction = getEmitFunctionFunc(TLI);
1112 FunctionCallee EmitArcs = getEmitArcsFunc(TLI);
1113 FunctionCallee SummaryInfo = getSummaryInfoFunc();
1114 FunctionCallee EndFile = getEndFileFunc();
1115
1116 NamedMDNode *CUNodes = M->getNamedMetadata("llvm.dbg.cu");
1117 if (!CUNodes) {
1118 Builder.CreateRetVoid();
1119 return WriteoutF;
1120 }
1121
1122 // Collect the relevant data into a large constant data structure that we can
1123 // walk to write out everything.
1124 StructType *StartFileCallArgsTy = StructType::create(
1125 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getInt32Ty()},
1126 "start_file_args_ty");
1127 StructType *EmitFunctionCallArgsTy = StructType::create(
1128 {Builder.getInt32Ty(), Builder.getInt32Ty(), Builder.getInt32Ty()},
1129 "emit_function_args_ty");
1130 auto *PtrTy = Builder.getPtrTy();
1131 StructType *EmitArcsCallArgsTy =
1132 StructType::create({Builder.getInt32Ty(), PtrTy}, "emit_arcs_args_ty");
1133 StructType *FileInfoTy = StructType::create(
1134 {StartFileCallArgsTy, Builder.getInt32Ty(), PtrTy, PtrTy}, "file_info");
1135
1137 for (int i : llvm::seq<int>(0, CUNodes->getNumOperands())) {
1138 auto *CU = cast<DICompileUnit>(CUNodes->getOperand(i));
1139
1140 // Skip module skeleton (and module) CUs.
1141 if (CU->getDWOId())
1142 continue;
1143
1144 std::string FilenameGcda = mangleName(CU, GCovFileType::GCDA);
1145 uint32_t CfgChecksum = FileChecksums.empty() ? 0 : FileChecksums[i];
1146 auto *StartFileCallArgs = ConstantStruct::get(
1147 StartFileCallArgsTy,
1148 {Builder.CreateGlobalString(FilenameGcda),
1149 Builder.getInt32(endian::read32be(Options.Version)),
1150 Builder.getInt32(CfgChecksum)});
1151
1152 SmallVector<Constant *, 8> EmitFunctionCallArgsArray;
1153 SmallVector<Constant *, 8> EmitArcsCallArgsArray;
1154 for (int j : llvm::seq<int>(0, CountersBySP.size())) {
1155 uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[j]->getFuncChecksum();
1156 EmitFunctionCallArgsArray.push_back(ConstantStruct::get(
1157 EmitFunctionCallArgsTy,
1158 {Builder.getInt32(j),
1159 Builder.getInt32(FuncChecksum),
1160 Builder.getInt32(CfgChecksum)}));
1161
1162 GlobalVariable *GV = CountersBySP[j].first;
1163 unsigned Arcs = cast<ArrayType>(GV->getValueType())->getNumElements();
1164 EmitArcsCallArgsArray.push_back(ConstantStruct::get(
1165 EmitArcsCallArgsTy, {Builder.getInt32(Arcs), GV}));
1166 }
1167 // Create global arrays for the two emit calls.
1168 int CountersSize = CountersBySP.size();
1169 assert(CountersSize == (int)EmitFunctionCallArgsArray.size() &&
1170 "Mismatched array size!");
1171 assert(CountersSize == (int)EmitArcsCallArgsArray.size() &&
1172 "Mismatched array size!");
1173 auto *EmitFunctionCallArgsArrayTy =
1174 ArrayType::get(EmitFunctionCallArgsTy, CountersSize);
1175 auto *EmitFunctionCallArgsArrayGV = new GlobalVariable(
1176 *M, EmitFunctionCallArgsArrayTy, /*isConstant*/ true,
1178 ConstantArray::get(EmitFunctionCallArgsArrayTy,
1179 EmitFunctionCallArgsArray),
1180 Twine("__llvm_internal_gcov_emit_function_args.") + Twine(i));
1181 auto *EmitArcsCallArgsArrayTy =
1182 ArrayType::get(EmitArcsCallArgsTy, CountersSize);
1183 EmitFunctionCallArgsArrayGV->setUnnamedAddr(
1184 GlobalValue::UnnamedAddr::Global);
1185 auto *EmitArcsCallArgsArrayGV = new GlobalVariable(
1186 *M, EmitArcsCallArgsArrayTy, /*isConstant*/ true,
1188 ConstantArray::get(EmitArcsCallArgsArrayTy, EmitArcsCallArgsArray),
1189 Twine("__llvm_internal_gcov_emit_arcs_args.") + Twine(i));
1190 EmitArcsCallArgsArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1191
1192 FileInfos.push_back(ConstantStruct::get(
1193 FileInfoTy, {StartFileCallArgs, Builder.getInt32(CountersSize),
1194 EmitFunctionCallArgsArrayGV, EmitArcsCallArgsArrayGV}));
1195 }
1196
1197 // If we didn't find anything to actually emit, bail on out.
1198 if (FileInfos.empty()) {
1199 Builder.CreateRetVoid();
1200 return WriteoutF;
1201 }
1202
1203 // To simplify code, we cap the number of file infos we write out to fit
1204 // easily in a 32-bit signed integer. This gives consistent behavior between
1205 // 32-bit and 64-bit systems without requiring (potentially very slow) 64-bit
1206 // operations on 32-bit systems. It also seems unreasonable to try to handle
1207 // more than 2 billion files.
1208 if ((int64_t)FileInfos.size() > (int64_t)INT_MAX)
1209 FileInfos.resize(INT_MAX);
1210
1211 // Create a global for the entire data structure so we can walk it more
1212 // easily.
1213 auto *FileInfoArrayTy = ArrayType::get(FileInfoTy, FileInfos.size());
1214 auto *FileInfoArrayGV = new GlobalVariable(
1215 *M, FileInfoArrayTy, /*isConstant*/ true, GlobalValue::InternalLinkage,
1216 ConstantArray::get(FileInfoArrayTy, FileInfos),
1217 "__llvm_internal_gcov_emit_file_info");
1218 FileInfoArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
1219
1220 // Create the CFG for walking this data structure.
1221 auto *FileLoopHeader =
1222 BasicBlock::Create(*Ctx, "file.loop.header", WriteoutF);
1223 auto *CounterLoopHeader =
1224 BasicBlock::Create(*Ctx, "counter.loop.header", WriteoutF);
1225 auto *FileLoopLatch = BasicBlock::Create(*Ctx, "file.loop.latch", WriteoutF);
1226 auto *ExitBB = BasicBlock::Create(*Ctx, "exit", WriteoutF);
1227
1228 // We always have at least one file, so just branch to the header.
1229 Builder.CreateBr(FileLoopHeader);
1230
1231 // The index into the files structure is our loop induction variable.
1232 Builder.SetInsertPoint(FileLoopHeader);
1233 PHINode *IV = Builder.CreatePHI(Builder.getInt32Ty(), /*NumReservedValues*/ 2,
1234 "file_idx");
1235 IV->addIncoming(Builder.getInt32(0), BB);
1236 auto *FileInfoPtr = Builder.CreateInBoundsGEP(
1237 FileInfoArrayTy, FileInfoArrayGV, {Builder.getInt32(0), IV});
1238 auto *StartFileCallArgsPtr =
1239 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 0, "start_file_args");
1240 auto *StartFileCall = Builder.CreateCall(
1241 StartFile,
1242 {Builder.CreateLoad(StartFileCallArgsTy->getElementType(0),
1243 Builder.CreateStructGEP(StartFileCallArgsTy,
1244 StartFileCallArgsPtr, 0),
1245 "filename"),
1246 Builder.CreateLoad(StartFileCallArgsTy->getElementType(1),
1247 Builder.CreateStructGEP(StartFileCallArgsTy,
1248 StartFileCallArgsPtr, 1),
1249 "version"),
1250 Builder.CreateLoad(StartFileCallArgsTy->getElementType(2),
1251 Builder.CreateStructGEP(StartFileCallArgsTy,
1252 StartFileCallArgsPtr, 2),
1253 "stamp")});
1254 if (auto AK = TLI->getExtAttrForI32Param(false))
1255 StartFileCall->addParamAttr(2, AK);
1256 auto *NumCounters = Builder.CreateLoad(
1257 FileInfoTy->getElementType(1),
1258 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 1), "num_ctrs");
1259 auto *EmitFunctionCallArgsArray =
1260 Builder.CreateLoad(FileInfoTy->getElementType(2),
1261 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 2),
1262 "emit_function_args");
1263 auto *EmitArcsCallArgsArray = Builder.CreateLoad(
1264 FileInfoTy->getElementType(3),
1265 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 3), "emit_arcs_args");
1266 auto *EnterCounterLoopCond =
1267 Builder.CreateICmpSLT(Builder.getInt32(0), NumCounters);
1268 Builder.CreateCondBr(EnterCounterLoopCond, CounterLoopHeader, FileLoopLatch);
1269
1270 Builder.SetInsertPoint(CounterLoopHeader);
1271 auto *JV = Builder.CreatePHI(Builder.getInt32Ty(), /*NumReservedValues*/ 2,
1272 "ctr_idx");
1273 JV->addIncoming(Builder.getInt32(0), FileLoopHeader);
1274 auto *EmitFunctionCallArgsPtr = Builder.CreateInBoundsGEP(
1275 EmitFunctionCallArgsTy, EmitFunctionCallArgsArray, JV);
1276 auto *EmitFunctionCall = Builder.CreateCall(
1277 EmitFunction,
1278 {Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(0),
1279 Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1280 EmitFunctionCallArgsPtr, 0),
1281 "ident"),
1282 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(1),
1283 Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1284 EmitFunctionCallArgsPtr, 1),
1285 "func_checkssum"),
1286 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(2),
1287 Builder.CreateStructGEP(EmitFunctionCallArgsTy,
1288 EmitFunctionCallArgsPtr, 2),
1289 "cfg_checksum")});
1290 if (auto AK = TLI->getExtAttrForI32Param(false)) {
1291 EmitFunctionCall->addParamAttr(0, AK);
1292 EmitFunctionCall->addParamAttr(1, AK);
1293 EmitFunctionCall->addParamAttr(2, AK);
1294 }
1295 auto *EmitArcsCallArgsPtr =
1296 Builder.CreateInBoundsGEP(EmitArcsCallArgsTy, EmitArcsCallArgsArray, JV);
1297 auto *EmitArcsCall = Builder.CreateCall(
1298 EmitArcs,
1299 {Builder.CreateLoad(
1300 EmitArcsCallArgsTy->getElementType(0),
1301 Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 0),
1302 "num_counters"),
1303 Builder.CreateLoad(
1304 EmitArcsCallArgsTy->getElementType(1),
1305 Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 1),
1306 "counters")});
1307 if (auto AK = TLI->getExtAttrForI32Param(false))
1308 EmitArcsCall->addParamAttr(0, AK);
1309 auto *NextJV = Builder.CreateAdd(JV, Builder.getInt32(1));
1310 auto *CounterLoopCond = Builder.CreateICmpSLT(NextJV, NumCounters);
1311 Builder.CreateCondBr(CounterLoopCond, CounterLoopHeader, FileLoopLatch);
1312 JV->addIncoming(NextJV, CounterLoopHeader);
1313
1314 Builder.SetInsertPoint(FileLoopLatch);
1315 Builder.CreateCall(SummaryInfo, {});
1316 Builder.CreateCall(EndFile, {});
1317 auto *NextIV = Builder.CreateAdd(IV, Builder.getInt32(1), "next_file_idx");
1318 auto *FileLoopCond =
1319 Builder.CreateICmpSLT(NextIV, Builder.getInt32(FileInfos.size()));
1320 Builder.CreateCondBr(FileLoopCond, FileLoopHeader, ExitBB);
1321 IV->addIncoming(NextIV, FileLoopLatch);
1322
1323 Builder.SetInsertPoint(ExitBB);
1324 Builder.CreateRetVoid();
1325
1326 return WriteoutF;
1327}
1328
1329Function *GCOVProfiler::insertReset(
1330 ArrayRef<std::pair<GlobalVariable *, MDNode *>> CountersBySP) {
1331 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
1332 Function *ResetF = M->getFunction("__llvm_gcov_reset");
1333 if (!ResetF)
1334 ResetF = createInternalFunction(FTy, "__llvm_gcov_reset", "_ZTSFvvE");
1335 ResetF->addFnAttr(Attribute::NoInline);
1336
1337 BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", ResetF);
1338 IRBuilder<> Builder(Entry);
1339 LLVMContext &C = Entry->getContext();
1340
1341 // Zero out the counters.
1342 for (const auto &I : CountersBySP) {
1343 GlobalVariable *GV = I.first;
1344 auto *GVTy = cast<ArrayType>(GV->getValueType());
1345 Builder.CreateMemSet(GV, Constant::getNullValue(Type::getInt8Ty(C)),
1346 GVTy->getNumElements() *
1347 GVTy->getElementType()->getScalarSizeInBits() / 8,
1348 GV->getAlign());
1349 }
1350
1351 Type *RetTy = ResetF->getReturnType();
1352 if (RetTy->isVoidTy())
1353 Builder.CreateRetVoid();
1354 else if (RetTy->isIntegerTy())
1355 // Used if __llvm_gcov_reset was implicitly declared.
1356 Builder.CreateRet(ConstantInt::get(RetTy, 0));
1357 else
1358 report_fatal_error("invalid return type for __llvm_gcov_reset");
1359
1360 return ResetF;
1361}
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
uint64_t uint64_t
Expand Atomic instructions
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static void writeString(raw_ostream &OS, StringRef S)
This file provides the interface for the GCOV style profiler pass.
static GCOVOptions getDefaultOptions(const InstrumentationOptions &Opts)
static unsigned wordsOfString(StringRef s)
static bool functionHasLines(const Function &F, unsigned &EndLine)
static bool isUsingScopeBasedEH(Function &F)
static void dumpEdges(CFGMST< Edge, BBInfo > &MST, GCOVFunction &GF)
static BasicBlock * getInstrBB(CFGMST< Edge, BBInfo > &MST, Edge &E, const DenseSet< const BasicBlock * > &ExecBlocks)
static StringRef getFunctionName(const DISubprogram *SP)
@ GCOV_TAG_LINES
Definition GCOV.cpp:38
@ GCOV_ARC_ON_TREE
Definition GCOV.cpp:32
@ GCOV_TAG_ARCS
Definition GCOV.cpp:37
@ GCOV_TAG_FUNCTION
Definition GCOV.cpp:35
@ GCOV_TAG_BLOCKS
Definition GCOV.cpp:36
Module.h This file contains the declarations for the Module class.
#define INSTR_PROF_DATA_ALIGNMENT
static LVOptions Options
Definition LVOptions.cpp:25
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
static constexpr StringLiteral Filename
#define P(N)
FunctionAnalysisManager FAM
std::pair< BasicBlock *, BasicBlock * > Edge
This file contains some templates that are useful if you are working with the STL at all.
Provides some synthesis utilities to produce sequences of values.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Defines the virtual file system interface vfs::FileSystem.
Value * RHS
static const uint32_t IV[8]
Definition blake3_impl.h:83
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
@ Add
*p = old + v
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:453
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
const Instruction & back() const
Definition BasicBlock.h:465
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
Analysis pass which computes BlockFrequencyInfo.
Analysis pass which computes BranchProbabilityInfo.
An union-find based Minimum Spanning Tree for CFG.
Definition CFGMST.h:41
Edge & addEdge(BasicBlock *Src, BasicBlock *Dest, uint64_t W)
Definition CFGMST.h:329
const std::vector< std::unique_ptr< Edge > > & allEdges() const
Definition CFGMST.h:366
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
uint64_t getDWOId() const
Base class for scope-like contexts.
StringRef getFilename() const
Subprogram description. Uses SubclassData1.
A debug info location.
Definition DebugLoc.h:126
LLVM_ABI unsigned getLine() const
Definition DebugLoc.cpp:43
LLVM_ABI MDNode * getScope() const
Definition DebugLoc.cpp:53
LLVM_ABI bool isImplicitCode() const
Check if the DebugLoc corresponds to an implicit code.
Definition DebugLoc.cpp:83
Implements a dense probed hash-table based set.
Definition DenseSet.h:283
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:641
static Function * createWithDefaultAttr(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Creates a function with some attributes recorded in llvm.module.flags and the LLVMContext applied.
Definition Function.cpp:372
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:217
GCOVBlock - Collects block information.
Definition GCOV.h:283
GCOVFunction - Collects function information.
Definition GCOV.h:237
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
Type * getValueType() const
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
LLVM_ABI void setNoSanitizeMetadata()
Sets the nosanitize metadata on this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
uint32_t getCRC() const
Definition CRC.h:77
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Definition CRC.cpp:103
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:613
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
LLVM_ABI MDNode * getOperand(unsigned i) const
LLVM_ABI unsigned getNumOperands() const
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
iterator end()
Definition StringMap.h:214
iterator find(StringRef Key)
Definition StringMap.h:227
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:467
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:662
Type * getElementType(unsigned N) const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
Definition Triple.h:539
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:188
self_iterator getIterator()
Definition ilist_node.h:123
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
virtual bool exists(const Twine &Path)
Check whether Path exists.
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output)
Gets real path of Path e.g.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Entry
Definition COFF.h:862
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
constexpr MCPhysReg SP
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
void write32(void *P, uint32_t V, endianness E)
Definition Endian.h:435
uint32_t read32be(const void *P)
Definition Endian.h:421
LLVM_ABI void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)
Replace the file extension of path with extension.
Definition Path.cpp:491
LLVM_ABI bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
Remove '.
Definition Path.cpp:779
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:594
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:467
This is an optimization pass for GlobalISel generic memory operations.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
hash_code hash_value(const FixedPointSemantics &Val)
LLVM_ABI unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ)
Search for the specified successor of basic block BB and return its position in the terminator instru...
Definition CFG.cpp:90
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool SplitIndirectBrCriticalEdges(Function &F, bool IgnoreBlocksWithoutPHI, BranchProbabilityInfo *BPI=nullptr, BlockFrequencyInfo *BFI=nullptr, DomTreeUpdater *DTU=nullptr)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)
Definition iterator.h:341
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI BasicBlock * SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")
If this edge is a critical edge, insert a new node to split the critical edge.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
LLVM_ABI void setKCFIType(Module &M, Function &F, StringRef MangledType)
Sets the KCFI type for the function.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2208
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
endianness
Definition bit.h:71
LLVM_ABI Error write(DWPWriter &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue, raw_pwrite_stream *OS=nullptr)
Definition DWP.cpp:746
LLVM_ABI DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
#define N