clang 18.0.0git
CoverageMappingGen.cpp
Go to the documentation of this file.
1//===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
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// Instrumentation-based code coverage mapping generator
10//
11//===----------------------------------------------------------------------===//
12
13#include "CoverageMappingGen.h"
14#include "CodeGenFunction.h"
19#include "clang/Lex/Lexer.h"
20#include "llvm/ADT/SmallSet.h"
21#include "llvm/ADT/StringExtras.h"
22#include "llvm/ProfileData/Coverage/CoverageMapping.h"
23#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
24#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
25#include "llvm/ProfileData/InstrProfReader.h"
26#include "llvm/Support/FileSystem.h"
27#include "llvm/Support/Path.h"
28#include <optional>
29
30// This selects the coverage mapping format defined when `InstrProfData.inc`
31// is textually included.
32#define COVMAP_V3
33
34static llvm::cl::opt<bool> EmptyLineCommentCoverage(
35 "emptyline-comment-coverage",
36 llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only "
37 "disable it on test)"),
38 llvm::cl::init(true), llvm::cl::Hidden);
39
40static llvm::cl::opt<bool> SystemHeadersCoverage(
41 "system-headers-coverage",
42 llvm::cl::desc("Enable collecting coverage from system headers"),
43 llvm::cl::init(false), llvm::cl::Hidden);
44
45using namespace clang;
46using namespace CodeGen;
47using namespace llvm::coverage;
48
51 CoverageSourceInfo *CoverageInfo =
53 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(CoverageInfo));
55 PP.addCommentHandler(CoverageInfo);
56 PP.setEmptylineHandler(CoverageInfo);
57 PP.setPreprocessToken(true);
58 PP.setTokenWatcher([CoverageInfo](clang::Token Tok) {
59 // Update previous token location.
60 CoverageInfo->PrevTokLoc = Tok.getLocation();
61 if (Tok.getKind() != clang::tok::eod)
62 CoverageInfo->updateNextTokLoc(Tok.getLocation());
63 });
64 }
65 return CoverageInfo;
66}
67
69 SkippedRange::Kind RangeKind) {
70 if (EmptyLineCommentCoverage && !SkippedRanges.empty() &&
71 PrevTokLoc == SkippedRanges.back().PrevTokLoc &&
72 SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(),
73 Range.getBegin()))
74 SkippedRanges.back().Range.setEnd(Range.getEnd());
75 else
76 SkippedRanges.push_back({Range, RangeKind, PrevTokLoc});
77}
78
80 AddSkippedRange(Range, SkippedRange::PPIfElse);
81}
82
84 AddSkippedRange(Range, SkippedRange::EmptyLine);
85}
86
88 AddSkippedRange(Range, SkippedRange::Comment);
89 return false;
90}
91
93 if (!SkippedRanges.empty() && SkippedRanges.back().NextTokLoc.isInvalid())
94 SkippedRanges.back().NextTokLoc = Loc;
95}
96
97namespace {
98
99/// A region of source code that can be mapped to a counter.
100class SourceMappingRegion {
101 /// Primary Counter that is also used for Branch Regions for "True" branches.
102 Counter Count;
103
104 /// Secondary Counter used for Branch Regions for "False" branches.
105 std::optional<Counter> FalseCount;
106
107 /// The region's starting location.
108 std::optional<SourceLocation> LocStart;
109
110 /// The region's ending location.
111 std::optional<SourceLocation> LocEnd;
112
113 /// Whether this region is a gap region. The count from a gap region is set
114 /// as the line execution count if there are no other regions on the line.
115 bool GapRegion;
116
117public:
118 SourceMappingRegion(Counter Count, std::optional<SourceLocation> LocStart,
119 std::optional<SourceLocation> LocEnd,
120 bool GapRegion = false)
121 : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {
122 }
123
124 SourceMappingRegion(Counter Count, std::optional<Counter> FalseCount,
125 std::optional<SourceLocation> LocStart,
126 std::optional<SourceLocation> LocEnd,
127 bool GapRegion = false)
128 : Count(Count), FalseCount(FalseCount), LocStart(LocStart),
129 LocEnd(LocEnd), GapRegion(GapRegion) {}
130
131 const Counter &getCounter() const { return Count; }
132
133 const Counter &getFalseCounter() const {
134 assert(FalseCount && "Region has no alternate counter");
135 return *FalseCount;
136 }
137
138 void setCounter(Counter C) { Count = C; }
139
140 bool hasStartLoc() const { return LocStart.has_value(); }
141
142 void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
143
144 SourceLocation getBeginLoc() const {
145 assert(LocStart && "Region has no start location");
146 return *LocStart;
147 }
148
149 bool hasEndLoc() const { return LocEnd.has_value(); }
150
151 void setEndLoc(SourceLocation Loc) {
152 assert(Loc.isValid() && "Setting an invalid end location");
153 LocEnd = Loc;
154 }
155
156 SourceLocation getEndLoc() const {
157 assert(LocEnd && "Region has no end location");
158 return *LocEnd;
159 }
160
161 bool isGap() const { return GapRegion; }
162
163 void setGap(bool Gap) { GapRegion = Gap; }
164
165 bool isBranch() const { return FalseCount.has_value(); }
166};
167
168/// Spelling locations for the start and end of a source region.
169struct SpellingRegion {
170 /// The line where the region starts.
171 unsigned LineStart;
172
173 /// The column where the region starts.
174 unsigned ColumnStart;
175
176 /// The line where the region ends.
177 unsigned LineEnd;
178
179 /// The column where the region ends.
180 unsigned ColumnEnd;
181
182 SpellingRegion(SourceManager &SM, SourceLocation LocStart,
183 SourceLocation LocEnd) {
184 LineStart = SM.getSpellingLineNumber(LocStart);
185 ColumnStart = SM.getSpellingColumnNumber(LocStart);
186 LineEnd = SM.getSpellingLineNumber(LocEnd);
187 ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
188 }
189
190 SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
191 : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
192
193 /// Check if the start and end locations appear in source order, i.e
194 /// top->bottom, left->right.
195 bool isInSourceOrder() const {
196 return (LineStart < LineEnd) ||
197 (LineStart == LineEnd && ColumnStart <= ColumnEnd);
198 }
199};
200
201/// Provides the common functionality for the different
202/// coverage mapping region builders.
203class CoverageMappingBuilder {
204public:
207 const LangOptions &LangOpts;
208
209private:
210 /// Map of clang's FileIDs to IDs used for coverage mapping.
211 llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
212 FileIDMapping;
213
214public:
215 /// The coverage mapping regions for this function
217 /// The source mapping regions for this function.
218 std::vector<SourceMappingRegion> SourceRegions;
219
220 /// A set of regions which can be used as a filter.
221 ///
222 /// It is produced by emitExpansionRegions() and is used in
223 /// emitSourceRegions() to suppress producing code regions if
224 /// the same area is covered by expansion regions.
225 typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
226 SourceRegionFilter;
227
228 CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
229 const LangOptions &LangOpts)
230 : CVM(CVM), SM(SM), LangOpts(LangOpts) {}
231
232 /// Return the precise end location for the given token.
233 SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
234 // We avoid getLocForEndOfToken here, because it doesn't do what we want for
235 // macro locations, which we just treat as expanded files.
236 unsigned TokLen =
237 Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts);
238 return Loc.getLocWithOffset(TokLen);
239 }
240
241 /// Return the start location of an included file or expanded macro.
242 SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
243 if (Loc.isMacroID())
244 return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
245 return SM.getLocForStartOfFile(SM.getFileID(Loc));
246 }
247
248 /// Return the end location of an included file or expanded macro.
249 SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
250 if (Loc.isMacroID())
251 return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
252 SM.getFileOffset(Loc));
253 return SM.getLocForEndOfFile(SM.getFileID(Loc));
254 }
255
256 /// Find out where the current file is included or macro is expanded.
257 SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
258 return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin()
259 : SM.getIncludeLoc(SM.getFileID(Loc));
260 }
261
262 /// Return true if \c Loc is a location in a built-in macro.
263 bool isInBuiltin(SourceLocation Loc) {
264 return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
265 }
266
267 /// Check whether \c Loc is included or expanded from \c Parent.
268 bool isNestedIn(SourceLocation Loc, FileID Parent) {
269 do {
270 Loc = getIncludeOrExpansionLoc(Loc);
271 if (Loc.isInvalid())
272 return false;
273 } while (!SM.isInFileID(Loc, Parent));
274 return true;
275 }
276
277 /// Get the start of \c S ignoring macro arguments and builtin macros.
278 SourceLocation getStart(const Stmt *S) {
279 SourceLocation Loc = S->getBeginLoc();
280 while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
281 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
282 return Loc;
283 }
284
285 /// Get the end of \c S ignoring macro arguments and builtin macros.
286 SourceLocation getEnd(const Stmt *S) {
287 SourceLocation Loc = S->getEndLoc();
288 while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
289 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
290 return getPreciseTokenLocEnd(Loc);
291 }
292
293 /// Find the set of files we have regions for and assign IDs
294 ///
295 /// Fills \c Mapping with the virtual file mapping needed to write out
296 /// coverage and collects the necessary file information to emit source and
297 /// expansion regions.
298 void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) {
299 FileIDMapping.clear();
300
301 llvm::SmallSet<FileID, 8> Visited;
303 for (const auto &Region : SourceRegions) {
304 SourceLocation Loc = Region.getBeginLoc();
305 FileID File = SM.getFileID(Loc);
306 if (!Visited.insert(File).second)
307 continue;
308
309 // Do not map FileID's associated with system headers unless collecting
310 // coverage from system headers is explicitly enabled.
311 if (!SystemHeadersCoverage && SM.isInSystemHeader(SM.getSpellingLoc(Loc)))
312 continue;
313
314 unsigned Depth = 0;
315 for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
316 Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent))
317 ++Depth;
318 FileLocs.push_back(std::make_pair(Loc, Depth));
319 }
320 llvm::stable_sort(FileLocs, llvm::less_second());
321
322 for (const auto &FL : FileLocs) {
323 SourceLocation Loc = FL.first;
324 FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first;
325 auto Entry = SM.getFileEntryRefForID(SpellingFile);
326 if (!Entry)
327 continue;
328
329 FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
330 Mapping.push_back(CVM.getFileID(*Entry));
331 }
332 }
333
334 /// Get the coverage mapping file ID for \c Loc.
335 ///
336 /// If such file id doesn't exist, return std::nullopt.
337 std::optional<unsigned> getCoverageFileID(SourceLocation Loc) {
338 auto Mapping = FileIDMapping.find(SM.getFileID(Loc));
339 if (Mapping != FileIDMapping.end())
340 return Mapping->second.first;
341 return std::nullopt;
342 }
343
344 /// This shrinks the skipped range if it spans a line that contains a
345 /// non-comment token. If shrinking the skipped range would make it empty,
346 /// this returns std::nullopt.
347 /// Note this function can potentially be expensive because
348 /// getSpellingLineNumber uses getLineNumber, which is expensive.
349 std::optional<SpellingRegion> adjustSkippedRange(SourceManager &SM,
350 SourceLocation LocStart,
351 SourceLocation LocEnd,
352 SourceLocation PrevTokLoc,
353 SourceLocation NextTokLoc) {
354 SpellingRegion SR{SM, LocStart, LocEnd};
355 SR.ColumnStart = 1;
356 if (PrevTokLoc.isValid() && SM.isWrittenInSameFile(LocStart, PrevTokLoc) &&
357 SR.LineStart == SM.getSpellingLineNumber(PrevTokLoc))
358 SR.LineStart++;
359 if (NextTokLoc.isValid() && SM.isWrittenInSameFile(LocEnd, NextTokLoc) &&
360 SR.LineEnd == SM.getSpellingLineNumber(NextTokLoc)) {
361 SR.LineEnd--;
362 SR.ColumnEnd++;
363 }
364 if (SR.isInSourceOrder())
365 return SR;
366 return std::nullopt;
367 }
368
369 /// Gather all the regions that were skipped by the preprocessor
370 /// using the constructs like #if or comments.
371 void gatherSkippedRegions() {
372 /// An array of the minimum lineStarts and the maximum lineEnds
373 /// for mapping regions from the appropriate source files.
375 FileLineRanges.resize(
376 FileIDMapping.size(),
377 std::make_pair(std::numeric_limits<unsigned>::max(), 0));
378 for (const auto &R : MappingRegions) {
379 FileLineRanges[R.FileID].first =
380 std::min(FileLineRanges[R.FileID].first, R.LineStart);
381 FileLineRanges[R.FileID].second =
382 std::max(FileLineRanges[R.FileID].second, R.LineEnd);
383 }
384
385 auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
386 for (auto &I : SkippedRanges) {
387 SourceRange Range = I.Range;
388 auto LocStart = Range.getBegin();
389 auto LocEnd = Range.getEnd();
390 assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
391 "region spans multiple files");
392
393 auto CovFileID = getCoverageFileID(LocStart);
394 if (!CovFileID)
395 continue;
396 std::optional<SpellingRegion> SR;
397 if (I.isComment())
398 SR = adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc,
399 I.NextTokLoc);
400 else if (I.isPPIfElse() || I.isEmptyLine())
401 SR = {SM, LocStart, LocEnd};
402
403 if (!SR)
404 continue;
405 auto Region = CounterMappingRegion::makeSkipped(
406 *CovFileID, SR->LineStart, SR->ColumnStart, SR->LineEnd,
407 SR->ColumnEnd);
408 // Make sure that we only collect the regions that are inside
409 // the source code of this function.
410 if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
411 Region.LineEnd <= FileLineRanges[*CovFileID].second)
412 MappingRegions.push_back(Region);
413 }
414 }
415
416 /// Generate the coverage counter mapping regions from collected
417 /// source regions.
418 void emitSourceRegions(const SourceRegionFilter &Filter) {
419 for (const auto &Region : SourceRegions) {
420 assert(Region.hasEndLoc() && "incomplete region");
421
422 SourceLocation LocStart = Region.getBeginLoc();
423 assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
424
425 // Ignore regions from system headers unless collecting coverage from
426 // system headers is explicitly enabled.
428 SM.isInSystemHeader(SM.getSpellingLoc(LocStart)))
429 continue;
430
431 auto CovFileID = getCoverageFileID(LocStart);
432 // Ignore regions that don't have a file, such as builtin macros.
433 if (!CovFileID)
434 continue;
435
436 SourceLocation LocEnd = Region.getEndLoc();
437 assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
438 "region spans multiple files");
439
440 // Don't add code regions for the area covered by expansion regions.
441 // This not only suppresses redundant regions, but sometimes prevents
442 // creating regions with wrong counters if, for example, a statement's
443 // body ends at the end of a nested macro.
444 if (Filter.count(std::make_pair(LocStart, LocEnd)))
445 continue;
446
447 // Find the spelling locations for the mapping region.
448 SpellingRegion SR{SM, LocStart, LocEnd};
449 assert(SR.isInSourceOrder() && "region start and end out of order");
450
451 if (Region.isGap()) {
452 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
453 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
454 SR.LineEnd, SR.ColumnEnd));
455 } else if (Region.isBranch()) {
456 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
457 Region.getCounter(), Region.getFalseCounter(), *CovFileID,
458 SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd));
459 } else {
460 MappingRegions.push_back(CounterMappingRegion::makeRegion(
461 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
462 SR.LineEnd, SR.ColumnEnd));
463 }
464 }
465 }
466
467 /// Generate expansion regions for each virtual file we've seen.
468 SourceRegionFilter emitExpansionRegions() {
469 SourceRegionFilter Filter;
470 for (const auto &FM : FileIDMapping) {
471 SourceLocation ExpandedLoc = FM.second.second;
472 SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
473 if (ParentLoc.isInvalid())
474 continue;
475
476 auto ParentFileID = getCoverageFileID(ParentLoc);
477 if (!ParentFileID)
478 continue;
479 auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
480 assert(ExpandedFileID && "expansion in uncovered file");
481
482 SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
483 assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
484 "region spans multiple files");
485 Filter.insert(std::make_pair(ParentLoc, LocEnd));
486
487 SpellingRegion SR{SM, ParentLoc, LocEnd};
488 assert(SR.isInSourceOrder() && "region start and end out of order");
489 MappingRegions.push_back(CounterMappingRegion::makeExpansion(
490 *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
491 SR.LineEnd, SR.ColumnEnd));
492 }
493 return Filter;
494 }
495};
496
497/// Creates unreachable coverage regions for the functions that
498/// are not emitted.
499struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
500 EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
501 const LangOptions &LangOpts)
502 : CoverageMappingBuilder(CVM, SM, LangOpts) {}
503
504 void VisitDecl(const Decl *D) {
505 if (!D->hasBody())
506 return;
507 auto Body = D->getBody();
508 SourceLocation Start = getStart(Body);
509 SourceLocation End = getEnd(Body);
510 if (!SM.isWrittenInSameFile(Start, End)) {
511 // Walk up to find the common ancestor.
512 // Correct the locations accordingly.
513 FileID StartFileID = SM.getFileID(Start);
514 FileID EndFileID = SM.getFileID(End);
515 while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
516 Start = getIncludeOrExpansionLoc(Start);
517 assert(Start.isValid() &&
518 "Declaration start location not nested within a known region");
519 StartFileID = SM.getFileID(Start);
520 }
521 while (StartFileID != EndFileID) {
522 End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
523 assert(End.isValid() &&
524 "Declaration end location not nested within a known region");
525 EndFileID = SM.getFileID(End);
526 }
527 }
528 SourceRegions.emplace_back(Counter(), Start, End);
529 }
530
531 /// Write the mapping data to the output stream
532 void write(llvm::raw_ostream &OS) {
533 SmallVector<unsigned, 16> FileIDMapping;
534 gatherFileIDs(FileIDMapping);
535 emitSourceRegions(SourceRegionFilter());
536
537 if (MappingRegions.empty())
538 return;
539
540 CoverageMappingWriter Writer(FileIDMapping, std::nullopt, MappingRegions);
541 Writer.write(OS);
542 }
543};
544
545/// A StmtVisitor that creates coverage mapping regions which map
546/// from the source code locations to the PGO counters.
547struct CounterCoverageMappingBuilder
548 : public CoverageMappingBuilder,
549 public ConstStmtVisitor<CounterCoverageMappingBuilder> {
550 /// The map of statements to count values.
551 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
552
553 /// A stack of currently live regions.
554 std::vector<SourceMappingRegion> RegionStack;
555
556 CounterExpressionBuilder Builder;
557
558 /// A location in the most recently visited file or macro.
559 ///
560 /// This is used to adjust the active source regions appropriately when
561 /// expressions cross file or macro boundaries.
562 SourceLocation MostRecentLocation;
563
564 /// Whether the visitor at a terminate statement.
565 bool HasTerminateStmt = false;
566
567 /// Gap region counter after terminate statement.
568 Counter GapRegionCounter;
569
570 /// Return a counter for the subtraction of \c RHS from \c LHS
571 Counter subtractCounters(Counter LHS, Counter RHS, bool Simplify = true) {
572 return Builder.subtract(LHS, RHS, Simplify);
573 }
574
575 /// Return a counter for the sum of \c LHS and \c RHS.
576 Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
577 return Builder.add(LHS, RHS, Simplify);
578 }
579
580 Counter addCounters(Counter C1, Counter C2, Counter C3,
581 bool Simplify = true) {
582 return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
583 }
584
585 /// Return the region counter for the given statement.
586 ///
587 /// This should only be called on statements that have a dedicated counter.
588 Counter getRegionCounter(const Stmt *S) {
589 return Counter::getCounter(CounterMap[S]);
590 }
591
592 /// Push a region onto the stack.
593 ///
594 /// Returns the index on the stack where the region was pushed. This can be
595 /// used with popRegions to exit a "scope", ending the region that was pushed.
596 size_t pushRegion(Counter Count,
597 std::optional<SourceLocation> StartLoc = std::nullopt,
598 std::optional<SourceLocation> EndLoc = std::nullopt,
599 std::optional<Counter> FalseCount = std::nullopt) {
600
601 if (StartLoc && !FalseCount) {
602 MostRecentLocation = *StartLoc;
603 }
604
605 // If either of these locations is invalid, something elsewhere in the
606 // compiler has broken.
607 assert((!StartLoc || StartLoc->isValid()) && "Start location is not valid");
608 assert((!EndLoc || EndLoc->isValid()) && "End location is not valid");
609
610 // However, we can still recover without crashing.
611 // If either location is invalid, set it to std::nullopt to avoid
612 // letting users of RegionStack think that region has a valid start/end
613 // location.
614 if (StartLoc && StartLoc->isInvalid())
615 StartLoc = std::nullopt;
616 if (EndLoc && EndLoc->isInvalid())
617 EndLoc = std::nullopt;
618 RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc);
619
620 return RegionStack.size() - 1;
621 }
622
623 size_t locationDepth(SourceLocation Loc) {
624 size_t Depth = 0;
625 while (Loc.isValid()) {
626 Loc = getIncludeOrExpansionLoc(Loc);
627 Depth++;
628 }
629 return Depth;
630 }
631
632 /// Pop regions from the stack into the function's list of regions.
633 ///
634 /// Adds all regions from \c ParentIndex to the top of the stack to the
635 /// function's \c SourceRegions.
636 void popRegions(size_t ParentIndex) {
637 assert(RegionStack.size() >= ParentIndex && "parent not in stack");
638 while (RegionStack.size() > ParentIndex) {
639 SourceMappingRegion &Region = RegionStack.back();
640 if (Region.hasStartLoc() &&
641 (Region.hasEndLoc() || RegionStack[ParentIndex].hasEndLoc())) {
642 SourceLocation StartLoc = Region.getBeginLoc();
643 SourceLocation EndLoc = Region.hasEndLoc()
644 ? Region.getEndLoc()
645 : RegionStack[ParentIndex].getEndLoc();
646 bool isBranch = Region.isBranch();
647 size_t StartDepth = locationDepth(StartLoc);
648 size_t EndDepth = locationDepth(EndLoc);
649 while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
650 bool UnnestStart = StartDepth >= EndDepth;
651 bool UnnestEnd = EndDepth >= StartDepth;
652 if (UnnestEnd) {
653 // The region ends in a nested file or macro expansion. If the
654 // region is not a branch region, create a separate region for each
655 // expansion, and for all regions, update the EndLoc. Branch
656 // regions should not be split in order to keep a straightforward
657 // correspondance between the region and its associated branch
658 // condition, even if the condition spans multiple depths.
659 SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
660 assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
661
662 if (!isBranch && !isRegionAlreadyAdded(NestedLoc, EndLoc))
663 SourceRegions.emplace_back(Region.getCounter(), NestedLoc,
664 EndLoc);
665
666 EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
667 if (EndLoc.isInvalid())
668 llvm::report_fatal_error(
669 "File exit not handled before popRegions");
670 EndDepth--;
671 }
672 if (UnnestStart) {
673 // The region ends in a nested file or macro expansion. If the
674 // region is not a branch region, create a separate region for each
675 // expansion, and for all regions, update the StartLoc. Branch
676 // regions should not be split in order to keep a straightforward
677 // correspondance between the region and its associated branch
678 // condition, even if the condition spans multiple depths.
679 SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
680 assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
681
682 if (!isBranch && !isRegionAlreadyAdded(StartLoc, NestedLoc))
683 SourceRegions.emplace_back(Region.getCounter(), StartLoc,
684 NestedLoc);
685
686 StartLoc = getIncludeOrExpansionLoc(StartLoc);
687 if (StartLoc.isInvalid())
688 llvm::report_fatal_error(
689 "File exit not handled before popRegions");
690 StartDepth--;
691 }
692 }
693 Region.setStartLoc(StartLoc);
694 Region.setEndLoc(EndLoc);
695
696 if (!isBranch) {
697 MostRecentLocation = EndLoc;
698 // If this region happens to span an entire expansion, we need to
699 // make sure we don't overlap the parent region with it.
700 if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
701 EndLoc == getEndOfFileOrMacro(EndLoc))
702 MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
703 }
704
705 assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
706 assert(SpellingRegion(SM, Region).isInSourceOrder());
707 SourceRegions.push_back(Region);
708 }
709 RegionStack.pop_back();
710 }
711 }
712
713 /// Return the currently active region.
714 SourceMappingRegion &getRegion() {
715 assert(!RegionStack.empty() && "statement has no region");
716 return RegionStack.back();
717 }
718
719 /// Propagate counts through the children of \p S if \p VisitChildren is true.
720 /// Otherwise, only emit a count for \p S itself.
721 Counter propagateCounts(Counter TopCount, const Stmt *S,
722 bool VisitChildren = true) {
723 SourceLocation StartLoc = getStart(S);
724 SourceLocation EndLoc = getEnd(S);
725 size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
726 if (VisitChildren)
727 Visit(S);
728 Counter ExitCount = getRegion().getCounter();
729 popRegions(Index);
730
731 // The statement may be spanned by an expansion. Make sure we handle a file
732 // exit out of this expansion before moving to the next statement.
733 if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
734 MostRecentLocation = EndLoc;
735
736 return ExitCount;
737 }
738
739 /// Determine whether the given condition can be constant folded.
740 bool ConditionFoldsToBool(const Expr *Cond) {
741 Expr::EvalResult Result;
742 return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
743 }
744
745 /// Create a Branch Region around an instrumentable condition for coverage
746 /// and add it to the function's SourceRegions. A branch region tracks a
747 /// "True" counter and a "False" counter for boolean expressions that
748 /// result in the generation of a branch.
749 void createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt) {
750 // Check for NULL conditions.
751 if (!C)
752 return;
753
754 // Ensure we are an instrumentable condition (i.e. no "&&" or "||"). Push
755 // region onto RegionStack but immediately pop it (which adds it to the
756 // function's SourceRegions) because it doesn't apply to any other source
757 // code other than the Condition.
758 if (CodeGenFunction::isInstrumentedCondition(C)) {
759 // If a condition can fold to true or false, the corresponding branch
760 // will be removed. Create a region with both counters hard-coded to
761 // zero. This allows us to visualize them in a special way.
762 // Alternatively, we can prevent any optimization done via
763 // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
764 // CodeGenFunction.c always returns false, but that is very heavy-handed.
765 if (ConditionFoldsToBool(C))
766 popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C),
767 Counter::getZero()));
768 else
769 // Otherwise, create a region with the True counter and False counter.
770 popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt));
771 }
772 }
773
774 /// Create a Branch Region around a SwitchCase for code coverage
775 /// and add it to the function's SourceRegions.
776 void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt,
777 Counter FalseCnt) {
778 // Push region onto RegionStack but immediately pop it (which adds it to
779 // the function's SourceRegions) because it doesn't apply to any other
780 // source other than the SwitchCase.
781 popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
782 }
783
784 /// Check whether a region with bounds \c StartLoc and \c EndLoc
785 /// is already added to \c SourceRegions.
786 bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc,
787 bool isBranch = false) {
788 return llvm::any_of(
789 llvm::reverse(SourceRegions), [&](const SourceMappingRegion &Region) {
790 return Region.getBeginLoc() == StartLoc &&
791 Region.getEndLoc() == EndLoc && Region.isBranch() == isBranch;
792 });
793 }
794
795 /// Adjust the most recently visited location to \c EndLoc.
796 ///
797 /// This should be used after visiting any statements in non-source order.
798 void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
799 MostRecentLocation = EndLoc;
800 // The code region for a whole macro is created in handleFileExit() when
801 // it detects exiting of the virtual file of that macro. If we visited
802 // statements in non-source order, we might already have such a region
803 // added, for example, if a body of a loop is divided among multiple
804 // macros. Avoid adding duplicate regions in such case.
805 if (getRegion().hasEndLoc() &&
806 MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
807 isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
808 MostRecentLocation, getRegion().isBranch()))
809 MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
810 }
811
812 /// Adjust regions and state when \c NewLoc exits a file.
813 ///
814 /// If moving from our most recently tracked location to \c NewLoc exits any
815 /// files, this adjusts our current region stack and creates the file regions
816 /// for the exited file.
817 void handleFileExit(SourceLocation NewLoc) {
818 if (NewLoc.isInvalid() ||
819 SM.isWrittenInSameFile(MostRecentLocation, NewLoc))
820 return;
821
822 // If NewLoc is not in a file that contains MostRecentLocation, walk up to
823 // find the common ancestor.
824 SourceLocation LCA = NewLoc;
825 FileID ParentFile = SM.getFileID(LCA);
826 while (!isNestedIn(MostRecentLocation, ParentFile)) {
827 LCA = getIncludeOrExpansionLoc(LCA);
828 if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) {
829 // Since there isn't a common ancestor, no file was exited. We just need
830 // to adjust our location to the new file.
831 MostRecentLocation = NewLoc;
832 return;
833 }
834 ParentFile = SM.getFileID(LCA);
835 }
836
837 llvm::SmallSet<SourceLocation, 8> StartLocs;
838 std::optional<Counter> ParentCounter;
839 for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
840 if (!I.hasStartLoc())
841 continue;
842 SourceLocation Loc = I.getBeginLoc();
843 if (!isNestedIn(Loc, ParentFile)) {
844 ParentCounter = I.getCounter();
845 break;
846 }
847
848 while (!SM.isInFileID(Loc, ParentFile)) {
849 // The most nested region for each start location is the one with the
850 // correct count. We avoid creating redundant regions by stopping once
851 // we've seen this region.
852 if (StartLocs.insert(Loc).second) {
853 if (I.isBranch())
854 SourceRegions.emplace_back(I.getCounter(), I.getFalseCounter(), Loc,
855 getEndOfFileOrMacro(Loc), I.isBranch());
856 else
857 SourceRegions.emplace_back(I.getCounter(), Loc,
858 getEndOfFileOrMacro(Loc));
859 }
860 Loc = getIncludeOrExpansionLoc(Loc);
861 }
862 I.setStartLoc(getPreciseTokenLocEnd(Loc));
863 }
864
865 if (ParentCounter) {
866 // If the file is contained completely by another region and doesn't
867 // immediately start its own region, the whole file gets a region
868 // corresponding to the parent.
869 SourceLocation Loc = MostRecentLocation;
870 while (isNestedIn(Loc, ParentFile)) {
871 SourceLocation FileStart = getStartOfFileOrMacro(Loc);
872 if (StartLocs.insert(FileStart).second) {
873 SourceRegions.emplace_back(*ParentCounter, FileStart,
874 getEndOfFileOrMacro(Loc));
875 assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder());
876 }
877 Loc = getIncludeOrExpansionLoc(Loc);
878 }
879 }
880
881 MostRecentLocation = NewLoc;
882 }
883
884 /// Ensure that \c S is included in the current region.
885 void extendRegion(const Stmt *S) {
886 SourceMappingRegion &Region = getRegion();
887 SourceLocation StartLoc = getStart(S);
888
889 handleFileExit(StartLoc);
890 if (!Region.hasStartLoc())
891 Region.setStartLoc(StartLoc);
892 }
893
894 /// Mark \c S as a terminator, starting a zero region.
895 void terminateRegion(const Stmt *S) {
896 extendRegion(S);
897 SourceMappingRegion &Region = getRegion();
898 SourceLocation EndLoc = getEnd(S);
899 if (!Region.hasEndLoc())
900 Region.setEndLoc(EndLoc);
901 pushRegion(Counter::getZero());
902 HasTerminateStmt = true;
903 }
904
905 /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
906 std::optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
907 SourceLocation BeforeLoc) {
908 // If AfterLoc is in function-like macro, use the right parenthesis
909 // location.
910 if (AfterLoc.isMacroID()) {
911 FileID FID = SM.getFileID(AfterLoc);
912 const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
913 if (EI->isFunctionMacroExpansion())
914 AfterLoc = EI->getExpansionLocEnd();
915 }
916
917 size_t StartDepth = locationDepth(AfterLoc);
918 size_t EndDepth = locationDepth(BeforeLoc);
919 while (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) {
920 bool UnnestStart = StartDepth >= EndDepth;
921 bool UnnestEnd = EndDepth >= StartDepth;
922 if (UnnestEnd) {
923 assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
924 BeforeLoc));
925
926 BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
927 assert(BeforeLoc.isValid());
928 EndDepth--;
929 }
930 if (UnnestStart) {
931 assert(SM.isWrittenInSameFile(AfterLoc,
932 getEndOfFileOrMacro(AfterLoc)));
933
934 AfterLoc = getIncludeOrExpansionLoc(AfterLoc);
935 assert(AfterLoc.isValid());
936 AfterLoc = getPreciseTokenLocEnd(AfterLoc);
937 assert(AfterLoc.isValid());
938 StartDepth--;
939 }
940 }
941 AfterLoc = getPreciseTokenLocEnd(AfterLoc);
942 // If the start and end locations of the gap are both within the same macro
943 // file, the range may not be in source order.
944 if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
945 return std::nullopt;
946 if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc) ||
947 !SpellingRegion(SM, AfterLoc, BeforeLoc).isInSourceOrder())
948 return std::nullopt;
949 return {{AfterLoc, BeforeLoc}};
950 }
951
952 /// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
953 void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
954 Counter Count) {
955 if (StartLoc == EndLoc)
956 return;
957 assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
958 handleFileExit(StartLoc);
959 size_t Index = pushRegion(Count, StartLoc, EndLoc);
960 getRegion().setGap(true);
961 handleFileExit(EndLoc);
962 popRegions(Index);
963 }
964
965 /// Keep counts of breaks and continues inside loops.
966 struct BreakContinue {
967 Counter BreakCount;
968 Counter ContinueCount;
969 };
970 SmallVector<BreakContinue, 8> BreakContinueStack;
971
972 CounterCoverageMappingBuilder(
974 llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
975 const LangOptions &LangOpts)
976 : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap) {}
977
978 /// Write the mapping data to the output stream
979 void write(llvm::raw_ostream &OS) {
980 llvm::SmallVector<unsigned, 8> VirtualFileMapping;
981 gatherFileIDs(VirtualFileMapping);
982 SourceRegionFilter Filter = emitExpansionRegions();
983 emitSourceRegions(Filter);
984 gatherSkippedRegions();
985
986 if (MappingRegions.empty())
987 return;
988
989 CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
990 MappingRegions);
991 Writer.write(OS);
992 }
993
994 void VisitStmt(const Stmt *S) {
995 if (S->getBeginLoc().isValid())
996 extendRegion(S);
997 const Stmt *LastStmt = nullptr;
998 bool SaveTerminateStmt = HasTerminateStmt;
999 HasTerminateStmt = false;
1000 GapRegionCounter = Counter::getZero();
1001 for (const Stmt *Child : S->children())
1002 if (Child) {
1003 // If last statement contains terminate statements, add a gap area
1004 // between the two statements. Skipping attributed statements, because
1005 // they don't have valid start location.
1006 if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
1007 auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
1008 if (Gap)
1009 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
1010 GapRegionCounter);
1011 SaveTerminateStmt = true;
1012 HasTerminateStmt = false;
1013 }
1014 this->Visit(Child);
1015 LastStmt = Child;
1016 }
1017 if (SaveTerminateStmt)
1018 HasTerminateStmt = true;
1019 handleFileExit(getEnd(S));
1020 }
1021
1022 void VisitDecl(const Decl *D) {
1023 Stmt *Body = D->getBody();
1024
1025 // Do not propagate region counts into system headers unless collecting
1026 // coverage from system headers is explicitly enabled.
1027 if (!SystemHeadersCoverage && Body &&
1028 SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
1029 return;
1030
1031 // Do not visit the artificial children nodes of defaulted methods. The
1032 // lexer may not be able to report back precise token end locations for
1033 // these children nodes (llvm.org/PR39822), and moreover users will not be
1034 // able to see coverage for them.
1035 Counter BodyCounter = getRegionCounter(Body);
1036 bool Defaulted = false;
1037 if (auto *Method = dyn_cast<CXXMethodDecl>(D))
1038 Defaulted = Method->isDefaulted();
1039 if (auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
1040 for (auto *Initializer : Ctor->inits()) {
1041 if (Initializer->isWritten()) {
1042 auto *Init = Initializer->getInit();
1043 if (getStart(Init).isValid() && getEnd(Init).isValid())
1044 propagateCounts(BodyCounter, Init);
1045 }
1046 }
1047 }
1048
1049 propagateCounts(BodyCounter, Body,
1050 /*VisitChildren=*/!Defaulted);
1051 assert(RegionStack.empty() && "Regions entered but never exited");
1052 }
1053
1054 void VisitReturnStmt(const ReturnStmt *S) {
1055 extendRegion(S);
1056 if (S->getRetValue())
1057 Visit(S->getRetValue());
1058 terminateRegion(S);
1059 }
1060
1061 void VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) {
1062 extendRegion(S);
1063 Visit(S->getBody());
1064 }
1065
1066 void VisitCoreturnStmt(const CoreturnStmt *S) {
1067 extendRegion(S);
1068 if (S->getOperand())
1069 Visit(S->getOperand());
1070 terminateRegion(S);
1071 }
1072
1073 void VisitCXXThrowExpr(const CXXThrowExpr *E) {
1074 extendRegion(E);
1075 if (E->getSubExpr())
1076 Visit(E->getSubExpr());
1077 terminateRegion(E);
1078 }
1079
1080 void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
1081
1082 void VisitLabelStmt(const LabelStmt *S) {
1083 Counter LabelCount = getRegionCounter(S);
1084 SourceLocation Start = getStart(S);
1085 // We can't extendRegion here or we risk overlapping with our new region.
1086 handleFileExit(Start);
1087 pushRegion(LabelCount, Start);
1088 Visit(S->getSubStmt());
1089 }
1090
1091 void VisitBreakStmt(const BreakStmt *S) {
1092 assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
1093 BreakContinueStack.back().BreakCount = addCounters(
1094 BreakContinueStack.back().BreakCount, getRegion().getCounter());
1095 // FIXME: a break in a switch should terminate regions for all preceding
1096 // case statements, not just the most recent one.
1097 terminateRegion(S);
1098 }
1099
1100 void VisitContinueStmt(const ContinueStmt *S) {
1101 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
1102 BreakContinueStack.back().ContinueCount = addCounters(
1103 BreakContinueStack.back().ContinueCount, getRegion().getCounter());
1104 terminateRegion(S);
1105 }
1106
1107 void VisitCallExpr(const CallExpr *E) {
1108 VisitStmt(E);
1109
1110 // Terminate the region when we hit a noreturn function.
1111 // (This is helpful dealing with switch statements.)
1112 QualType CalleeType = E->getCallee()->getType();
1113 if (getFunctionExtInfo(*CalleeType).getNoReturn())
1114 terminateRegion(E);
1115 }
1116
1117 void VisitWhileStmt(const WhileStmt *S) {
1118 extendRegion(S);
1119
1120 Counter ParentCount = getRegion().getCounter();
1121 Counter BodyCount = getRegionCounter(S);
1122
1123 // Handle the body first so that we can get the backedge count.
1124 BreakContinueStack.push_back(BreakContinue());
1125 extendRegion(S->getBody());
1126 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1127 BreakContinue BC = BreakContinueStack.pop_back_val();
1128
1129 bool BodyHasTerminateStmt = HasTerminateStmt;
1130 HasTerminateStmt = false;
1131
1132 // Go back to handle the condition.
1133 Counter CondCount =
1134 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1135 propagateCounts(CondCount, S->getCond());
1136 adjustForOutOfOrderTraversal(getEnd(S));
1137
1138 // The body count applies to the area immediately after the increment.
1139 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1140 if (Gap)
1141 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1142
1143 Counter OutCount =
1144 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1145 if (OutCount != ParentCount) {
1146 pushRegion(OutCount);
1147 GapRegionCounter = OutCount;
1148 if (BodyHasTerminateStmt)
1149 HasTerminateStmt = true;
1150 }
1151
1152 // Create Branch Region around condition.
1153 createBranchRegion(S->getCond(), BodyCount,
1154 subtractCounters(CondCount, BodyCount));
1155 }
1156
1157 void VisitDoStmt(const DoStmt *S) {
1158 extendRegion(S);
1159
1160 Counter ParentCount = getRegion().getCounter();
1161 Counter BodyCount = getRegionCounter(S);
1162
1163 BreakContinueStack.push_back(BreakContinue());
1164 extendRegion(S->getBody());
1165 Counter BackedgeCount =
1166 propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
1167 BreakContinue BC = BreakContinueStack.pop_back_val();
1168
1169 bool BodyHasTerminateStmt = HasTerminateStmt;
1170 HasTerminateStmt = false;
1171
1172 Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
1173 propagateCounts(CondCount, S->getCond());
1174
1175 Counter OutCount =
1176 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1177 if (OutCount != ParentCount) {
1178 pushRegion(OutCount);
1179 GapRegionCounter = OutCount;
1180 }
1181
1182 // Create Branch Region around condition.
1183 createBranchRegion(S->getCond(), BodyCount,
1184 subtractCounters(CondCount, BodyCount));
1185
1186 if (BodyHasTerminateStmt)
1187 HasTerminateStmt = true;
1188 }
1189
1190 void VisitForStmt(const ForStmt *S) {
1191 extendRegion(S);
1192 if (S->getInit())
1193 Visit(S->getInit());
1194
1195 Counter ParentCount = getRegion().getCounter();
1196 Counter BodyCount = getRegionCounter(S);
1197
1198 // The loop increment may contain a break or continue.
1199 if (S->getInc())
1200 BreakContinueStack.emplace_back();
1201
1202 // Handle the body first so that we can get the backedge count.
1203 BreakContinueStack.emplace_back();
1204 extendRegion(S->getBody());
1205 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1206 BreakContinue BodyBC = BreakContinueStack.pop_back_val();
1207
1208 bool BodyHasTerminateStmt = HasTerminateStmt;
1209 HasTerminateStmt = false;
1210
1211 // The increment is essentially part of the body but it needs to include
1212 // the count for all the continue statements.
1213 BreakContinue IncrementBC;
1214 if (const Stmt *Inc = S->getInc()) {
1215 propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
1216 IncrementBC = BreakContinueStack.pop_back_val();
1217 }
1218
1219 // Go back to handle the condition.
1220 Counter CondCount = addCounters(
1221 addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
1222 IncrementBC.ContinueCount);
1223 if (const Expr *Cond = S->getCond()) {
1224 propagateCounts(CondCount, Cond);
1225 adjustForOutOfOrderTraversal(getEnd(S));
1226 }
1227
1228 // The body count applies to the area immediately after the increment.
1229 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1230 if (Gap)
1231 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1232
1233 Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
1234 subtractCounters(CondCount, BodyCount));
1235 if (OutCount != ParentCount) {
1236 pushRegion(OutCount);
1237 GapRegionCounter = OutCount;
1238 if (BodyHasTerminateStmt)
1239 HasTerminateStmt = true;
1240 }
1241
1242 // Create Branch Region around condition.
1243 createBranchRegion(S->getCond(), BodyCount,
1244 subtractCounters(CondCount, BodyCount));
1245 }
1246
1247 void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
1248 extendRegion(S);
1249 if (S->getInit())
1250 Visit(S->getInit());
1251 Visit(S->getLoopVarStmt());
1252 Visit(S->getRangeStmt());
1253
1254 Counter ParentCount = getRegion().getCounter();
1255 Counter BodyCount = getRegionCounter(S);
1256
1257 BreakContinueStack.push_back(BreakContinue());
1258 extendRegion(S->getBody());
1259 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1260 BreakContinue BC = BreakContinueStack.pop_back_val();
1261
1262 bool BodyHasTerminateStmt = HasTerminateStmt;
1263 HasTerminateStmt = false;
1264
1265 // The body count applies to the area immediately after the range.
1266 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1267 if (Gap)
1268 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1269
1270 Counter LoopCount =
1271 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1272 Counter OutCount =
1273 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1274 if (OutCount != ParentCount) {
1275 pushRegion(OutCount);
1276 GapRegionCounter = OutCount;
1277 if (BodyHasTerminateStmt)
1278 HasTerminateStmt = true;
1279 }
1280
1281 // Create Branch Region around condition.
1282 createBranchRegion(S->getCond(), BodyCount,
1283 subtractCounters(LoopCount, BodyCount));
1284 }
1285
1286 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
1287 extendRegion(S);
1288 Visit(S->getElement());
1289
1290 Counter ParentCount = getRegion().getCounter();
1291 Counter BodyCount = getRegionCounter(S);
1292
1293 BreakContinueStack.push_back(BreakContinue());
1294 extendRegion(S->getBody());
1295 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1296 BreakContinue BC = BreakContinueStack.pop_back_val();
1297
1298 // The body count applies to the area immediately after the collection.
1299 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1300 if (Gap)
1301 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1302
1303 Counter LoopCount =
1304 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1305 Counter OutCount =
1306 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1307 if (OutCount != ParentCount) {
1308 pushRegion(OutCount);
1309 GapRegionCounter = OutCount;
1310 }
1311 }
1312
1313 void VisitSwitchStmt(const SwitchStmt *S) {
1314 extendRegion(S);
1315 if (S->getInit())
1316 Visit(S->getInit());
1317 Visit(S->getCond());
1318
1319 BreakContinueStack.push_back(BreakContinue());
1320
1321 const Stmt *Body = S->getBody();
1322 extendRegion(Body);
1323 if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
1324 if (!CS->body_empty()) {
1325 // Make a region for the body of the switch. If the body starts with
1326 // a case, that case will reuse this region; otherwise, this covers
1327 // the unreachable code at the beginning of the switch body.
1328 size_t Index = pushRegion(Counter::getZero(), getStart(CS));
1329 getRegion().setGap(true);
1330 Visit(Body);
1331
1332 // Set the end for the body of the switch, if it isn't already set.
1333 for (size_t i = RegionStack.size(); i != Index; --i) {
1334 if (!RegionStack[i - 1].hasEndLoc())
1335 RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
1336 }
1337
1338 popRegions(Index);
1339 }
1340 } else
1341 propagateCounts(Counter::getZero(), Body);
1342 BreakContinue BC = BreakContinueStack.pop_back_val();
1343
1344 if (!BreakContinueStack.empty())
1345 BreakContinueStack.back().ContinueCount = addCounters(
1346 BreakContinueStack.back().ContinueCount, BC.ContinueCount);
1347
1348 Counter ParentCount = getRegion().getCounter();
1349 Counter ExitCount = getRegionCounter(S);
1350 SourceLocation ExitLoc = getEnd(S);
1351 pushRegion(ExitCount);
1352 GapRegionCounter = ExitCount;
1353
1354 // Ensure that handleFileExit recognizes when the end location is located
1355 // in a different file.
1356 MostRecentLocation = getStart(S);
1357 handleFileExit(ExitLoc);
1358
1359 // Create a Branch Region around each Case. Subtract the case's
1360 // counter from the Parent counter to track the "False" branch count.
1361 Counter CaseCountSum;
1362 bool HasDefaultCase = false;
1363 const SwitchCase *Case = S->getSwitchCaseList();
1364 for (; Case; Case = Case->getNextSwitchCase()) {
1365 HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
1366 CaseCountSum =
1367 addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false);
1368 createSwitchCaseRegion(
1369 Case, getRegionCounter(Case),
1370 subtractCounters(ParentCount, getRegionCounter(Case)));
1371 }
1372 // Simplify is skipped while building the counters above: it can get really
1373 // slow on top of switches with thousands of cases. Instead, trigger
1374 // simplification by adding zero to the last counter.
1375 CaseCountSum = addCounters(CaseCountSum, Counter::getZero());
1376
1377 // If no explicit default case exists, create a branch region to represent
1378 // the hidden branch, which will be added later by the CodeGen. This region
1379 // will be associated with the switch statement's condition.
1380 if (!HasDefaultCase) {
1381 Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum);
1382 Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue);
1383 createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse);
1384 }
1385 }
1386
1387 void VisitSwitchCase(const SwitchCase *S) {
1388 extendRegion(S);
1389
1390 SourceMappingRegion &Parent = getRegion();
1391
1392 Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
1393 // Reuse the existing region if it starts at our label. This is typical of
1394 // the first case in a switch.
1395 if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
1396 Parent.setCounter(Count);
1397 else
1398 pushRegion(Count, getStart(S));
1399
1400 GapRegionCounter = Count;
1401
1402 if (const auto *CS = dyn_cast<CaseStmt>(S)) {
1403 Visit(CS->getLHS());
1404 if (const Expr *RHS = CS->getRHS())
1405 Visit(RHS);
1406 }
1407 Visit(S->getSubStmt());
1408 }
1409
1410 void VisitIfStmt(const IfStmt *S) {
1411 extendRegion(S);
1412 if (S->getInit())
1413 Visit(S->getInit());
1414
1415 // Extend into the condition before we propagate through it below - this is
1416 // needed to handle macros that generate the "if" but not the condition.
1417 if (!S->isConsteval())
1418 extendRegion(S->getCond());
1419
1420 Counter ParentCount = getRegion().getCounter();
1421 Counter ThenCount = getRegionCounter(S);
1422
1423 if (!S->isConsteval()) {
1424 // Emitting a counter for the condition makes it easier to interpret the
1425 // counter for the body when looking at the coverage.
1426 propagateCounts(ParentCount, S->getCond());
1427
1428 // The 'then' count applies to the area immediately after the condition.
1429 std::optional<SourceRange> Gap =
1430 findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
1431 if (Gap)
1432 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
1433 }
1434
1435 extendRegion(S->getThen());
1436 Counter OutCount = propagateCounts(ThenCount, S->getThen());
1437
1438 Counter ElseCount = subtractCounters(ParentCount, ThenCount);
1439 if (const Stmt *Else = S->getElse()) {
1440 bool ThenHasTerminateStmt = HasTerminateStmt;
1441 HasTerminateStmt = false;
1442 // The 'else' count applies to the area immediately after the 'then'.
1443 std::optional<SourceRange> Gap =
1444 findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
1445 if (Gap)
1446 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
1447 extendRegion(Else);
1448 OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1449
1450 if (ThenHasTerminateStmt)
1451 HasTerminateStmt = true;
1452 } else
1453 OutCount = addCounters(OutCount, ElseCount);
1454
1455 if (OutCount != ParentCount) {
1456 pushRegion(OutCount);
1457 GapRegionCounter = OutCount;
1458 }
1459
1460 if (!S->isConsteval()) {
1461 // Create Branch Region around condition.
1462 createBranchRegion(S->getCond(), ThenCount,
1463 subtractCounters(ParentCount, ThenCount));
1464 }
1465 }
1466
1467 void VisitCXXTryStmt(const CXXTryStmt *S) {
1468 extendRegion(S);
1469 // Handle macros that generate the "try" but not the rest.
1470 extendRegion(S->getTryBlock());
1471
1472 Counter ParentCount = getRegion().getCounter();
1473 propagateCounts(ParentCount, S->getTryBlock());
1474
1475 for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
1476 Visit(S->getHandler(I));
1477
1478 Counter ExitCount = getRegionCounter(S);
1479 pushRegion(ExitCount);
1480 }
1481
1482 void VisitCXXCatchStmt(const CXXCatchStmt *S) {
1483 propagateCounts(getRegionCounter(S), S->getHandlerBlock());
1484 }
1485
1486 void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
1487 extendRegion(E);
1488
1489 Counter ParentCount = getRegion().getCounter();
1490 Counter TrueCount = getRegionCounter(E);
1491
1492 propagateCounts(ParentCount, E->getCond());
1493 Counter OutCount;
1494
1495 if (!isa<BinaryConditionalOperator>(E)) {
1496 // The 'then' count applies to the area immediately after the condition.
1497 auto Gap =
1498 findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
1499 if (Gap)
1500 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
1501
1502 extendRegion(E->getTrueExpr());
1503 OutCount = propagateCounts(TrueCount, E->getTrueExpr());
1504 }
1505
1506 extendRegion(E->getFalseExpr());
1507 OutCount = addCounters(
1508 OutCount, propagateCounts(subtractCounters(ParentCount, TrueCount),
1509 E->getFalseExpr()));
1510
1511 if (OutCount != ParentCount) {
1512 pushRegion(OutCount);
1513 GapRegionCounter = OutCount;
1514 }
1515
1516 // Create Branch Region around condition.
1517 createBranchRegion(E->getCond(), TrueCount,
1518 subtractCounters(ParentCount, TrueCount));
1519 }
1520
1521 void VisitBinLAnd(const BinaryOperator *E) {
1522 extendRegion(E->getLHS());
1523 propagateCounts(getRegion().getCounter(), E->getLHS());
1524 handleFileExit(getEnd(E->getLHS()));
1525
1526 // Counter tracks the right hand side of a logical and operator.
1527 extendRegion(E->getRHS());
1528 propagateCounts(getRegionCounter(E), E->getRHS());
1529
1530 // Extract the RHS's Execution Counter.
1531 Counter RHSExecCnt = getRegionCounter(E);
1532
1533 // Extract the RHS's "True" Instance Counter.
1534 Counter RHSTrueCnt = getRegionCounter(E->getRHS());
1535
1536 // Extract the Parent Region Counter.
1537 Counter ParentCnt = getRegion().getCounter();
1538
1539 // Create Branch Region around LHS condition.
1540 createBranchRegion(E->getLHS(), RHSExecCnt,
1541 subtractCounters(ParentCnt, RHSExecCnt));
1542
1543 // Create Branch Region around RHS condition.
1544 createBranchRegion(E->getRHS(), RHSTrueCnt,
1545 subtractCounters(RHSExecCnt, RHSTrueCnt));
1546 }
1547
1548 // Determine whether the right side of OR operation need to be visited.
1549 bool shouldVisitRHS(const Expr *LHS) {
1550 bool LHSIsTrue = false;
1551 bool LHSIsConst = false;
1552 if (!LHS->isValueDependent())
1553 LHSIsConst = LHS->EvaluateAsBooleanCondition(
1554 LHSIsTrue, CVM.getCodeGenModule().getContext());
1555 return !LHSIsConst || (LHSIsConst && !LHSIsTrue);
1556 }
1557
1558 void VisitBinLOr(const BinaryOperator *E) {
1559 extendRegion(E->getLHS());
1560 Counter OutCount = propagateCounts(getRegion().getCounter(), E->getLHS());
1561 handleFileExit(getEnd(E->getLHS()));
1562
1563 // Counter tracks the right hand side of a logical or operator.
1564 extendRegion(E->getRHS());
1565 propagateCounts(getRegionCounter(E), E->getRHS());
1566
1567 // Extract the RHS's Execution Counter.
1568 Counter RHSExecCnt = getRegionCounter(E);
1569
1570 // Extract the RHS's "False" Instance Counter.
1571 Counter RHSFalseCnt = getRegionCounter(E->getRHS());
1572
1573 if (!shouldVisitRHS(E->getLHS())) {
1574 GapRegionCounter = OutCount;
1575 }
1576
1577 // Extract the Parent Region Counter.
1578 Counter ParentCnt = getRegion().getCounter();
1579
1580 // Create Branch Region around LHS condition.
1581 createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
1582 RHSExecCnt);
1583
1584 // Create Branch Region around RHS condition.
1585 createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
1586 RHSFalseCnt);
1587 }
1588
1589 void VisitLambdaExpr(const LambdaExpr *LE) {
1590 // Lambdas are treated as their own functions for now, so we shouldn't
1591 // propagate counts into them.
1592 }
1593
1594 void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) {
1595 // Just visit syntatic expression as this is what users actually write.
1596 VisitStmt(POE->getSyntacticForm());
1597 }
1598
1599 void VisitOpaqueValueExpr(const OpaqueValueExpr* OVE) {
1600 Visit(OVE->getSourceExpr());
1601 }
1602};
1603
1604} // end anonymous namespace
1605
1606static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
1607 ArrayRef<CounterExpression> Expressions,
1609 OS << FunctionName << ":\n";
1610 CounterMappingContext Ctx(Expressions);
1611 for (const auto &R : Regions) {
1612 OS.indent(2);
1613 switch (R.Kind) {
1614 case CounterMappingRegion::CodeRegion:
1615 break;
1616 case CounterMappingRegion::ExpansionRegion:
1617 OS << "Expansion,";
1618 break;
1619 case CounterMappingRegion::SkippedRegion:
1620 OS << "Skipped,";
1621 break;
1622 case CounterMappingRegion::GapRegion:
1623 OS << "Gap,";
1624 break;
1625 case CounterMappingRegion::BranchRegion:
1626 OS << "Branch,";
1627 break;
1628 }
1629
1630 OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
1631 << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
1632 Ctx.dump(R.Count, OS);
1633
1634 if (R.Kind == CounterMappingRegion::BranchRegion) {
1635 OS << ", ";
1636 Ctx.dump(R.FalseCount, OS);
1637 }
1638
1639 if (R.Kind == CounterMappingRegion::ExpansionRegion)
1640 OS << " (Expanded file = " << R.ExpandedFileID << ")";
1641 OS << "\n";
1642 }
1643}
1644
1646 CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
1647 : CGM(CGM), SourceInfo(SourceInfo) {}
1648
1649std::string CoverageMappingModuleGen::getCurrentDirname() {
1650 if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
1652
1653 SmallString<256> CWD;
1654 llvm::sys::fs::current_path(CWD);
1655 return CWD.str().str();
1656}
1657
1658std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
1660 llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
1661
1662 /// Traverse coverage prefix map in reverse order because prefix replacements
1663 /// are applied in reverse order starting from the last one when multiple
1664 /// prefix replacement options are provided.
1665 for (const auto &[From, To] :
1666 llvm::reverse(CGM.getCodeGenOpts().CoveragePrefixMap)) {
1667 if (llvm::sys::path::replace_path_prefix(Path, From, To))
1668 break;
1669 }
1670 return Path.str().str();
1671}
1672
1673static std::string getInstrProfSection(const CodeGenModule &CGM,
1674 llvm::InstrProfSectKind SK) {
1675 return llvm::getInstrProfSectionName(
1676 SK, CGM.getContext().getTargetInfo().getTriple().getObjectFormat());
1677}
1678
1679void CoverageMappingModuleGen::emitFunctionMappingRecord(
1680 const FunctionInfo &Info, uint64_t FilenamesRef) {
1681 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1682
1683 // Assign a name to the function record. This is used to merge duplicates.
1684 std::string FuncRecordName = "__covrec_" + llvm::utohexstr(Info.NameHash);
1685
1686 // A dummy description for a function included-but-not-used in a TU can be
1687 // replaced by full description provided by a different TU. The two kinds of
1688 // descriptions play distinct roles: therefore, assign them different names
1689 // to prevent `linkonce_odr` merging.
1690 if (Info.IsUsed)
1691 FuncRecordName += "u";
1692
1693 // Create the function record type.
1694 const uint64_t NameHash = Info.NameHash;
1695 const uint64_t FuncHash = Info.FuncHash;
1696 const std::string &CoverageMapping = Info.CoverageMapping;
1697#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
1698 llvm::Type *FunctionRecordTypes[] = {
1699#include "llvm/ProfileData/InstrProfData.inc"
1700 };
1701 auto *FunctionRecordTy =
1702 llvm::StructType::get(Ctx, ArrayRef(FunctionRecordTypes),
1703 /*isPacked=*/true);
1704
1705 // Create the function record constant.
1706#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
1707 llvm::Constant *FunctionRecordVals[] = {
1708 #include "llvm/ProfileData/InstrProfData.inc"
1709 };
1710 auto *FuncRecordConstant =
1711 llvm::ConstantStruct::get(FunctionRecordTy, ArrayRef(FunctionRecordVals));
1712
1713 // Create the function record global.
1714 auto *FuncRecord = new llvm::GlobalVariable(
1715 CGM.getModule(), FunctionRecordTy, /*isConstant=*/true,
1716 llvm::GlobalValue::LinkOnceODRLinkage, FuncRecordConstant,
1717 FuncRecordName);
1718 FuncRecord->setVisibility(llvm::GlobalValue::HiddenVisibility);
1719 FuncRecord->setSection(getInstrProfSection(CGM, llvm::IPSK_covfun));
1720 FuncRecord->setAlignment(llvm::Align(8));
1721 if (CGM.supportsCOMDAT())
1722 FuncRecord->setComdat(CGM.getModule().getOrInsertComdat(FuncRecordName));
1723
1724 // Make sure the data doesn't get deleted.
1725 CGM.addUsedGlobal(FuncRecord);
1726}
1727
1729 llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
1730 const std::string &CoverageMapping, bool IsUsed) {
1731 const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue);
1732 FunctionRecords.push_back({NameHash, FuncHash, CoverageMapping, IsUsed});
1733
1734 if (!IsUsed)
1735 FunctionNames.push_back(NamePtr);
1736
1737 if (CGM.getCodeGenOpts().DumpCoverageMapping) {
1738 // Dump the coverage mapping data for this function by decoding the
1739 // encoded data. This allows us to dump the mapping regions which were
1740 // also processed by the CoverageMappingWriter which performs
1741 // additional minimization operations such as reducing the number of
1742 // expressions.
1744 std::vector<StringRef> Filenames;
1745 std::vector<CounterExpression> Expressions;
1746 std::vector<CounterMappingRegion> Regions;
1747 FilenameStrs.resize(FileEntries.size() + 1);
1748 FilenameStrs[0] = normalizeFilename(getCurrentDirname());
1749 for (const auto &Entry : FileEntries) {
1750 auto I = Entry.second;
1751 FilenameStrs[I] = normalizeFilename(Entry.first.getName());
1752 }
1753 ArrayRef<std::string> FilenameRefs = llvm::ArrayRef(FilenameStrs);
1754 RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
1755 Expressions, Regions);
1756 if (Reader.read())
1757 return;
1758 dump(llvm::outs(), NameValue, Expressions, Regions);
1759 }
1760}
1761
1763 if (FunctionRecords.empty())
1764 return;
1765 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1766 auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
1767
1768 // Create the filenames and merge them with coverage mappings
1770 FilenameStrs.resize(FileEntries.size() + 1);
1771 // The first filename is the current working directory.
1772 FilenameStrs[0] = normalizeFilename(getCurrentDirname());
1773 for (const auto &Entry : FileEntries) {
1774 auto I = Entry.second;
1775 FilenameStrs[I] = normalizeFilename(Entry.first.getName());
1776 }
1777
1778 std::string Filenames;
1779 {
1780 llvm::raw_string_ostream OS(Filenames);
1781 CoverageFilenamesSectionWriter(FilenameStrs).write(OS);
1782 }
1783 auto *FilenamesVal =
1784 llvm::ConstantDataArray::getString(Ctx, Filenames, false);
1785 const int64_t FilenamesRef = llvm::IndexedInstrProf::ComputeHash(Filenames);
1786
1787 // Emit the function records.
1788 for (const FunctionInfo &Info : FunctionRecords)
1789 emitFunctionMappingRecord(Info, FilenamesRef);
1790
1791 const unsigned NRecords = 0;
1792 const size_t FilenamesSize = Filenames.size();
1793 const unsigned CoverageMappingSize = 0;
1794 llvm::Type *CovDataHeaderTypes[] = {
1795#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
1796#include "llvm/ProfileData/InstrProfData.inc"
1797 };
1798 auto CovDataHeaderTy =
1799 llvm::StructType::get(Ctx, ArrayRef(CovDataHeaderTypes));
1800 llvm::Constant *CovDataHeaderVals[] = {
1801#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
1802#include "llvm/ProfileData/InstrProfData.inc"
1803 };
1804 auto CovDataHeaderVal =
1805 llvm::ConstantStruct::get(CovDataHeaderTy, ArrayRef(CovDataHeaderVals));
1806
1807 // Create the coverage data record
1808 llvm::Type *CovDataTypes[] = {CovDataHeaderTy, FilenamesVal->getType()};
1809 auto CovDataTy = llvm::StructType::get(Ctx, ArrayRef(CovDataTypes));
1810 llvm::Constant *TUDataVals[] = {CovDataHeaderVal, FilenamesVal};
1811 auto CovDataVal = llvm::ConstantStruct::get(CovDataTy, ArrayRef(TUDataVals));
1812 auto CovData = new llvm::GlobalVariable(
1813 CGM.getModule(), CovDataTy, true, llvm::GlobalValue::PrivateLinkage,
1814 CovDataVal, llvm::getCoverageMappingVarName());
1815
1816 CovData->setSection(getInstrProfSection(CGM, llvm::IPSK_covmap));
1817 CovData->setAlignment(llvm::Align(8));
1818
1819 // Make sure the data doesn't get deleted.
1820 CGM.addUsedGlobal(CovData);
1821 // Create the deferred function records array
1822 if (!FunctionNames.empty()) {
1823 auto NamesArrTy = llvm::ArrayType::get(llvm::PointerType::getUnqual(Ctx),
1824 FunctionNames.size());
1825 auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
1826 // This variable will *NOT* be emitted to the object file. It is used
1827 // to pass the list of names referenced to codegen.
1828 new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
1829 llvm::GlobalValue::InternalLinkage, NamesArrVal,
1830 llvm::getCoverageUnusedNamesVarName());
1831 }
1832}
1833
1835 auto It = FileEntries.find(File);
1836 if (It != FileEntries.end())
1837 return It->second;
1838 unsigned FileID = FileEntries.size() + 1;
1839 FileEntries.insert(std::make_pair(File, FileID));
1840 return FileID;
1841}
1842
1844 llvm::raw_ostream &OS) {
1845 assert(CounterMap);
1846 CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts);
1847 Walker.VisitDecl(D);
1848 Walker.write(OS);
1849}
1850
1852 llvm::raw_ostream &OS) {
1853 EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
1854 Walker.VisitDecl(D);
1855 Walker.write(OS);
1856}
NodeId Parent
Definition: ASTDiff.cpp:191
#define SM(sm)
Definition: Cuda.cpp:80
Defines the Diagnostic-related interfaces.
static std::string getInstrProfSection(const CodeGenModule &CGM, llvm::InstrProfSectKind SK)
static llvm::cl::opt< bool > SystemHeadersCoverage("system-headers-coverage", llvm::cl::desc("Enable collecting coverage from system headers"), llvm::cl::init(false), llvm::cl::Hidden)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
static llvm::cl::opt< bool > EmptyLineCommentCoverage("emptyline-comment-coverage", llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only " "disable it on test)"), llvm::cl::init(true), llvm::cl::Hidden)
Defines the clang::FileManager interface and associated types.
StringRef Filename
Definition: Format.cpp:2976
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:142
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:749
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition: Expr.h:4163
Expr * getCond() const
getCond - Return the expression representing the condition for the ?: operator.
Definition: Expr.h:4341
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition: Expr.h:4347
SourceLocation getQuestionLoc() const
Definition: Expr.h:4190
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition: Expr.h:4353
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3862
Expr * getLHS() const
Definition: Expr.h:3911
Expr * getRHS() const
Definition: Expr.h:3913
BreakStmt - This represents a break.
Definition: Stmt.h:2974
CXXCatchStmt - This represents a C++ catch block.
Definition: StmtCXX.h:28
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition: StmtCXX.h:135
A C++ throw-expression (C++ [except.throw]).
Definition: ExprCXX.h:1192
const Expr * getSubExpr() const
Definition: ExprCXX.h:1212
CXXTryStmt - A C++ try block, including all handlers.
Definition: StmtCXX.h:69
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2847
Expr * getCallee()
Definition: Expr.h:2997
llvm::SmallVector< std::pair< std::string, std::string >, 0 > CoveragePrefixMap
Prefix replacement map for source-based code coverage to remap source file paths in coverage mapping.
std::string CoverageCompilationDir
The string to embed in coverage mapping as the current working directory.
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
void addUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.used metadata.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS)
Emit the coverage mapping data for an unused function.
void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS)
Emit the coverage mapping data which maps the regions of code to counters that will be used to find t...
Organizes the cross-function state that is used while generating code coverage mapping data.
void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, StringRef FunctionNameValue, uint64_t FunctionHash, const std::string &CoverageMapping, bool IsUsed=true)
Add a function's coverage mapping record to the collection of the function mapping records.
CoverageSourceInfo & getSourceInfo() const
static CoverageSourceInfo * setUpCoverageCallbacks(Preprocessor &PP)
CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
void emit()
Emit the coverage mapping data for a translation unit.
CodeGenModule & getCodeGenModule()
Return an interface into CodeGenModule.
unsigned getFileID(FileEntryRef File)
Return the coverage mapping translation unit file id for the given file.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:194
ContinueStmt - This represents a continue.
Definition: Stmt.h:2944
Represents a 'co_return' statement in the C++ Coroutines TS.
Definition: StmtCXX.h:473
Represents the body of a coroutine.
Definition: StmtCXX.h:320
Stores additional source code information like skipped ranges which is required by the coverage mappi...
void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override
Hook called when a source range is skipped.
void updateNextTokLoc(SourceLocation Loc)
void AddSkippedRange(SourceRange Range, SkippedRange::Kind RangeKind)
std::vector< SkippedRange > & getSkippedRanges()
bool HandleComment(Preprocessor &PP, SourceRange Range) override
void HandleEmptyline(SourceRange Range) override
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:85
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:1076
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
Definition: DeclBase.h:1082
DoStmt - This represents a 'do/while' stmt.
Definition: Stmt.h:2719
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:169
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
QualType getType() const
Definition: Expr.h:142
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Definition: FileEntry.h:57
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2775
bool getNoReturn() const
Definition: Type.h:3953
GotoStmt - This represents a direct goto.
Definition: Stmt.h:2856
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2132
LabelStmt - Represents a label, which has a substatement.
Definition: Stmt.h:2025
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Definition: ExprCXX.h:1938
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:83
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Definition: Lexer.cpp:454
Represents Objective-C's collection statement.
Definition: StmtObjC.h:23
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1156
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition: Expr.h:1206
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:128
void addCommentHandler(CommentHandler *Handler)
Add the specified comment handler to the preprocessor.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
SourceManager & getSourceManager() const
void setPreprocessToken(bool Preprocess)
void setTokenWatcher(llvm::unique_function< void(const clang::Token &)> F)
Register a function that would be called on each token in the final expanded token stream.
void setEmptylineHandler(EmptylineHandler *Handler)
Set empty line handler.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition: Expr.h:6316
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
Definition: Expr.h:6358
A (possibly-)qualified type.
Definition: Type.h:736
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3013
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
bool isFunctionMacroExpansion() const
SourceLocation getExpansionLocEnd() const
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceLocation getColonLoc() const
Definition: Stmt.h:1774
const SwitchCase * getNextSwitchCase() const
Definition: Stmt.h:1768
SwitchStmt - This represents a 'switch' stmt.
Definition: Stmt.h:2382
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1218
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition: Token.h:131
tok::TokenKind getKind() const
Definition: Token.h:93
WhileStmt - This represents a 'while' stmt.
Definition: Stmt.h:2578
llvm::cl::opt< std::string > Filter
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
Definition: Type.h:6933
unsigned long uint64_t
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:629