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