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 "CodeGenPGO.h"
16 #include "clang/AST/StmtVisitor.h"
17 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Lex/Lexer.h"
19 #include "llvm/ADT/DenseSet.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/Support/FileSystem.h"
26 #include "llvm/Support/Path.h"
27 #include <optional>
28
29 // This selects the coverage mapping format defined when `InstrProfData.inc`
30 // is textually included.
31 #define COVMAP_V3
32
33 namespace llvm {
34 cl::opt<bool>
35 EnableSingleByteCoverage("enable-single-byte-coverage",
36 llvm::cl::ZeroOrMore,
37 llvm::cl::desc("Enable single byte coverage"),
38 llvm::cl::Hidden, llvm::cl::init(false));
39 } // namespace llvm
40
41 static llvm::cl::opt<bool> EmptyLineCommentCoverage(
42 "emptyline-comment-coverage",
43 llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only "
44 "disable it on test)"),
45 llvm::cl::init(true), llvm::cl::Hidden);
46
47 namespace llvm::coverage {
48 cl::opt<bool> SystemHeadersCoverage(
49 "system-headers-coverage",
50 cl::desc("Enable collecting coverage from system headers"), cl::init(false),
51 cl::Hidden);
52 }
53
54 using namespace clang;
55 using namespace CodeGen;
56 using namespace llvm::coverage;
57
58 CoverageSourceInfo *
setUpCoverageCallbacks(Preprocessor & PP)59 CoverageMappingModuleGen::setUpCoverageCallbacks(Preprocessor &PP) {
60 CoverageSourceInfo *CoverageInfo =
61 new CoverageSourceInfo(PP.getSourceManager());
62 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(CoverageInfo));
63 if (EmptyLineCommentCoverage) {
64 PP.addCommentHandler(CoverageInfo);
65 PP.setEmptylineHandler(CoverageInfo);
66 PP.setPreprocessToken(true);
67 PP.setTokenWatcher([CoverageInfo](clang::Token Tok) {
68 // Update previous token location.
69 CoverageInfo->PrevTokLoc = Tok.getLocation();
70 if (Tok.getKind() != clang::tok::eod)
71 CoverageInfo->updateNextTokLoc(Tok.getLocation());
72 });
73 }
74 return CoverageInfo;
75 }
76
AddSkippedRange(SourceRange Range,SkippedRange::Kind RangeKind)77 void CoverageSourceInfo::AddSkippedRange(SourceRange Range,
78 SkippedRange::Kind RangeKind) {
79 if (EmptyLineCommentCoverage && !SkippedRanges.empty() &&
80 PrevTokLoc == SkippedRanges.back().PrevTokLoc &&
81 SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(),
82 Range.getBegin()))
83 SkippedRanges.back().Range.setEnd(Range.getEnd());
84 else
85 SkippedRanges.push_back({Range, RangeKind, PrevTokLoc});
86 }
87
SourceRangeSkipped(SourceRange Range,SourceLocation)88 void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
89 AddSkippedRange(Range, SkippedRange::PPIfElse);
90 }
91
HandleEmptyline(SourceRange Range)92 void CoverageSourceInfo::HandleEmptyline(SourceRange Range) {
93 AddSkippedRange(Range, SkippedRange::EmptyLine);
94 }
95
HandleComment(Preprocessor & PP,SourceRange Range)96 bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) {
97 AddSkippedRange(Range, SkippedRange::Comment);
98 return false;
99 }
100
updateNextTokLoc(SourceLocation Loc)101 void CoverageSourceInfo::updateNextTokLoc(SourceLocation Loc) {
102 if (!SkippedRanges.empty() && SkippedRanges.back().NextTokLoc.isInvalid())
103 SkippedRanges.back().NextTokLoc = Loc;
104 }
105
106 namespace {
107 /// A region of source code that can be mapped to a counter.
108 class SourceMappingRegion {
109 /// Primary Counter that is also used for Branch Regions for "True" branches.
110 Counter Count;
111
112 /// Secondary Counter used for Branch Regions for "False" branches.
113 std::optional<Counter> FalseCount;
114
115 /// Parameters used for Modified Condition/Decision Coverage
116 mcdc::Parameters MCDCParams;
117
118 /// The region's starting location.
119 std::optional<SourceLocation> LocStart;
120
121 /// The region's ending location.
122 std::optional<SourceLocation> LocEnd;
123
124 /// Whether this region is a gap region. The count from a gap region is set
125 /// as the line execution count if there are no other regions on the line.
126 bool GapRegion;
127
128 /// Whetever this region is skipped ('if constexpr' or 'if consteval' untaken
129 /// branch, or anything skipped but not empty line / comments)
130 bool SkippedRegion;
131
132 public:
SourceMappingRegion(Counter Count,std::optional<SourceLocation> LocStart,std::optional<SourceLocation> LocEnd,bool GapRegion=false)133 SourceMappingRegion(Counter Count, std::optional<SourceLocation> LocStart,
134 std::optional<SourceLocation> LocEnd,
135 bool GapRegion = false)
136 : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
137 SkippedRegion(false) {}
138
SourceMappingRegion(Counter Count,std::optional<Counter> FalseCount,mcdc::Parameters MCDCParams,std::optional<SourceLocation> LocStart,std::optional<SourceLocation> LocEnd,bool GapRegion=false)139 SourceMappingRegion(Counter Count, std::optional<Counter> FalseCount,
140 mcdc::Parameters MCDCParams,
141 std::optional<SourceLocation> LocStart,
142 std::optional<SourceLocation> LocEnd,
143 bool GapRegion = false)
144 : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams),
145 LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion),
146 SkippedRegion(false) {}
147
SourceMappingRegion(mcdc::Parameters MCDCParams,std::optional<SourceLocation> LocStart,std::optional<SourceLocation> LocEnd)148 SourceMappingRegion(mcdc::Parameters MCDCParams,
149 std::optional<SourceLocation> LocStart,
150 std::optional<SourceLocation> LocEnd)
151 : MCDCParams(MCDCParams), LocStart(LocStart), LocEnd(LocEnd),
152 GapRegion(false), SkippedRegion(false) {}
153
getCounter() const154 const Counter &getCounter() const { return Count; }
155
getFalseCounter() const156 const Counter &getFalseCounter() const {
157 assert(FalseCount && "Region has no alternate counter");
158 return *FalseCount;
159 }
160
setCounter(Counter C)161 void setCounter(Counter C) { Count = C; }
162
hasStartLoc() const163 bool hasStartLoc() const { return LocStart.has_value(); }
164
setStartLoc(SourceLocation Loc)165 void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
166
getBeginLoc() const167 SourceLocation getBeginLoc() const {
168 assert(LocStart && "Region has no start location");
169 return *LocStart;
170 }
171
hasEndLoc() const172 bool hasEndLoc() const { return LocEnd.has_value(); }
173
setEndLoc(SourceLocation Loc)174 void setEndLoc(SourceLocation Loc) {
175 assert(Loc.isValid() && "Setting an invalid end location");
176 LocEnd = Loc;
177 }
178
getEndLoc() const179 SourceLocation getEndLoc() const {
180 assert(LocEnd && "Region has no end location");
181 return *LocEnd;
182 }
183
isGap() const184 bool isGap() const { return GapRegion; }
185
setGap(bool Gap)186 void setGap(bool Gap) { GapRegion = Gap; }
187
isSkipped() const188 bool isSkipped() const { return SkippedRegion; }
189
setSkipped(bool Skipped)190 void setSkipped(bool Skipped) { SkippedRegion = Skipped; }
191
isBranch() const192 bool isBranch() const { return FalseCount.has_value(); }
193
isMCDCBranch() const194 bool isMCDCBranch() const {
195 return std::holds_alternative<mcdc::BranchParameters>(MCDCParams);
196 }
197
getMCDCBranchParams() const198 const auto &getMCDCBranchParams() const {
199 return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
200 }
201
isMCDCDecision() const202 bool isMCDCDecision() const {
203 return std::holds_alternative<mcdc::DecisionParameters>(MCDCParams);
204 }
205
getMCDCDecisionParams() const206 const auto &getMCDCDecisionParams() const {
207 return mcdc::getParams<const mcdc::DecisionParameters>(MCDCParams);
208 }
209
getMCDCParams() const210 const mcdc::Parameters &getMCDCParams() const { return MCDCParams; }
211
resetMCDCParams()212 void resetMCDCParams() { MCDCParams = mcdc::Parameters(); }
213 };
214
215 /// Spelling locations for the start and end of a source region.
216 struct SpellingRegion {
217 /// The line where the region starts.
218 unsigned LineStart;
219
220 /// The column where the region starts.
221 unsigned ColumnStart;
222
223 /// The line where the region ends.
224 unsigned LineEnd;
225
226 /// The column where the region ends.
227 unsigned ColumnEnd;
228
SpellingRegion__anon413222f00211::SpellingRegion229 SpellingRegion(SourceManager &SM, SourceLocation LocStart,
230 SourceLocation LocEnd) {
231 LineStart = SM.getSpellingLineNumber(LocStart);
232 ColumnStart = SM.getSpellingColumnNumber(LocStart);
233 LineEnd = SM.getSpellingLineNumber(LocEnd);
234 ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
235 }
236
SpellingRegion__anon413222f00211::SpellingRegion237 SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
238 : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
239
240 /// Check if the start and end locations appear in source order, i.e
241 /// top->bottom, left->right.
isInSourceOrder__anon413222f00211::SpellingRegion242 bool isInSourceOrder() const {
243 return (LineStart < LineEnd) ||
244 (LineStart == LineEnd && ColumnStart <= ColumnEnd);
245 }
246 };
247
248 /// Provides the common functionality for the different
249 /// coverage mapping region builders.
250 class CoverageMappingBuilder {
251 public:
252 CoverageMappingModuleGen &CVM;
253 SourceManager &SM;
254 const LangOptions &LangOpts;
255
256 private:
257 /// Map of clang's FileIDs to IDs used for coverage mapping.
258 llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
259 FileIDMapping;
260
261 public:
262 /// The coverage mapping regions for this function
263 llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
264 /// The source mapping regions for this function.
265 std::vector<SourceMappingRegion> SourceRegions;
266
267 /// A set of regions which can be used as a filter.
268 ///
269 /// It is produced by emitExpansionRegions() and is used in
270 /// emitSourceRegions() to suppress producing code regions if
271 /// the same area is covered by expansion regions.
272 typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
273 SourceRegionFilter;
274
CoverageMappingBuilder(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts)275 CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
276 const LangOptions &LangOpts)
277 : CVM(CVM), SM(SM), LangOpts(LangOpts) {}
278
279 /// Return the precise end location for the given token.
getPreciseTokenLocEnd(SourceLocation Loc)280 SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
281 // We avoid getLocForEndOfToken here, because it doesn't do what we want for
282 // macro locations, which we just treat as expanded files.
283 unsigned TokLen =
284 Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts);
285 return Loc.getLocWithOffset(TokLen);
286 }
287
288 /// Return the start location of an included file or expanded macro.
getStartOfFileOrMacro(SourceLocation Loc)289 SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
290 if (Loc.isMacroID())
291 return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
292 return SM.getLocForStartOfFile(SM.getFileID(Loc));
293 }
294
295 /// Return the end location of an included file or expanded macro.
getEndOfFileOrMacro(SourceLocation Loc)296 SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
297 if (Loc.isMacroID())
298 return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
299 SM.getFileOffset(Loc));
300 return SM.getLocForEndOfFile(SM.getFileID(Loc));
301 }
302
303 /// Find out where a macro is expanded. If the immediate result is a
304 /// <scratch space>, keep looking until the result isn't. Return a pair of
305 /// \c SourceLocation. The first object is always the begin sloc of found
306 /// result. The second should be checked by the caller: if it has value, it's
307 /// the end sloc of the found result. Otherwise the while loop didn't get
308 /// executed, which means the location wasn't changed and the caller has to
309 /// learn the end sloc from somewhere else.
310 std::pair<SourceLocation, std::optional<SourceLocation>>
getNonScratchExpansionLoc(SourceLocation Loc)311 getNonScratchExpansionLoc(SourceLocation Loc) {
312 std::optional<SourceLocation> EndLoc = std::nullopt;
313 while (Loc.isMacroID() &&
314 SM.isWrittenInScratchSpace(SM.getSpellingLoc(Loc))) {
315 auto ExpansionRange = SM.getImmediateExpansionRange(Loc);
316 Loc = ExpansionRange.getBegin();
317 EndLoc = ExpansionRange.getEnd();
318 }
319 return std::make_pair(Loc, EndLoc);
320 }
321
322 /// Find out where the current file is included or macro is expanded. If
323 /// \c AcceptScratch is set to false, keep looking for expansions until the
324 /// found sloc is not a <scratch space>.
getIncludeOrExpansionLoc(SourceLocation Loc,bool AcceptScratch=true)325 SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc,
326 bool AcceptScratch = true) {
327 if (!Loc.isMacroID())
328 return SM.getIncludeLoc(SM.getFileID(Loc));
329 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
330 if (AcceptScratch)
331 return Loc;
332 return getNonScratchExpansionLoc(Loc).first;
333 }
334
335 /// Return true if \c Loc is a location in a built-in macro.
isInBuiltin(SourceLocation Loc)336 bool isInBuiltin(SourceLocation Loc) {
337 return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
338 }
339
340 /// Check whether \c Loc is included or expanded from \c Parent.
isNestedIn(SourceLocation Loc,FileID Parent)341 bool isNestedIn(SourceLocation Loc, FileID Parent) {
342 do {
343 Loc = getIncludeOrExpansionLoc(Loc);
344 if (Loc.isInvalid())
345 return false;
346 } while (!SM.isInFileID(Loc, Parent));
347 return true;
348 }
349
350 /// Get the start of \c S ignoring macro arguments and builtin macros.
getStart(const Stmt * S)351 SourceLocation getStart(const Stmt *S) {
352 SourceLocation Loc = S->getBeginLoc();
353 while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
354 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
355 return Loc;
356 }
357
358 /// Get the end of \c S ignoring macro arguments and builtin macros.
getEnd(const Stmt * S)359 SourceLocation getEnd(const Stmt *S) {
360 SourceLocation Loc = S->getEndLoc();
361 while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
362 Loc = SM.getImmediateExpansionRange(Loc).getBegin();
363 return getPreciseTokenLocEnd(Loc);
364 }
365
366 /// Find the set of files we have regions for and assign IDs
367 ///
368 /// Fills \c Mapping with the virtual file mapping needed to write out
369 /// coverage and collects the necessary file information to emit source and
370 /// expansion regions.
gatherFileIDs(SmallVectorImpl<unsigned> & Mapping)371 void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) {
372 FileIDMapping.clear();
373
374 llvm::SmallSet<FileID, 8> Visited;
375 SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
376 for (auto &Region : SourceRegions) {
377 SourceLocation Loc = Region.getBeginLoc();
378
379 // Replace Region with its definition if it is in <scratch space>.
380 auto NonScratchExpansionLoc = getNonScratchExpansionLoc(Loc);
381 auto EndLoc = NonScratchExpansionLoc.second;
382 if (EndLoc.has_value()) {
383 Loc = NonScratchExpansionLoc.first;
384 Region.setStartLoc(Loc);
385 Region.setEndLoc(EndLoc.value());
386 }
387
388 // Replace Loc with FileLoc if it is expanded with system headers.
389 if (!SystemHeadersCoverage && SM.isInSystemMacro(Loc)) {
390 auto BeginLoc = SM.getSpellingLoc(Loc);
391 auto EndLoc = SM.getSpellingLoc(Region.getEndLoc());
392 if (SM.isWrittenInSameFile(BeginLoc, EndLoc)) {
393 Loc = SM.getFileLoc(Loc);
394 Region.setStartLoc(Loc);
395 Region.setEndLoc(SM.getFileLoc(Region.getEndLoc()));
396 }
397 }
398
399 FileID File = SM.getFileID(Loc);
400 if (!Visited.insert(File).second)
401 continue;
402
403 assert(SystemHeadersCoverage ||
404 !SM.isInSystemHeader(SM.getSpellingLoc(Loc)));
405
406 unsigned Depth = 0;
407 for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
408 Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent))
409 ++Depth;
410 FileLocs.push_back(std::make_pair(Loc, Depth));
411 }
412 llvm::stable_sort(FileLocs, llvm::less_second());
413
414 for (const auto &FL : FileLocs) {
415 SourceLocation Loc = FL.first;
416 FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first;
417 auto Entry = SM.getFileEntryRefForID(SpellingFile);
418 if (!Entry)
419 continue;
420
421 FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
422 Mapping.push_back(CVM.getFileID(*Entry));
423 }
424 }
425
426 /// Get the coverage mapping file ID for \c Loc.
427 ///
428 /// If such file id doesn't exist, return std::nullopt.
getCoverageFileID(SourceLocation Loc)429 std::optional<unsigned> getCoverageFileID(SourceLocation Loc) {
430 auto Mapping = FileIDMapping.find(SM.getFileID(Loc));
431 if (Mapping != FileIDMapping.end())
432 return Mapping->second.first;
433 return std::nullopt;
434 }
435
436 /// This shrinks the skipped range if it spans a line that contains a
437 /// non-comment token. If shrinking the skipped range would make it empty,
438 /// this returns std::nullopt.
439 /// Note this function can potentially be expensive because
440 /// getSpellingLineNumber uses getLineNumber, which is expensive.
adjustSkippedRange(SourceManager & SM,SourceLocation LocStart,SourceLocation LocEnd,SourceLocation PrevTokLoc,SourceLocation NextTokLoc)441 std::optional<SpellingRegion> adjustSkippedRange(SourceManager &SM,
442 SourceLocation LocStart,
443 SourceLocation LocEnd,
444 SourceLocation PrevTokLoc,
445 SourceLocation NextTokLoc) {
446 SpellingRegion SR{SM, LocStart, LocEnd};
447 SR.ColumnStart = 1;
448 if (PrevTokLoc.isValid() && SM.isWrittenInSameFile(LocStart, PrevTokLoc) &&
449 SR.LineStart == SM.getSpellingLineNumber(PrevTokLoc))
450 SR.LineStart++;
451 if (NextTokLoc.isValid() && SM.isWrittenInSameFile(LocEnd, NextTokLoc) &&
452 SR.LineEnd == SM.getSpellingLineNumber(NextTokLoc)) {
453 SR.LineEnd--;
454 SR.ColumnEnd++;
455 }
456 if (SR.isInSourceOrder())
457 return SR;
458 return std::nullopt;
459 }
460
461 /// Gather all the regions that were skipped by the preprocessor
462 /// using the constructs like #if or comments.
gatherSkippedRegions()463 void gatherSkippedRegions() {
464 /// An array of the minimum lineStarts and the maximum lineEnds
465 /// for mapping regions from the appropriate source files.
466 llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
467 FileLineRanges.resize(
468 FileIDMapping.size(),
469 std::make_pair(std::numeric_limits<unsigned>::max(), 0));
470 for (const auto &R : MappingRegions) {
471 FileLineRanges[R.FileID].first =
472 std::min(FileLineRanges[R.FileID].first, R.LineStart);
473 FileLineRanges[R.FileID].second =
474 std::max(FileLineRanges[R.FileID].second, R.LineEnd);
475 }
476
477 auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
478 for (auto &I : SkippedRanges) {
479 SourceRange Range = I.Range;
480 auto LocStart = Range.getBegin();
481 auto LocEnd = Range.getEnd();
482 assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
483 "region spans multiple files");
484
485 auto CovFileID = getCoverageFileID(LocStart);
486 if (!CovFileID)
487 continue;
488 std::optional<SpellingRegion> SR;
489 if (I.isComment())
490 SR = adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc,
491 I.NextTokLoc);
492 else if (I.isPPIfElse() || I.isEmptyLine())
493 SR = {SM, LocStart, LocEnd};
494
495 if (!SR)
496 continue;
497 auto Region = CounterMappingRegion::makeSkipped(
498 *CovFileID, SR->LineStart, SR->ColumnStart, SR->LineEnd,
499 SR->ColumnEnd);
500 // Make sure that we only collect the regions that are inside
501 // the source code of this function.
502 if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
503 Region.LineEnd <= FileLineRanges[*CovFileID].second)
504 MappingRegions.push_back(Region);
505 }
506 }
507
508 /// Generate the coverage counter mapping regions from collected
509 /// source regions.
emitSourceRegions(const SourceRegionFilter & Filter)510 void emitSourceRegions(const SourceRegionFilter &Filter) {
511 for (const auto &Region : SourceRegions) {
512 assert(Region.hasEndLoc() && "incomplete region");
513
514 SourceLocation LocStart = Region.getBeginLoc();
515 assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
516
517 // Ignore regions from system headers unless collecting coverage from
518 // system headers is explicitly enabled.
519 if (!SystemHeadersCoverage &&
520 SM.isInSystemHeader(SM.getSpellingLoc(LocStart))) {
521 assert(!Region.isMCDCBranch() && !Region.isMCDCDecision() &&
522 "Don't suppress the condition in system headers");
523 continue;
524 }
525
526 auto CovFileID = getCoverageFileID(LocStart);
527 // Ignore regions that don't have a file, such as builtin macros.
528 if (!CovFileID) {
529 assert(!Region.isMCDCBranch() && !Region.isMCDCDecision() &&
530 "Don't suppress the condition in non-file regions");
531 continue;
532 }
533
534 SourceLocation LocEnd = Region.getEndLoc();
535 assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
536 "region spans multiple files");
537
538 // Don't add code regions for the area covered by expansion regions.
539 // This not only suppresses redundant regions, but sometimes prevents
540 // creating regions with wrong counters if, for example, a statement's
541 // body ends at the end of a nested macro.
542 if (Filter.count(std::make_pair(LocStart, LocEnd))) {
543 assert(!Region.isMCDCBranch() && !Region.isMCDCDecision() &&
544 "Don't suppress the condition");
545 continue;
546 }
547
548 // Find the spelling locations for the mapping region.
549 SpellingRegion SR{SM, LocStart, LocEnd};
550 assert(SR.isInSourceOrder() && "region start and end out of order");
551
552 if (Region.isGap()) {
553 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
554 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
555 SR.LineEnd, SR.ColumnEnd));
556 } else if (Region.isSkipped()) {
557 MappingRegions.push_back(CounterMappingRegion::makeSkipped(
558 *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd,
559 SR.ColumnEnd));
560 } else if (Region.isBranch()) {
561 MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
562 Region.getCounter(), Region.getFalseCounter(), *CovFileID,
563 SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd,
564 Region.getMCDCParams()));
565 } else if (Region.isMCDCDecision()) {
566 MappingRegions.push_back(CounterMappingRegion::makeDecisionRegion(
567 Region.getMCDCDecisionParams(), *CovFileID, SR.LineStart,
568 SR.ColumnStart, SR.LineEnd, SR.ColumnEnd));
569 } else {
570 MappingRegions.push_back(CounterMappingRegion::makeRegion(
571 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
572 SR.LineEnd, SR.ColumnEnd));
573 }
574 }
575 }
576
577 /// Generate expansion regions for each virtual file we've seen.
emitExpansionRegions()578 SourceRegionFilter emitExpansionRegions() {
579 SourceRegionFilter Filter;
580 for (const auto &FM : FileIDMapping) {
581 SourceLocation ExpandedLoc = FM.second.second;
582 SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc, false);
583 if (ParentLoc.isInvalid())
584 continue;
585
586 auto ParentFileID = getCoverageFileID(ParentLoc);
587 if (!ParentFileID)
588 continue;
589 auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
590 assert(ExpandedFileID && "expansion in uncovered file");
591
592 SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
593 assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
594 "region spans multiple files");
595 Filter.insert(std::make_pair(ParentLoc, LocEnd));
596
597 SpellingRegion SR{SM, ParentLoc, LocEnd};
598 assert(SR.isInSourceOrder() && "region start and end out of order");
599 MappingRegions.push_back(CounterMappingRegion::makeExpansion(
600 *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
601 SR.LineEnd, SR.ColumnEnd));
602 }
603 return Filter;
604 }
605 };
606
607 /// Creates unreachable coverage regions for the functions that
608 /// are not emitted.
609 struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
EmptyCoverageMappingBuilder__anon413222f00211::EmptyCoverageMappingBuilder610 EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
611 const LangOptions &LangOpts)
612 : CoverageMappingBuilder(CVM, SM, LangOpts) {}
613
VisitDecl__anon413222f00211::EmptyCoverageMappingBuilder614 void VisitDecl(const Decl *D) {
615 if (!D->hasBody())
616 return;
617 auto Body = D->getBody();
618 SourceLocation Start = getStart(Body);
619 SourceLocation End = getEnd(Body);
620 if (!SM.isWrittenInSameFile(Start, End)) {
621 // Walk up to find the common ancestor.
622 // Correct the locations accordingly.
623 FileID StartFileID = SM.getFileID(Start);
624 FileID EndFileID = SM.getFileID(End);
625 while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
626 Start = getIncludeOrExpansionLoc(Start);
627 assert(Start.isValid() &&
628 "Declaration start location not nested within a known region");
629 StartFileID = SM.getFileID(Start);
630 }
631 while (StartFileID != EndFileID) {
632 End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
633 assert(End.isValid() &&
634 "Declaration end location not nested within a known region");
635 EndFileID = SM.getFileID(End);
636 }
637 }
638 SourceRegions.emplace_back(Counter(), Start, End);
639 }
640
641 /// Write the mapping data to the output stream
write__anon413222f00211::EmptyCoverageMappingBuilder642 void write(llvm::raw_ostream &OS) {
643 SmallVector<unsigned, 16> FileIDMapping;
644 gatherFileIDs(FileIDMapping);
645 emitSourceRegions(SourceRegionFilter());
646
647 if (MappingRegions.empty())
648 return;
649
650 CoverageMappingWriter Writer(FileIDMapping, {}, MappingRegions);
651 Writer.write(OS);
652 }
653 };
654
655 /// A wrapper object for maintaining stacks to track the resursive AST visitor
656 /// walks for the purpose of assigning IDs to leaf-level conditions measured by
657 /// MC/DC. The object is created with a reference to the MCDCBitmapMap that was
658 /// created during the initial AST walk. The presence of a bitmap associated
659 /// with a boolean expression (top-level logical operator nest) indicates that
660 /// the boolean expression qualified for MC/DC. The resulting condition IDs
661 /// are preserved in a map reference that is also provided during object
662 /// creation.
663 struct MCDCCoverageBuilder {
664
665 /// The AST walk recursively visits nested logical-AND or logical-OR binary
666 /// operator nodes and then visits their LHS and RHS children nodes. As this
667 /// happens, the algorithm will assign IDs to each operator's LHS and RHS side
668 /// as the walk moves deeper into the nest. At each level of the recursive
669 /// nest, the LHS and RHS may actually correspond to larger subtrees (not
670 /// leaf-conditions). If this is the case, when that node is visited, the ID
671 /// assigned to the subtree is re-assigned to its LHS, and a new ID is given
672 /// to its RHS. At the end of the walk, all leaf-level conditions will have a
673 /// unique ID -- keep in mind that the final set of IDs may not be in
674 /// numerical order from left to right.
675 ///
676 /// Example: "x = (A && B) || (C && D) || (D && F)"
677 ///
678 /// Visit Depth1:
679 /// (A && B) || (C && D) || (D && F)
680 /// ^-------LHS--------^ ^-RHS--^
681 /// ID=1 ID=2
682 ///
683 /// Visit LHS-Depth2:
684 /// (A && B) || (C && D)
685 /// ^-LHS--^ ^-RHS--^
686 /// ID=1 ID=3
687 ///
688 /// Visit LHS-Depth3:
689 /// (A && B)
690 /// LHS RHS
691 /// ID=1 ID=4
692 ///
693 /// Visit RHS-Depth3:
694 /// (C && D)
695 /// LHS RHS
696 /// ID=3 ID=5
697 ///
698 /// Visit RHS-Depth2: (D && F)
699 /// LHS RHS
700 /// ID=2 ID=6
701 ///
702 /// Visit Depth1:
703 /// (A && B) || (C && D) || (D && F)
704 /// ID=1 ID=4 ID=3 ID=5 ID=2 ID=6
705 ///
706 /// A node ID of '0' always means MC/DC isn't being tracked.
707 ///
708 /// As the AST walk proceeds recursively, the algorithm will also use a stack
709 /// to track the IDs of logical-AND and logical-OR operations on the RHS so
710 /// that it can be determined which nodes are executed next, depending on how
711 /// a LHS or RHS of a logical-AND or logical-OR is evaluated. This
712 /// information relies on the assigned IDs and are embedded within the
713 /// coverage region IDs of each branch region associated with a leaf-level
714 /// condition. This information helps the visualization tool reconstruct all
715 /// possible test vectors for the purposes of MC/DC analysis. If a "next" node
716 /// ID is '0', it means it's the end of the test vector. The following rules
717 /// are used:
718 ///
719 /// For logical-AND ("LHS && RHS"):
720 /// - If LHS is TRUE, execution goes to the RHS node.
721 /// - If LHS is FALSE, execution goes to the LHS node of the next logical-OR.
722 /// If that does not exist, execution exits (ID == 0).
723 ///
724 /// - If RHS is TRUE, execution goes to LHS node of the next logical-AND.
725 /// If that does not exist, execution exits (ID == 0).
726 /// - If RHS is FALSE, execution goes to the LHS node of the next logical-OR.
727 /// If that does not exist, execution exits (ID == 0).
728 ///
729 /// For logical-OR ("LHS || RHS"):
730 /// - If LHS is TRUE, execution goes to the LHS node of the next logical-AND.
731 /// If that does not exist, execution exits (ID == 0).
732 /// - If LHS is FALSE, execution goes to the RHS node.
733 ///
734 /// - If RHS is TRUE, execution goes to LHS node of the next logical-AND.
735 /// If that does not exist, execution exits (ID == 0).
736 /// - If RHS is FALSE, execution goes to the LHS node of the next logical-OR.
737 /// If that does not exist, execution exits (ID == 0).
738 ///
739 /// Finally, the condition IDs are also used when instrumenting the code to
740 /// indicate a unique offset into a temporary bitmap that represents the true
741 /// or false evaluation of that particular condition.
742 ///
743 /// NOTE regarding the use of CodeGenFunction::stripCond(). Even though, for
744 /// simplicity, parentheses and unary logical-NOT operators are considered
745 /// part of their underlying condition for both MC/DC and branch coverage, the
746 /// condition IDs themselves are assigned and tracked using the underlying
747 /// condition itself. This is done solely for consistency since parentheses
748 /// and logical-NOTs are ignored when checking whether the condition is
749 /// actually an instrumentable condition. This can also make debugging a bit
750 /// easier.
751
752 private:
753 CodeGenModule &CGM;
754
755 llvm::SmallVector<mcdc::ConditionIDs> DecisionStack;
756 MCDC::State &MCDCState;
757 const Stmt *DecisionStmt = nullptr;
758 mcdc::ConditionID NextID = 0;
759 bool NotMapped = false;
760
761 /// Represent a sentinel value as a pair of final decisions for the bottom
762 // of DecisionStack.
763 static constexpr mcdc::ConditionIDs DecisionStackSentinel{-1, -1};
764
765 /// Is this a logical-AND operation?
isLAnd__anon413222f00211::MCDCCoverageBuilder766 bool isLAnd(const BinaryOperator *E) const {
767 return E->getOpcode() == BO_LAnd;
768 }
769
770 public:
MCDCCoverageBuilder__anon413222f00211::MCDCCoverageBuilder771 MCDCCoverageBuilder(CodeGenModule &CGM, MCDC::State &MCDCState)
772 : CGM(CGM), DecisionStack(1, DecisionStackSentinel),
773 MCDCState(MCDCState) {}
774
775 /// Return whether the build of the control flow map is at the top-level
776 /// (root) of a logical operator nest in a boolean expression prior to the
777 /// assignment of condition IDs.
isIdle__anon413222f00211::MCDCCoverageBuilder778 bool isIdle() const { return (NextID == 0 && !NotMapped); }
779
780 /// Return whether any IDs have been assigned in the build of the control
781 /// flow map, indicating that the map is being generated for this boolean
782 /// expression.
isBuilding__anon413222f00211::MCDCCoverageBuilder783 bool isBuilding() const { return (NextID > 0); }
784
785 /// Set the given condition's ID.
setCondID__anon413222f00211::MCDCCoverageBuilder786 void setCondID(const Expr *Cond, mcdc::ConditionID ID) {
787 MCDCState.BranchByStmt[CodeGenFunction::stripCond(Cond)] = {ID,
788 DecisionStmt};
789 }
790
791 /// Return the ID of a given condition.
getCondID__anon413222f00211::MCDCCoverageBuilder792 mcdc::ConditionID getCondID(const Expr *Cond) const {
793 auto I = MCDCState.BranchByStmt.find(CodeGenFunction::stripCond(Cond));
794 if (I == MCDCState.BranchByStmt.end())
795 return -1;
796 else
797 return I->second.ID;
798 }
799
800 /// Return the LHS Decision ([0,0] if not set).
back__anon413222f00211::MCDCCoverageBuilder801 const mcdc::ConditionIDs &back() const { return DecisionStack.back(); }
802
803 /// Push the binary operator statement to track the nest level and assign IDs
804 /// to the operator's LHS and RHS. The RHS may be a larger subtree that is
805 /// broken up on successive levels.
pushAndAssignIDs__anon413222f00211::MCDCCoverageBuilder806 void pushAndAssignIDs(const BinaryOperator *E) {
807 if (!CGM.getCodeGenOpts().MCDCCoverage)
808 return;
809
810 // If binary expression is disqualified, don't do mapping.
811 if (!isBuilding() &&
812 !MCDCState.DecisionByStmt.contains(CodeGenFunction::stripCond(E)))
813 NotMapped = true;
814
815 // Don't go any further if we don't need to map condition IDs.
816 if (NotMapped)
817 return;
818
819 if (NextID == 0) {
820 DecisionStmt = E;
821 assert(MCDCState.DecisionByStmt.contains(E));
822 }
823
824 const mcdc::ConditionIDs &ParentDecision = DecisionStack.back();
825
826 // If the operator itself has an assigned ID, this means it represents a
827 // larger subtree. In this case, assign that ID to its LHS node. Its RHS
828 // will receive a new ID below. Otherwise, assign ID+1 to LHS.
829 if (MCDCState.BranchByStmt.contains(CodeGenFunction::stripCond(E)))
830 setCondID(E->getLHS(), getCondID(E));
831 else
832 setCondID(E->getLHS(), NextID++);
833
834 // Assign a ID+1 for the RHS.
835 mcdc::ConditionID RHSid = NextID++;
836 setCondID(E->getRHS(), RHSid);
837
838 // Push the LHS decision IDs onto the DecisionStack.
839 if (isLAnd(E))
840 DecisionStack.push_back({ParentDecision[false], RHSid});
841 else
842 DecisionStack.push_back({RHSid, ParentDecision[true]});
843 }
844
845 /// Pop and return the LHS Decision ([0,0] if not set).
pop__anon413222f00211::MCDCCoverageBuilder846 mcdc::ConditionIDs pop() {
847 if (!CGM.getCodeGenOpts().MCDCCoverage || NotMapped)
848 return DecisionStackSentinel;
849
850 assert(DecisionStack.size() > 1);
851 return DecisionStack.pop_back_val();
852 }
853
854 /// Return the total number of conditions and reset the state. The number of
855 /// conditions is zero if the expression isn't mapped.
getTotalConditionsAndReset__anon413222f00211::MCDCCoverageBuilder856 unsigned getTotalConditionsAndReset(const BinaryOperator *E) {
857 if (!CGM.getCodeGenOpts().MCDCCoverage)
858 return 0;
859
860 assert(!isIdle());
861 assert(DecisionStack.size() == 1);
862
863 // Reset state if not doing mapping.
864 if (NotMapped) {
865 NotMapped = false;
866 assert(NextID == 0);
867 return 0;
868 }
869
870 // Set number of conditions and reset.
871 unsigned TotalConds = NextID;
872
873 // Reset ID back to beginning.
874 NextID = 0;
875
876 return TotalConds;
877 }
878 };
879
880 /// A StmtVisitor that creates coverage mapping regions which map
881 /// from the source code locations to the PGO counters.
882 struct CounterCoverageMappingBuilder
883 : public CoverageMappingBuilder,
884 public ConstStmtVisitor<CounterCoverageMappingBuilder> {
885 /// The map of statements to count values.
886 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
887
888 MCDC::State &MCDCState;
889
890 /// A stack of currently live regions.
891 llvm::SmallVector<SourceMappingRegion> RegionStack;
892
893 /// Set if the Expr should be handled as a leaf even if it is kind of binary
894 /// logical ops (&&, ||).
895 llvm::DenseSet<const Stmt *> LeafExprSet;
896
897 /// An object to manage MCDC regions.
898 MCDCCoverageBuilder MCDCBuilder;
899
900 CounterExpressionBuilder Builder;
901
902 /// A location in the most recently visited file or macro.
903 ///
904 /// This is used to adjust the active source regions appropriately when
905 /// expressions cross file or macro boundaries.
906 SourceLocation MostRecentLocation;
907
908 /// Whether the visitor at a terminate statement.
909 bool HasTerminateStmt = false;
910
911 /// Gap region counter after terminate statement.
912 Counter GapRegionCounter;
913
914 /// Return a counter for the subtraction of \c RHS from \c LHS
subtractCounters__anon413222f00211::CounterCoverageMappingBuilder915 Counter subtractCounters(Counter LHS, Counter RHS, bool Simplify = true) {
916 assert(!llvm::EnableSingleByteCoverage &&
917 "cannot add counters when single byte coverage mode is enabled");
918 return Builder.subtract(LHS, RHS, Simplify);
919 }
920
921 /// Return a counter for the sum of \c LHS and \c RHS.
addCounters__anon413222f00211::CounterCoverageMappingBuilder922 Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
923 return Builder.add(LHS, RHS, Simplify);
924 }
925
addCounters__anon413222f00211::CounterCoverageMappingBuilder926 Counter addCounters(Counter C1, Counter C2, Counter C3,
927 bool Simplify = true) {
928 return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
929 }
930
931 /// Return the region counter for the given statement.
932 ///
933 /// This should only be called on statements that have a dedicated counter.
getRegionCounter__anon413222f00211::CounterCoverageMappingBuilder934 Counter getRegionCounter(const Stmt *S) {
935 return Counter::getCounter(CounterMap[S].Executed);
936 }
937
938 struct BranchCounterPair {
939 Counter Executed; ///< The Counter previously assigned.
940 Counter Skipped; ///< An expression (Parent-Executed), or equivalent to it.
941 };
942
943 /// Retrieve or assign the pair of Counter(s).
944 ///
945 /// This returns BranchCounterPair {Executed, Skipped}.
946 /// Executed is the Counter associated with S assigned by an earlier
947 /// CounterMapping pass.
948 /// Skipped may be an expression (Executed - ParentCnt) or newly
949 /// assigned Counter in EnableSingleByteCoverage, as subtract
950 /// expressions are not available in this mode.
951 ///
952 /// \param S Key to the CounterMap
953 /// \param ParentCnt The Counter representing how many times S is evaluated.
954 /// \param SkipCntForOld (To be removed later) Optional fake Counter
955 /// to override Skipped for adjustment of
956 /// expressions in the old behavior of
957 /// EnableSingleByteCoverage that is unaware of
958 /// Branch coverage.
959 BranchCounterPair
getBranchCounterPair__anon413222f00211::CounterCoverageMappingBuilder960 getBranchCounterPair(const Stmt *S, Counter ParentCnt,
961 std::optional<Counter> SkipCntForOld = std::nullopt) {
962 Counter ExecCnt = getRegionCounter(S);
963
964 // The old behavior of SingleByte is unaware of Branches.
965 // Will be pruned after the migration of SingleByte.
966 if (llvm::EnableSingleByteCoverage) {
967 assert(SkipCntForOld &&
968 "SingleByte must provide SkipCntForOld as a fake Skipped count.");
969 return {ExecCnt, *SkipCntForOld};
970 }
971
972 return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
973 }
974
IsCounterEqual__anon413222f00211::CounterCoverageMappingBuilder975 bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
976 if (OutCount == ParentCount)
977 return true;
978
979 return false;
980 }
981
982 /// Push a region onto the stack.
983 ///
984 /// Returns the index on the stack where the region was pushed. This can be
985 /// used with popRegions to exit a "scope", ending the region that was pushed.
pushRegion__anon413222f00211::CounterCoverageMappingBuilder986 size_t pushRegion(Counter Count,
987 std::optional<SourceLocation> StartLoc = std::nullopt,
988 std::optional<SourceLocation> EndLoc = std::nullopt,
989 std::optional<Counter> FalseCount = std::nullopt,
990 const mcdc::Parameters &BranchParams = std::monostate()) {
991
992 if (StartLoc && !FalseCount) {
993 MostRecentLocation = *StartLoc;
994 }
995
996 // If either of these locations is invalid, something elsewhere in the
997 // compiler has broken.
998 assert((!StartLoc || StartLoc->isValid()) && "Start location is not valid");
999 assert((!EndLoc || EndLoc->isValid()) && "End location is not valid");
1000
1001 // However, we can still recover without crashing.
1002 // If either location is invalid, set it to std::nullopt to avoid
1003 // letting users of RegionStack think that region has a valid start/end
1004 // location.
1005 if (StartLoc && StartLoc->isInvalid())
1006 StartLoc = std::nullopt;
1007 if (EndLoc && EndLoc->isInvalid())
1008 EndLoc = std::nullopt;
1009 RegionStack.emplace_back(Count, FalseCount, BranchParams, StartLoc, EndLoc);
1010
1011 return RegionStack.size() - 1;
1012 }
1013
pushRegion__anon413222f00211::CounterCoverageMappingBuilder1014 size_t pushRegion(const mcdc::DecisionParameters &DecisionParams,
1015 std::optional<SourceLocation> StartLoc = std::nullopt,
1016 std::optional<SourceLocation> EndLoc = std::nullopt) {
1017
1018 RegionStack.emplace_back(DecisionParams, StartLoc, EndLoc);
1019
1020 return RegionStack.size() - 1;
1021 }
1022
locationDepth__anon413222f00211::CounterCoverageMappingBuilder1023 size_t locationDepth(SourceLocation Loc) {
1024 size_t Depth = 0;
1025 while (Loc.isValid()) {
1026 Loc = getIncludeOrExpansionLoc(Loc);
1027 Depth++;
1028 }
1029 return Depth;
1030 }
1031
1032 /// Pop regions from the stack into the function's list of regions.
1033 ///
1034 /// Adds all regions from \c ParentIndex to the top of the stack to the
1035 /// function's \c SourceRegions.
popRegions__anon413222f00211::CounterCoverageMappingBuilder1036 void popRegions(size_t ParentIndex) {
1037 assert(RegionStack.size() >= ParentIndex && "parent not in stack");
1038 while (RegionStack.size() > ParentIndex) {
1039 SourceMappingRegion &Region = RegionStack.back();
1040 if (Region.hasStartLoc() &&
1041 (Region.hasEndLoc() || RegionStack[ParentIndex].hasEndLoc())) {
1042 SourceLocation StartLoc = Region.getBeginLoc();
1043 SourceLocation EndLoc = Region.hasEndLoc()
1044 ? Region.getEndLoc()
1045 : RegionStack[ParentIndex].getEndLoc();
1046 bool isBranch = Region.isBranch();
1047 size_t StartDepth = locationDepth(StartLoc);
1048 size_t EndDepth = locationDepth(EndLoc);
1049 while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
1050 bool UnnestStart = StartDepth >= EndDepth;
1051 bool UnnestEnd = EndDepth >= StartDepth;
1052 if (UnnestEnd) {
1053 // The region ends in a nested file or macro expansion. If the
1054 // region is not a branch region, create a separate region for each
1055 // expansion, and for all regions, update the EndLoc. Branch
1056 // regions should not be split in order to keep a straightforward
1057 // correspondance between the region and its associated branch
1058 // condition, even if the condition spans multiple depths.
1059 SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
1060 assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
1061
1062 if (!isBranch && !isRegionAlreadyAdded(NestedLoc, EndLoc))
1063 SourceRegions.emplace_back(Region.getCounter(), NestedLoc,
1064 EndLoc);
1065
1066 EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
1067 if (EndLoc.isInvalid())
1068 llvm::report_fatal_error(
1069 "File exit not handled before popRegions");
1070 EndDepth--;
1071 }
1072 if (UnnestStart) {
1073 // The region ends in a nested file or macro expansion. If the
1074 // region is not a branch region, create a separate region for each
1075 // expansion, and for all regions, update the StartLoc. Branch
1076 // regions should not be split in order to keep a straightforward
1077 // correspondance between the region and its associated branch
1078 // condition, even if the condition spans multiple depths.
1079 SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
1080 assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
1081
1082 if (!isBranch && !isRegionAlreadyAdded(StartLoc, NestedLoc))
1083 SourceRegions.emplace_back(Region.getCounter(), StartLoc,
1084 NestedLoc);
1085
1086 StartLoc = getIncludeOrExpansionLoc(StartLoc);
1087 if (StartLoc.isInvalid())
1088 llvm::report_fatal_error(
1089 "File exit not handled before popRegions");
1090 StartDepth--;
1091 }
1092 }
1093 Region.setStartLoc(StartLoc);
1094 Region.setEndLoc(EndLoc);
1095
1096 if (!isBranch) {
1097 MostRecentLocation = EndLoc;
1098 // If this region happens to span an entire expansion, we need to
1099 // make sure we don't overlap the parent region with it.
1100 if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
1101 EndLoc == getEndOfFileOrMacro(EndLoc))
1102 MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
1103 }
1104
1105 assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
1106 assert(SpellingRegion(SM, Region).isInSourceOrder());
1107 SourceRegions.push_back(Region);
1108 }
1109 RegionStack.pop_back();
1110 }
1111 }
1112
1113 /// Return the currently active region.
getRegion__anon413222f00211::CounterCoverageMappingBuilder1114 SourceMappingRegion &getRegion() {
1115 assert(!RegionStack.empty() && "statement has no region");
1116 return RegionStack.back();
1117 }
1118
1119 /// Propagate counts through the children of \p S if \p VisitChildren is true.
1120 /// Otherwise, only emit a count for \p S itself.
propagateCounts__anon413222f00211::CounterCoverageMappingBuilder1121 Counter propagateCounts(Counter TopCount, const Stmt *S,
1122 bool VisitChildren = true) {
1123 SourceLocation StartLoc = getStart(S);
1124 SourceLocation EndLoc = getEnd(S);
1125 size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
1126 if (VisitChildren)
1127 Visit(S);
1128 Counter ExitCount = getRegion().getCounter();
1129 popRegions(Index);
1130
1131 // The statement may be spanned by an expansion. Make sure we handle a file
1132 // exit out of this expansion before moving to the next statement.
1133 if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
1134 MostRecentLocation = EndLoc;
1135
1136 return ExitCount;
1137 }
1138
1139 /// Create a Branch Region around an instrumentable condition for coverage
1140 /// and add it to the function's SourceRegions. A branch region tracks a
1141 /// "True" counter and a "False" counter for boolean expressions that
1142 /// result in the generation of a branch.
createBranchRegion__anon413222f00211::CounterCoverageMappingBuilder1143 void createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt,
1144 const mcdc::ConditionIDs &Conds = {}) {
1145 // Check for NULL conditions.
1146 if (!C)
1147 return;
1148
1149 // Ensure we are an instrumentable condition (i.e. no "&&" or "||"). Push
1150 // region onto RegionStack but immediately pop it (which adds it to the
1151 // function's SourceRegions) because it doesn't apply to any other source
1152 // code other than the Condition.
1153 // With !SystemHeadersCoverage, binary logical ops in system headers may be
1154 // treated as instrumentable conditions.
1155 if (CodeGenFunction::isInstrumentedCondition(C) ||
1156 LeafExprSet.count(CodeGenFunction::stripCond(C))) {
1157 mcdc::Parameters BranchParams;
1158 mcdc::ConditionID ID = MCDCBuilder.getCondID(C);
1159 if (ID >= 0)
1160 BranchParams = mcdc::BranchParameters{ID, Conds};
1161
1162 // If a condition can fold to true or false, the corresponding branch
1163 // will be removed. Create a region with both counters hard-coded to
1164 // zero. This allows us to visualize them in a special way.
1165 // Alternatively, we can prevent any optimization done via
1166 // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
1167 // CodeGenFunction.c always returns false, but that is very heavy-handed.
1168 Expr::EvalResult Result;
1169 if (C->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext())) {
1170 if (Result.Val.getInt().getBoolValue())
1171 FalseCnt = Counter::getZero();
1172 else
1173 TrueCnt = Counter::getZero();
1174 }
1175 popRegions(
1176 pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, BranchParams));
1177 }
1178 }
1179
1180 /// Create a Decision Region with a BitmapIdx and number of Conditions. This
1181 /// type of region "contains" branch regions, one for each of the conditions.
1182 /// The visualization tool will group everything together.
createDecisionRegion__anon413222f00211::CounterCoverageMappingBuilder1183 void createDecisionRegion(const Expr *C,
1184 const mcdc::DecisionParameters &DecisionParams) {
1185 popRegions(pushRegion(DecisionParams, getStart(C), getEnd(C)));
1186 }
1187
1188 /// Create a Branch Region around a SwitchCase for code coverage
1189 /// and add it to the function's SourceRegions.
1190 /// Returns Counter that corresponds to SC.
createSwitchCaseRegion__anon413222f00211::CounterCoverageMappingBuilder1191 Counter createSwitchCaseRegion(const SwitchCase *SC, Counter ParentCount) {
1192 // Push region onto RegionStack but immediately pop it (which adds it to
1193 // the function's SourceRegions) because it doesn't apply to any other
1194 // source other than the SwitchCase.
1195 Counter TrueCnt = getRegionCounter(SC);
1196 popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(),
1197 subtractCounters(ParentCount, TrueCnt)));
1198 return TrueCnt;
1199 }
1200
1201 /// Check whether a region with bounds \c StartLoc and \c EndLoc
1202 /// is already added to \c SourceRegions.
isRegionAlreadyAdded__anon413222f00211::CounterCoverageMappingBuilder1203 bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc,
1204 bool isBranch = false) {
1205 return llvm::any_of(
1206 llvm::reverse(SourceRegions), [&](const SourceMappingRegion &Region) {
1207 return Region.getBeginLoc() == StartLoc &&
1208 Region.getEndLoc() == EndLoc && Region.isBranch() == isBranch;
1209 });
1210 }
1211
1212 /// Adjust the most recently visited location to \c EndLoc.
1213 ///
1214 /// This should be used after visiting any statements in non-source order.
adjustForOutOfOrderTraversal__anon413222f00211::CounterCoverageMappingBuilder1215 void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
1216 MostRecentLocation = EndLoc;
1217 // The code region for a whole macro is created in handleFileExit() when
1218 // it detects exiting of the virtual file of that macro. If we visited
1219 // statements in non-source order, we might already have such a region
1220 // added, for example, if a body of a loop is divided among multiple
1221 // macros. Avoid adding duplicate regions in such case.
1222 if (getRegion().hasEndLoc() &&
1223 MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
1224 isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
1225 MostRecentLocation, getRegion().isBranch()))
1226 MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
1227 }
1228
1229 /// Adjust regions and state when \c NewLoc exits a file.
1230 ///
1231 /// If moving from our most recently tracked location to \c NewLoc exits any
1232 /// files, this adjusts our current region stack and creates the file regions
1233 /// for the exited file.
handleFileExit__anon413222f00211::CounterCoverageMappingBuilder1234 void handleFileExit(SourceLocation NewLoc) {
1235 if (NewLoc.isInvalid() ||
1236 SM.isWrittenInSameFile(MostRecentLocation, NewLoc))
1237 return;
1238
1239 // If NewLoc is not in a file that contains MostRecentLocation, walk up to
1240 // find the common ancestor.
1241 SourceLocation LCA = NewLoc;
1242 FileID ParentFile = SM.getFileID(LCA);
1243 while (!isNestedIn(MostRecentLocation, ParentFile)) {
1244 LCA = getIncludeOrExpansionLoc(LCA);
1245 if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) {
1246 // Since there isn't a common ancestor, no file was exited. We just need
1247 // to adjust our location to the new file.
1248 MostRecentLocation = NewLoc;
1249 return;
1250 }
1251 ParentFile = SM.getFileID(LCA);
1252 }
1253
1254 llvm::SmallSet<SourceLocation, 8> StartLocs;
1255 std::optional<Counter> ParentCounter;
1256 for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
1257 if (!I.hasStartLoc())
1258 continue;
1259 SourceLocation Loc = I.getBeginLoc();
1260 if (!isNestedIn(Loc, ParentFile)) {
1261 ParentCounter = I.getCounter();
1262 break;
1263 }
1264
1265 while (!SM.isInFileID(Loc, ParentFile)) {
1266 // The most nested region for each start location is the one with the
1267 // correct count. We avoid creating redundant regions by stopping once
1268 // we've seen this region.
1269 if (StartLocs.insert(Loc).second) {
1270 if (I.isBranch())
1271 SourceRegions.emplace_back(I.getCounter(), I.getFalseCounter(),
1272 I.getMCDCParams(), Loc,
1273 getEndOfFileOrMacro(Loc), I.isBranch());
1274 else
1275 SourceRegions.emplace_back(I.getCounter(), Loc,
1276 getEndOfFileOrMacro(Loc));
1277 }
1278 Loc = getIncludeOrExpansionLoc(Loc);
1279 }
1280 I.setStartLoc(getPreciseTokenLocEnd(Loc));
1281 }
1282
1283 if (ParentCounter) {
1284 // If the file is contained completely by another region and doesn't
1285 // immediately start its own region, the whole file gets a region
1286 // corresponding to the parent.
1287 SourceLocation Loc = MostRecentLocation;
1288 while (isNestedIn(Loc, ParentFile)) {
1289 SourceLocation FileStart = getStartOfFileOrMacro(Loc);
1290 if (StartLocs.insert(FileStart).second) {
1291 SourceRegions.emplace_back(*ParentCounter, FileStart,
1292 getEndOfFileOrMacro(Loc));
1293 assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder());
1294 }
1295 Loc = getIncludeOrExpansionLoc(Loc);
1296 }
1297 }
1298
1299 MostRecentLocation = NewLoc;
1300 }
1301
1302 /// Ensure that \c S is included in the current region.
extendRegion__anon413222f00211::CounterCoverageMappingBuilder1303 void extendRegion(const Stmt *S) {
1304 SourceMappingRegion &Region = getRegion();
1305 SourceLocation StartLoc = getStart(S);
1306
1307 handleFileExit(StartLoc);
1308 if (!Region.hasStartLoc())
1309 Region.setStartLoc(StartLoc);
1310 }
1311
1312 /// Mark \c S as a terminator, starting a zero region.
terminateRegion__anon413222f00211::CounterCoverageMappingBuilder1313 void terminateRegion(const Stmt *S) {
1314 extendRegion(S);
1315 SourceMappingRegion &Region = getRegion();
1316 SourceLocation EndLoc = getEnd(S);
1317 if (!Region.hasEndLoc())
1318 Region.setEndLoc(EndLoc);
1319 pushRegion(Counter::getZero());
1320 HasTerminateStmt = true;
1321 }
1322
1323 /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
findGapAreaBetween__anon413222f00211::CounterCoverageMappingBuilder1324 std::optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
1325 SourceLocation BeforeLoc) {
1326 // Some statements (like AttributedStmt and ImplicitValueInitExpr) don't
1327 // have valid source locations. Do not emit a gap region if this is the case
1328 // in either AfterLoc end or BeforeLoc end.
1329 if (AfterLoc.isInvalid() || BeforeLoc.isInvalid())
1330 return std::nullopt;
1331
1332 // If AfterLoc is in function-like macro, use the right parenthesis
1333 // location.
1334 if (AfterLoc.isMacroID()) {
1335 FileID FID = SM.getFileID(AfterLoc);
1336 const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
1337 if (EI->isFunctionMacroExpansion())
1338 AfterLoc = EI->getExpansionLocEnd();
1339 }
1340
1341 size_t StartDepth = locationDepth(AfterLoc);
1342 size_t EndDepth = locationDepth(BeforeLoc);
1343 while (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) {
1344 bool UnnestStart = StartDepth >= EndDepth;
1345 bool UnnestEnd = EndDepth >= StartDepth;
1346 if (UnnestEnd) {
1347 assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
1348 BeforeLoc));
1349
1350 BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
1351 assert(BeforeLoc.isValid());
1352 EndDepth--;
1353 }
1354 if (UnnestStart) {
1355 assert(SM.isWrittenInSameFile(AfterLoc,
1356 getEndOfFileOrMacro(AfterLoc)));
1357
1358 AfterLoc = getIncludeOrExpansionLoc(AfterLoc);
1359 assert(AfterLoc.isValid());
1360 AfterLoc = getPreciseTokenLocEnd(AfterLoc);
1361 assert(AfterLoc.isValid());
1362 StartDepth--;
1363 }
1364 }
1365 AfterLoc = getPreciseTokenLocEnd(AfterLoc);
1366 // If the start and end locations of the gap are both within the same macro
1367 // file, the range may not be in source order.
1368 if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
1369 return std::nullopt;
1370 if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc) ||
1371 !SpellingRegion(SM, AfterLoc, BeforeLoc).isInSourceOrder())
1372 return std::nullopt;
1373 return {{AfterLoc, BeforeLoc}};
1374 }
1375
1376 /// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
fillGapAreaWithCount__anon413222f00211::CounterCoverageMappingBuilder1377 void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
1378 Counter Count) {
1379 if (StartLoc == EndLoc)
1380 return;
1381 assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
1382 handleFileExit(StartLoc);
1383 size_t Index = pushRegion(Count, StartLoc, EndLoc);
1384 getRegion().setGap(true);
1385 handleFileExit(EndLoc);
1386 popRegions(Index);
1387 }
1388
1389 /// Find a valid range starting with \p StartingLoc and ending before \p
1390 /// BeforeLoc.
findAreaStartingFromTo__anon413222f00211::CounterCoverageMappingBuilder1391 std::optional<SourceRange> findAreaStartingFromTo(SourceLocation StartingLoc,
1392 SourceLocation BeforeLoc) {
1393 // If StartingLoc is in function-like macro, use its start location.
1394 if (StartingLoc.isMacroID()) {
1395 FileID FID = SM.getFileID(StartingLoc);
1396 const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
1397 if (EI->isFunctionMacroExpansion())
1398 StartingLoc = EI->getExpansionLocStart();
1399 }
1400
1401 size_t StartDepth = locationDepth(StartingLoc);
1402 size_t EndDepth = locationDepth(BeforeLoc);
1403 while (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc)) {
1404 bool UnnestStart = StartDepth >= EndDepth;
1405 bool UnnestEnd = EndDepth >= StartDepth;
1406 if (UnnestEnd) {
1407 assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
1408 BeforeLoc));
1409
1410 BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
1411 assert(BeforeLoc.isValid());
1412 EndDepth--;
1413 }
1414 if (UnnestStart) {
1415 assert(SM.isWrittenInSameFile(StartingLoc,
1416 getStartOfFileOrMacro(StartingLoc)));
1417
1418 StartingLoc = getIncludeOrExpansionLoc(StartingLoc);
1419 assert(StartingLoc.isValid());
1420 StartDepth--;
1421 }
1422 }
1423 // If the start and end locations of the gap are both within the same macro
1424 // file, the range may not be in source order.
1425 if (StartingLoc.isMacroID() || BeforeLoc.isMacroID())
1426 return std::nullopt;
1427 if (!SM.isWrittenInSameFile(StartingLoc, BeforeLoc) ||
1428 !SpellingRegion(SM, StartingLoc, BeforeLoc).isInSourceOrder())
1429 return std::nullopt;
1430 return {{StartingLoc, BeforeLoc}};
1431 }
1432
markSkipped__anon413222f00211::CounterCoverageMappingBuilder1433 void markSkipped(SourceLocation StartLoc, SourceLocation BeforeLoc) {
1434 const auto Skipped = findAreaStartingFromTo(StartLoc, BeforeLoc);
1435
1436 if (!Skipped)
1437 return;
1438
1439 const auto NewStartLoc = Skipped->getBegin();
1440 const auto EndLoc = Skipped->getEnd();
1441
1442 if (NewStartLoc == EndLoc)
1443 return;
1444 assert(SpellingRegion(SM, NewStartLoc, EndLoc).isInSourceOrder());
1445 handleFileExit(NewStartLoc);
1446 size_t Index = pushRegion(Counter{}, NewStartLoc, EndLoc);
1447 getRegion().setSkipped(true);
1448 handleFileExit(EndLoc);
1449 popRegions(Index);
1450 }
1451
1452 /// Keep counts of breaks and continues inside loops.
1453 struct BreakContinue {
1454 Counter BreakCount;
1455 Counter ContinueCount;
1456 };
1457 SmallVector<BreakContinue, 8> BreakContinueStack;
1458
CounterCoverageMappingBuilder__anon413222f00211::CounterCoverageMappingBuilder1459 CounterCoverageMappingBuilder(
1460 CoverageMappingModuleGen &CVM,
1461 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
1462 MCDC::State &MCDCState, SourceManager &SM, const LangOptions &LangOpts)
1463 : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
1464 MCDCState(MCDCState), MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {}
1465
1466 /// Write the mapping data to the output stream
write__anon413222f00211::CounterCoverageMappingBuilder1467 void write(llvm::raw_ostream &OS) {
1468 llvm::SmallVector<unsigned, 8> VirtualFileMapping;
1469 gatherFileIDs(VirtualFileMapping);
1470 SourceRegionFilter Filter = emitExpansionRegions();
1471 emitSourceRegions(Filter);
1472 gatherSkippedRegions();
1473
1474 if (MappingRegions.empty())
1475 return;
1476
1477 CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
1478 MappingRegions);
1479 Writer.write(OS);
1480 }
1481
VisitStmt__anon413222f00211::CounterCoverageMappingBuilder1482 void VisitStmt(const Stmt *S) {
1483 if (S->getBeginLoc().isValid())
1484 extendRegion(S);
1485 const Stmt *LastStmt = nullptr;
1486 bool SaveTerminateStmt = HasTerminateStmt;
1487 HasTerminateStmt = false;
1488 GapRegionCounter = Counter::getZero();
1489 for (const Stmt *Child : S->children())
1490 if (Child) {
1491 // If last statement contains terminate statements, add a gap area
1492 // between the two statements.
1493 if (LastStmt && HasTerminateStmt) {
1494 auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
1495 if (Gap)
1496 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
1497 GapRegionCounter);
1498 SaveTerminateStmt = true;
1499 HasTerminateStmt = false;
1500 }
1501 this->Visit(Child);
1502 LastStmt = Child;
1503 }
1504 if (SaveTerminateStmt)
1505 HasTerminateStmt = true;
1506 handleFileExit(getEnd(S));
1507 }
1508
VisitStmtExpr__anon413222f00211::CounterCoverageMappingBuilder1509 void VisitStmtExpr(const StmtExpr *E) {
1510 Visit(E->getSubStmt());
1511 // Any region termination (such as a noreturn CallExpr) within the statement
1512 // expression has been handled by visiting the sub-statement. The visitor
1513 // cannot be at a terminate statement leaving the statement expression.
1514 HasTerminateStmt = false;
1515 }
1516
VisitDecl__anon413222f00211::CounterCoverageMappingBuilder1517 void VisitDecl(const Decl *D) {
1518 Stmt *Body = D->getBody();
1519
1520 // Do not propagate region counts into system headers unless collecting
1521 // coverage from system headers is explicitly enabled.
1522 if (!SystemHeadersCoverage && Body &&
1523 SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
1524 return;
1525
1526 // Do not visit the artificial children nodes of defaulted methods. The
1527 // lexer may not be able to report back precise token end locations for
1528 // these children nodes (llvm.org/PR39822), and moreover users will not be
1529 // able to see coverage for them.
1530 Counter BodyCounter = getRegionCounter(Body);
1531 bool Defaulted = false;
1532 if (auto *Method = dyn_cast<CXXMethodDecl>(D))
1533 Defaulted = Method->isDefaulted();
1534 if (auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
1535 for (auto *Initializer : Ctor->inits()) {
1536 if (Initializer->isWritten()) {
1537 auto *Init = Initializer->getInit();
1538 if (getStart(Init).isValid() && getEnd(Init).isValid())
1539 propagateCounts(BodyCounter, Init);
1540 }
1541 }
1542 }
1543
1544 propagateCounts(BodyCounter, Body,
1545 /*VisitChildren=*/!Defaulted);
1546 assert(RegionStack.empty() && "Regions entered but never exited");
1547 }
1548
VisitReturnStmt__anon413222f00211::CounterCoverageMappingBuilder1549 void VisitReturnStmt(const ReturnStmt *S) {
1550 extendRegion(S);
1551 if (S->getRetValue())
1552 Visit(S->getRetValue());
1553 terminateRegion(S);
1554 }
1555
VisitCoroutineBodyStmt__anon413222f00211::CounterCoverageMappingBuilder1556 void VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) {
1557 extendRegion(S);
1558 Visit(S->getBody());
1559 }
1560
VisitCoreturnStmt__anon413222f00211::CounterCoverageMappingBuilder1561 void VisitCoreturnStmt(const CoreturnStmt *S) {
1562 extendRegion(S);
1563 if (S->getOperand())
1564 Visit(S->getOperand());
1565 terminateRegion(S);
1566 }
1567
VisitCoroutineSuspendExpr__anon413222f00211::CounterCoverageMappingBuilder1568 void VisitCoroutineSuspendExpr(const CoroutineSuspendExpr *E) {
1569 Visit(E->getOperand());
1570 }
1571
VisitCXXThrowExpr__anon413222f00211::CounterCoverageMappingBuilder1572 void VisitCXXThrowExpr(const CXXThrowExpr *E) {
1573 extendRegion(E);
1574 if (E->getSubExpr())
1575 Visit(E->getSubExpr());
1576 terminateRegion(E);
1577 }
1578
VisitGotoStmt__anon413222f00211::CounterCoverageMappingBuilder1579 void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
1580
VisitLabelStmt__anon413222f00211::CounterCoverageMappingBuilder1581 void VisitLabelStmt(const LabelStmt *S) {
1582 Counter LabelCount = getRegionCounter(S);
1583 SourceLocation Start = getStart(S);
1584 // We can't extendRegion here or we risk overlapping with our new region.
1585 handleFileExit(Start);
1586 pushRegion(LabelCount, Start);
1587 Visit(S->getSubStmt());
1588 }
1589
VisitBreakStmt__anon413222f00211::CounterCoverageMappingBuilder1590 void VisitBreakStmt(const BreakStmt *S) {
1591 assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
1592 if (!llvm::EnableSingleByteCoverage)
1593 BreakContinueStack.back().BreakCount = addCounters(
1594 BreakContinueStack.back().BreakCount, getRegion().getCounter());
1595 // FIXME: a break in a switch should terminate regions for all preceding
1596 // case statements, not just the most recent one.
1597 terminateRegion(S);
1598 }
1599
VisitContinueStmt__anon413222f00211::CounterCoverageMappingBuilder1600 void VisitContinueStmt(const ContinueStmt *S) {
1601 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
1602 if (!llvm::EnableSingleByteCoverage)
1603 BreakContinueStack.back().ContinueCount = addCounters(
1604 BreakContinueStack.back().ContinueCount, getRegion().getCounter());
1605 terminateRegion(S);
1606 }
1607
VisitCallExpr__anon413222f00211::CounterCoverageMappingBuilder1608 void VisitCallExpr(const CallExpr *E) {
1609 VisitStmt(E);
1610
1611 // Terminate the region when we hit a noreturn function.
1612 // (This is helpful dealing with switch statements.)
1613 QualType CalleeType = E->getCallee()->getType();
1614 if (getFunctionExtInfo(*CalleeType).getNoReturn())
1615 terminateRegion(E);
1616 }
1617
VisitWhileStmt__anon413222f00211::CounterCoverageMappingBuilder1618 void VisitWhileStmt(const WhileStmt *S) {
1619 extendRegion(S);
1620
1621 Counter ParentCount = getRegion().getCounter();
1622 Counter BodyCount = llvm::EnableSingleByteCoverage
1623 ? getRegionCounter(S->getBody())
1624 : getRegionCounter(S);
1625
1626 // Handle the body first so that we can get the backedge count.
1627 BreakContinueStack.push_back(BreakContinue());
1628 extendRegion(S->getBody());
1629 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1630 BreakContinue BC = BreakContinueStack.pop_back_val();
1631
1632 bool BodyHasTerminateStmt = HasTerminateStmt;
1633 HasTerminateStmt = false;
1634
1635 // Go back to handle the condition.
1636 Counter CondCount =
1637 llvm::EnableSingleByteCoverage
1638 ? getRegionCounter(S->getCond())
1639 : addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1640 auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
1641 assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
1642 llvm::EnableSingleByteCoverage);
1643
1644 propagateCounts(CondCount, S->getCond());
1645 adjustForOutOfOrderTraversal(getEnd(S));
1646
1647 // The body count applies to the area immediately after the increment.
1648 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1649 if (Gap)
1650 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1651
1652 assert(
1653 !llvm::EnableSingleByteCoverage ||
1654 (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
1655 Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
1656 if (!IsCounterEqual(OutCount, ParentCount)) {
1657 pushRegion(OutCount);
1658 GapRegionCounter = OutCount;
1659 if (BodyHasTerminateStmt)
1660 HasTerminateStmt = true;
1661 }
1662
1663 // Create Branch Region around condition.
1664 if (!llvm::EnableSingleByteCoverage)
1665 createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
1666 }
1667
VisitDoStmt__anon413222f00211::CounterCoverageMappingBuilder1668 void VisitDoStmt(const DoStmt *S) {
1669 extendRegion(S);
1670
1671 Counter ParentCount = getRegion().getCounter();
1672 Counter BodyCount = llvm::EnableSingleByteCoverage
1673 ? getRegionCounter(S->getBody())
1674 : getRegionCounter(S);
1675
1676 BreakContinueStack.push_back(BreakContinue());
1677 extendRegion(S->getBody());
1678
1679 Counter BackedgeCount;
1680 if (llvm::EnableSingleByteCoverage)
1681 propagateCounts(BodyCount, S->getBody());
1682 else
1683 BackedgeCount =
1684 propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
1685
1686 BreakContinue BC = BreakContinueStack.pop_back_val();
1687
1688 bool BodyHasTerminateStmt = HasTerminateStmt;
1689 HasTerminateStmt = false;
1690
1691 Counter CondCount = llvm::EnableSingleByteCoverage
1692 ? getRegionCounter(S->getCond())
1693 : addCounters(BackedgeCount, BC.ContinueCount);
1694 auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
1695 assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
1696 llvm::EnableSingleByteCoverage);
1697
1698 propagateCounts(CondCount, S->getCond());
1699
1700 assert(
1701 !llvm::EnableSingleByteCoverage ||
1702 (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
1703 Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
1704 if (!IsCounterEqual(OutCount, ParentCount)) {
1705 pushRegion(OutCount);
1706 GapRegionCounter = OutCount;
1707 if (BodyHasTerminateStmt)
1708 HasTerminateStmt = true;
1709 }
1710
1711 // Create Branch Region around condition.
1712 if (!llvm::EnableSingleByteCoverage)
1713 createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
1714 }
1715
VisitForStmt__anon413222f00211::CounterCoverageMappingBuilder1716 void VisitForStmt(const ForStmt *S) {
1717 extendRegion(S);
1718 if (S->getInit())
1719 Visit(S->getInit());
1720
1721 Counter ParentCount = getRegion().getCounter();
1722 Counter BodyCount = llvm::EnableSingleByteCoverage
1723 ? getRegionCounter(S->getBody())
1724 : getRegionCounter(S);
1725
1726 // The loop increment may contain a break or continue.
1727 if (S->getInc())
1728 BreakContinueStack.emplace_back();
1729
1730 // Handle the body first so that we can get the backedge count.
1731 BreakContinueStack.emplace_back();
1732 extendRegion(S->getBody());
1733 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1734 BreakContinue BodyBC = BreakContinueStack.pop_back_val();
1735
1736 bool BodyHasTerminateStmt = HasTerminateStmt;
1737 HasTerminateStmt = false;
1738
1739 // The increment is essentially part of the body but it needs to include
1740 // the count for all the continue statements.
1741 BreakContinue IncrementBC;
1742 if (const Stmt *Inc = S->getInc()) {
1743 Counter IncCount;
1744 if (llvm::EnableSingleByteCoverage)
1745 IncCount = getRegionCounter(S->getInc());
1746 else
1747 IncCount = addCounters(BackedgeCount, BodyBC.ContinueCount);
1748 propagateCounts(IncCount, Inc);
1749 IncrementBC = BreakContinueStack.pop_back_val();
1750 }
1751
1752 // Go back to handle the condition.
1753 Counter CondCount =
1754 llvm::EnableSingleByteCoverage
1755 ? getRegionCounter(S->getCond())
1756 : addCounters(
1757 addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
1758 IncrementBC.ContinueCount);
1759 auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
1760 assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
1761 llvm::EnableSingleByteCoverage);
1762
1763 if (const Expr *Cond = S->getCond()) {
1764 propagateCounts(CondCount, Cond);
1765 adjustForOutOfOrderTraversal(getEnd(S));
1766 }
1767
1768 // The body count applies to the area immediately after the increment.
1769 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1770 if (Gap)
1771 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1772
1773 assert(!llvm::EnableSingleByteCoverage ||
1774 (BodyBC.BreakCount.isZero() && IncrementBC.BreakCount.isZero()));
1775 Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
1776 BranchCount.Skipped);
1777 if (!IsCounterEqual(OutCount, ParentCount)) {
1778 pushRegion(OutCount);
1779 GapRegionCounter = OutCount;
1780 if (BodyHasTerminateStmt)
1781 HasTerminateStmt = true;
1782 }
1783
1784 // Create Branch Region around condition.
1785 if (!llvm::EnableSingleByteCoverage)
1786 createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
1787 }
1788
VisitCXXForRangeStmt__anon413222f00211::CounterCoverageMappingBuilder1789 void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
1790 extendRegion(S);
1791 if (S->getInit())
1792 Visit(S->getInit());
1793 Visit(S->getLoopVarStmt());
1794 Visit(S->getRangeStmt());
1795
1796 Counter ParentCount = getRegion().getCounter();
1797 Counter BodyCount = llvm::EnableSingleByteCoverage
1798 ? getRegionCounter(S->getBody())
1799 : getRegionCounter(S);
1800
1801 BreakContinueStack.push_back(BreakContinue());
1802 extendRegion(S->getBody());
1803 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1804 BreakContinue BC = BreakContinueStack.pop_back_val();
1805
1806 bool BodyHasTerminateStmt = HasTerminateStmt;
1807 HasTerminateStmt = false;
1808
1809 // The body count applies to the area immediately after the range.
1810 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1811 if (Gap)
1812 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1813
1814 Counter LoopCount =
1815 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1816 auto BranchCount = getBranchCounterPair(S, LoopCount, getRegionCounter(S));
1817 assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
1818 llvm::EnableSingleByteCoverage);
1819 assert(
1820 !llvm::EnableSingleByteCoverage ||
1821 (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
1822
1823 Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
1824 if (!IsCounterEqual(OutCount, ParentCount)) {
1825 pushRegion(OutCount);
1826 GapRegionCounter = OutCount;
1827 if (BodyHasTerminateStmt)
1828 HasTerminateStmt = true;
1829 }
1830
1831 // Create Branch Region around condition.
1832 if (!llvm::EnableSingleByteCoverage)
1833 createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
1834 }
1835
VisitObjCForCollectionStmt__anon413222f00211::CounterCoverageMappingBuilder1836 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
1837 extendRegion(S);
1838 Visit(S->getElement());
1839
1840 Counter ParentCount = getRegion().getCounter();
1841 Counter BodyCount = getRegionCounter(S);
1842
1843 BreakContinueStack.push_back(BreakContinue());
1844 extendRegion(S->getBody());
1845 Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
1846 BreakContinue BC = BreakContinueStack.pop_back_val();
1847
1848 // The body count applies to the area immediately after the collection.
1849 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
1850 if (Gap)
1851 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1852
1853 Counter LoopCount =
1854 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1855 auto BranchCount = getBranchCounterPair(S, LoopCount);
1856 assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount);
1857 Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
1858 if (!IsCounterEqual(OutCount, ParentCount)) {
1859 pushRegion(OutCount);
1860 GapRegionCounter = OutCount;
1861 }
1862 }
1863
VisitSwitchStmt__anon413222f00211::CounterCoverageMappingBuilder1864 void VisitSwitchStmt(const SwitchStmt *S) {
1865 extendRegion(S);
1866 if (S->getInit())
1867 Visit(S->getInit());
1868 Visit(S->getCond());
1869
1870 BreakContinueStack.push_back(BreakContinue());
1871
1872 const Stmt *Body = S->getBody();
1873 extendRegion(Body);
1874 if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
1875 if (!CS->body_empty()) {
1876 // Make a region for the body of the switch. If the body starts with
1877 // a case, that case will reuse this region; otherwise, this covers
1878 // the unreachable code at the beginning of the switch body.
1879 size_t Index = pushRegion(Counter::getZero(), getStart(CS));
1880 getRegion().setGap(true);
1881 Visit(Body);
1882
1883 // Set the end for the body of the switch, if it isn't already set.
1884 for (size_t i = RegionStack.size(); i != Index; --i) {
1885 if (!RegionStack[i - 1].hasEndLoc())
1886 RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
1887 }
1888
1889 popRegions(Index);
1890 }
1891 } else
1892 propagateCounts(Counter::getZero(), Body);
1893 BreakContinue BC = BreakContinueStack.pop_back_val();
1894
1895 if (!BreakContinueStack.empty() && !llvm::EnableSingleByteCoverage)
1896 BreakContinueStack.back().ContinueCount = addCounters(
1897 BreakContinueStack.back().ContinueCount, BC.ContinueCount);
1898
1899 Counter ParentCount = getRegion().getCounter();
1900 Counter ExitCount = getRegionCounter(S);
1901 SourceLocation ExitLoc = getEnd(S);
1902 pushRegion(ExitCount);
1903 GapRegionCounter = ExitCount;
1904
1905 // Ensure that handleFileExit recognizes when the end location is located
1906 // in a different file.
1907 MostRecentLocation = getStart(S);
1908 handleFileExit(ExitLoc);
1909
1910 // When single byte coverage mode is enabled, do not create branch region by
1911 // early returning.
1912 if (llvm::EnableSingleByteCoverage)
1913 return;
1914
1915 // Create a Branch Region around each Case. Subtract the case's
1916 // counter from the Parent counter to track the "False" branch count.
1917 Counter CaseCountSum;
1918 bool HasDefaultCase = false;
1919 const SwitchCase *Case = S->getSwitchCaseList();
1920 for (; Case; Case = Case->getNextSwitchCase()) {
1921 HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
1922 auto CaseCount = createSwitchCaseRegion(Case, ParentCount);
1923 CaseCountSum = addCounters(CaseCountSum, CaseCount, /*Simplify=*/false);
1924 }
1925 // If no explicit default case exists, create a branch region to represent
1926 // the hidden branch, which will be added later by the CodeGen. This region
1927 // will be associated with the switch statement's condition.
1928 if (!HasDefaultCase) {
1929 // Simplify is skipped while building the counters above: it can get
1930 // really slow on top of switches with thousands of cases. Instead,
1931 // trigger simplification by adding zero to the last counter.
1932 CaseCountSum =
1933 addCounters(CaseCountSum, Counter::getZero(), /*Simplify=*/true);
1934
1935 // This is considered as the False count on SwitchStmt.
1936 Counter SwitchFalse = subtractCounters(ParentCount, CaseCountSum);
1937 createBranchRegion(S->getCond(), CaseCountSum, SwitchFalse);
1938 }
1939 }
1940
VisitSwitchCase__anon413222f00211::CounterCoverageMappingBuilder1941 void VisitSwitchCase(const SwitchCase *S) {
1942 extendRegion(S);
1943
1944 SourceMappingRegion &Parent = getRegion();
1945 Counter Count = llvm::EnableSingleByteCoverage
1946 ? getRegionCounter(S)
1947 : addCounters(Parent.getCounter(), getRegionCounter(S));
1948
1949 // Reuse the existing region if it starts at our label. This is typical of
1950 // the first case in a switch.
1951 if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
1952 Parent.setCounter(Count);
1953 else
1954 pushRegion(Count, getStart(S));
1955
1956 GapRegionCounter = Count;
1957
1958 if (const auto *CS = dyn_cast<CaseStmt>(S)) {
1959 Visit(CS->getLHS());
1960 if (const Expr *RHS = CS->getRHS())
1961 Visit(RHS);
1962 }
1963 Visit(S->getSubStmt());
1964 }
1965
coverIfConsteval__anon413222f00211::CounterCoverageMappingBuilder1966 void coverIfConsteval(const IfStmt *S) {
1967 assert(S->isConsteval());
1968
1969 const auto *Then = S->getThen();
1970 const auto *Else = S->getElse();
1971
1972 // It's better for llvm-cov to create a new region with same counter
1973 // so line-coverage can be properly calculated for lines containing
1974 // a skipped region (without it the line is marked uncovered)
1975 const Counter ParentCount = getRegion().getCounter();
1976
1977 extendRegion(S);
1978
1979 if (S->isNegatedConsteval()) {
1980 // ignore 'if consteval'
1981 markSkipped(S->getIfLoc(), getStart(Then));
1982 propagateCounts(ParentCount, Then);
1983
1984 if (Else) {
1985 // ignore 'else <else>'
1986 markSkipped(getEnd(Then), getEnd(Else));
1987 }
1988 } else {
1989 assert(S->isNonNegatedConsteval());
1990 // ignore 'if consteval <then> [else]'
1991 markSkipped(S->getIfLoc(), Else ? getStart(Else) : getEnd(Then));
1992
1993 if (Else)
1994 propagateCounts(ParentCount, Else);
1995 }
1996 }
1997
coverIfConstexpr__anon413222f00211::CounterCoverageMappingBuilder1998 void coverIfConstexpr(const IfStmt *S) {
1999 assert(S->isConstexpr());
2000
2001 // evaluate constant condition...
2002 const bool isTrue =
2003 S->getCond()
2004 ->EvaluateKnownConstInt(CVM.getCodeGenModule().getContext())
2005 .getBoolValue();
2006
2007 extendRegion(S);
2008
2009 // I'm using 'propagateCounts' later as new region is better and allows me
2010 // to properly calculate line coverage in llvm-cov utility
2011 const Counter ParentCount = getRegion().getCounter();
2012
2013 // ignore 'if constexpr ('
2014 SourceLocation startOfSkipped = S->getIfLoc();
2015
2016 if (const auto *Init = S->getInit()) {
2017 const auto start = getStart(Init);
2018 const auto end = getEnd(Init);
2019
2020 // this check is to make sure typedef here which doesn't have valid source
2021 // location won't crash it
2022 if (start.isValid() && end.isValid()) {
2023 markSkipped(startOfSkipped, start);
2024 propagateCounts(ParentCount, Init);
2025 startOfSkipped = getEnd(Init);
2026 }
2027 }
2028
2029 const auto *Then = S->getThen();
2030 const auto *Else = S->getElse();
2031
2032 if (isTrue) {
2033 // ignore '<condition>)'
2034 markSkipped(startOfSkipped, getStart(Then));
2035 propagateCounts(ParentCount, Then);
2036
2037 if (Else)
2038 // ignore 'else <else>'
2039 markSkipped(getEnd(Then), getEnd(Else));
2040 } else {
2041 // ignore '<condition>) <then> [else]'
2042 markSkipped(startOfSkipped, Else ? getStart(Else) : getEnd(Then));
2043
2044 if (Else)
2045 propagateCounts(ParentCount, Else);
2046 }
2047 }
2048
VisitIfStmt__anon413222f00211::CounterCoverageMappingBuilder2049 void VisitIfStmt(const IfStmt *S) {
2050 // "if constexpr" and "if consteval" are not normal conditional statements,
2051 // their discarded statement should be skipped
2052 if (S->isConsteval())
2053 return coverIfConsteval(S);
2054 else if (S->isConstexpr())
2055 return coverIfConstexpr(S);
2056
2057 extendRegion(S);
2058 if (S->getInit())
2059 Visit(S->getInit());
2060
2061 // Extend into the condition before we propagate through it below - this is
2062 // needed to handle macros that generate the "if" but not the condition.
2063 extendRegion(S->getCond());
2064
2065 Counter ParentCount = getRegion().getCounter();
2066 auto [ThenCount, ElseCount] =
2067 (llvm::EnableSingleByteCoverage
2068 ? BranchCounterPair{getRegionCounter(S->getThen()),
2069 (S->getElse() ? getRegionCounter(S->getElse())
2070 : Counter::getZero())}
2071 : getBranchCounterPair(S, ParentCount));
2072
2073 // Emitting a counter for the condition makes it easier to interpret the
2074 // counter for the body when looking at the coverage.
2075 propagateCounts(ParentCount, S->getCond());
2076
2077 // The 'then' count applies to the area immediately after the condition.
2078 std::optional<SourceRange> Gap =
2079 findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
2080 if (Gap)
2081 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
2082
2083 extendRegion(S->getThen());
2084 Counter OutCount = propagateCounts(ThenCount, S->getThen());
2085
2086 if (const Stmt *Else = S->getElse()) {
2087 bool ThenHasTerminateStmt = HasTerminateStmt;
2088 HasTerminateStmt = false;
2089 // The 'else' count applies to the area immediately after the 'then'.
2090 std::optional<SourceRange> Gap =
2091 findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
2092 if (Gap)
2093 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
2094 extendRegion(Else);
2095
2096 Counter ElseOutCount = propagateCounts(ElseCount, Else);
2097 if (!llvm::EnableSingleByteCoverage)
2098 OutCount = addCounters(OutCount, ElseOutCount);
2099
2100 if (ThenHasTerminateStmt)
2101 HasTerminateStmt = true;
2102 } else if (!llvm::EnableSingleByteCoverage)
2103 OutCount = addCounters(OutCount, ElseCount);
2104
2105 if (llvm::EnableSingleByteCoverage)
2106 OutCount = getRegionCounter(S);
2107
2108 if (!IsCounterEqual(OutCount, ParentCount)) {
2109 pushRegion(OutCount);
2110 GapRegionCounter = OutCount;
2111 }
2112
2113 if (!llvm::EnableSingleByteCoverage)
2114 // Create Branch Region around condition.
2115 createBranchRegion(S->getCond(), ThenCount, ElseCount);
2116 }
2117
VisitCXXTryStmt__anon413222f00211::CounterCoverageMappingBuilder2118 void VisitCXXTryStmt(const CXXTryStmt *S) {
2119 extendRegion(S);
2120 // Handle macros that generate the "try" but not the rest.
2121 extendRegion(S->getTryBlock());
2122
2123 Counter ParentCount = getRegion().getCounter();
2124 propagateCounts(ParentCount, S->getTryBlock());
2125
2126 for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
2127 Visit(S->getHandler(I));
2128
2129 Counter ExitCount = getRegionCounter(S);
2130 pushRegion(ExitCount);
2131 }
2132
VisitCXXCatchStmt__anon413222f00211::CounterCoverageMappingBuilder2133 void VisitCXXCatchStmt(const CXXCatchStmt *S) {
2134 propagateCounts(getRegionCounter(S), S->getHandlerBlock());
2135 }
2136
VisitAbstractConditionalOperator__anon413222f00211::CounterCoverageMappingBuilder2137 void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
2138 extendRegion(E);
2139
2140 Counter ParentCount = getRegion().getCounter();
2141 auto [TrueCount, FalseCount] =
2142 (llvm::EnableSingleByteCoverage
2143 ? BranchCounterPair{getRegionCounter(E->getTrueExpr()),
2144 getRegionCounter(E->getFalseExpr())}
2145 : getBranchCounterPair(E, ParentCount));
2146 Counter OutCount;
2147
2148 if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
2149 propagateCounts(ParentCount, BCO->getCommon());
2150 OutCount = TrueCount;
2151 } else {
2152 propagateCounts(ParentCount, E->getCond());
2153 // The 'then' count applies to the area immediately after the condition.
2154 auto Gap =
2155 findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
2156 if (Gap)
2157 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
2158
2159 extendRegion(E->getTrueExpr());
2160 OutCount = propagateCounts(TrueCount, E->getTrueExpr());
2161 }
2162
2163 extendRegion(E->getFalseExpr());
2164 Counter FalseOutCount = propagateCounts(FalseCount, E->getFalseExpr());
2165 if (llvm::EnableSingleByteCoverage)
2166 OutCount = getRegionCounter(E);
2167 else
2168 OutCount = addCounters(OutCount, FalseOutCount);
2169
2170 if (!IsCounterEqual(OutCount, ParentCount)) {
2171 pushRegion(OutCount);
2172 GapRegionCounter = OutCount;
2173 }
2174
2175 // Create Branch Region around condition.
2176 if (!llvm::EnableSingleByteCoverage)
2177 createBranchRegion(E->getCond(), TrueCount, FalseCount);
2178 }
2179
createOrCancelDecision__anon413222f00211::CounterCoverageMappingBuilder2180 void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
2181 unsigned NumConds = MCDCBuilder.getTotalConditionsAndReset(E);
2182 if (NumConds == 0)
2183 return;
2184
2185 // Extract [ID, Conds] to construct the graph.
2186 llvm::SmallVector<mcdc::ConditionIDs> CondIDs(NumConds);
2187 for (const auto &SR : ArrayRef(SourceRegions).slice(Since)) {
2188 if (SR.isMCDCBranch()) {
2189 auto [ID, Conds] = SR.getMCDCBranchParams();
2190 CondIDs[ID] = Conds;
2191 }
2192 }
2193
2194 // Construct the graph and calculate `Indices`.
2195 mcdc::TVIdxBuilder Builder(CondIDs);
2196 unsigned NumTVs = Builder.NumTestVectors;
2197 unsigned MaxTVs = CVM.getCodeGenModule().getCodeGenOpts().MCDCMaxTVs;
2198 assert(MaxTVs < mcdc::TVIdxBuilder::HardMaxTVs);
2199
2200 if (NumTVs > MaxTVs) {
2201 // NumTVs exceeds MaxTVs -- warn and cancel the Decision.
2202 cancelDecision(E, Since, NumTVs, MaxTVs);
2203 return;
2204 }
2205
2206 // Update the state for CodeGenPGO
2207 assert(MCDCState.DecisionByStmt.contains(E));
2208 MCDCState.DecisionByStmt[E] = {
2209 MCDCState.BitmapBits, // Top
2210 std::move(Builder.Indices),
2211 };
2212
2213 auto DecisionParams = mcdc::DecisionParameters{
2214 MCDCState.BitmapBits += NumTVs, // Tail
2215 NumConds,
2216 };
2217
2218 // Create MCDC Decision Region.
2219 createDecisionRegion(E, DecisionParams);
2220 }
2221
2222 // Warn and cancel the Decision.
cancelDecision__anon413222f00211::CounterCoverageMappingBuilder2223 void cancelDecision(const BinaryOperator *E, unsigned Since, int NumTVs,
2224 int MaxTVs) {
2225 auto &Diag = CVM.getCodeGenModule().getDiags();
2226 unsigned DiagID =
2227 Diag.getCustomDiagID(DiagnosticsEngine::Warning,
2228 "unsupported MC/DC boolean expression; "
2229 "number of test vectors (%0) exceeds max (%1). "
2230 "Expression will not be covered");
2231 Diag.Report(E->getBeginLoc(), DiagID) << NumTVs << MaxTVs;
2232
2233 // Restore MCDCBranch to Branch.
2234 for (auto &SR : MutableArrayRef(SourceRegions).slice(Since)) {
2235 assert(!SR.isMCDCDecision() && "Decision shouldn't be seen here");
2236 if (SR.isMCDCBranch())
2237 SR.resetMCDCParams();
2238 }
2239
2240 // Tell CodeGenPGO not to instrument.
2241 MCDCState.DecisionByStmt.erase(E);
2242 }
2243
2244 /// Check if E belongs to system headers.
isExprInSystemHeader__anon413222f00211::CounterCoverageMappingBuilder2245 bool isExprInSystemHeader(const BinaryOperator *E) const {
2246 return (!SystemHeadersCoverage &&
2247 SM.isInSystemHeader(SM.getSpellingLoc(E->getOperatorLoc())) &&
2248 SM.isInSystemHeader(SM.getSpellingLoc(E->getBeginLoc())) &&
2249 SM.isInSystemHeader(SM.getSpellingLoc(E->getEndLoc())));
2250 }
2251
VisitBinLAnd__anon413222f00211::CounterCoverageMappingBuilder2252 void VisitBinLAnd(const BinaryOperator *E) {
2253 if (isExprInSystemHeader(E)) {
2254 LeafExprSet.insert(E);
2255 return;
2256 }
2257
2258 bool IsRootNode = MCDCBuilder.isIdle();
2259
2260 unsigned SourceRegionsSince = SourceRegions.size();
2261
2262 // Keep track of Binary Operator and assign MCDC condition IDs.
2263 MCDCBuilder.pushAndAssignIDs(E);
2264
2265 extendRegion(E->getLHS());
2266 propagateCounts(getRegion().getCounter(), E->getLHS());
2267 handleFileExit(getEnd(E->getLHS()));
2268
2269 // Track LHS True/False Decision.
2270 const auto DecisionLHS = MCDCBuilder.pop();
2271
2272 // Counter tracks the right hand side of a logical and operator.
2273 extendRegion(E->getRHS());
2274 propagateCounts(getRegionCounter(E), E->getRHS());
2275
2276 if (llvm::EnableSingleByteCoverage)
2277 return;
2278
2279 // Track RHS True/False Decision.
2280 const auto DecisionRHS = MCDCBuilder.back();
2281
2282 // Extract the Parent Region Counter.
2283 Counter ParentCnt = getRegion().getCounter();
2284
2285 // Extract the RHS's Execution Counter.
2286 auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);
2287
2288 // Extract the RHS's "True" Instance Counter.
2289 auto [RHSTrueCnt, RHSExitCnt] =
2290 getBranchCounterPair(E->getRHS(), RHSExecCnt);
2291
2292 // Create Branch Region around LHS condition.
2293 createBranchRegion(E->getLHS(), RHSExecCnt, LHSExitCnt, DecisionLHS);
2294
2295 // Create Branch Region around RHS condition.
2296 createBranchRegion(E->getRHS(), RHSTrueCnt, RHSExitCnt, DecisionRHS);
2297
2298 // Create MCDC Decision Region if at top-level (root).
2299 if (IsRootNode)
2300 createOrCancelDecision(E, SourceRegionsSince);
2301 }
2302
2303 // Determine whether the right side of OR operation need to be visited.
shouldVisitRHS__anon413222f00211::CounterCoverageMappingBuilder2304 bool shouldVisitRHS(const Expr *LHS) {
2305 bool LHSIsTrue = false;
2306 bool LHSIsConst = false;
2307 if (!LHS->isValueDependent())
2308 LHSIsConst = LHS->EvaluateAsBooleanCondition(
2309 LHSIsTrue, CVM.getCodeGenModule().getContext());
2310 return !LHSIsConst || (LHSIsConst && !LHSIsTrue);
2311 }
2312
VisitBinLOr__anon413222f00211::CounterCoverageMappingBuilder2313 void VisitBinLOr(const BinaryOperator *E) {
2314 if (isExprInSystemHeader(E)) {
2315 LeafExprSet.insert(E);
2316 return;
2317 }
2318
2319 bool IsRootNode = MCDCBuilder.isIdle();
2320
2321 unsigned SourceRegionsSince = SourceRegions.size();
2322
2323 // Keep track of Binary Operator and assign MCDC condition IDs.
2324 MCDCBuilder.pushAndAssignIDs(E);
2325
2326 extendRegion(E->getLHS());
2327 Counter OutCount = propagateCounts(getRegion().getCounter(), E->getLHS());
2328 handleFileExit(getEnd(E->getLHS()));
2329
2330 // Track LHS True/False Decision.
2331 const auto DecisionLHS = MCDCBuilder.pop();
2332
2333 // Counter tracks the right hand side of a logical or operator.
2334 extendRegion(E->getRHS());
2335 propagateCounts(getRegionCounter(E), E->getRHS());
2336
2337 if (llvm::EnableSingleByteCoverage)
2338 return;
2339
2340 // Track RHS True/False Decision.
2341 const auto DecisionRHS = MCDCBuilder.back();
2342
2343 // Extract the Parent Region Counter.
2344 Counter ParentCnt = getRegion().getCounter();
2345
2346 // Extract the RHS's Execution Counter.
2347 auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);
2348
2349 // Extract the RHS's "False" Instance Counter.
2350 auto [RHSFalseCnt, RHSExitCnt] =
2351 getBranchCounterPair(E->getRHS(), RHSExecCnt);
2352
2353 if (!shouldVisitRHS(E->getLHS())) {
2354 GapRegionCounter = OutCount;
2355 }
2356
2357 // Create Branch Region around LHS condition.
2358 createBranchRegion(E->getLHS(), LHSExitCnt, RHSExecCnt, DecisionLHS);
2359
2360 // Create Branch Region around RHS condition.
2361 createBranchRegion(E->getRHS(), RHSExitCnt, RHSFalseCnt, DecisionRHS);
2362
2363 // Create MCDC Decision Region if at top-level (root).
2364 if (IsRootNode)
2365 createOrCancelDecision(E, SourceRegionsSince);
2366 }
2367
VisitLambdaExpr__anon413222f00211::CounterCoverageMappingBuilder2368 void VisitLambdaExpr(const LambdaExpr *LE) {
2369 // Lambdas are treated as their own functions for now, so we shouldn't
2370 // propagate counts into them.
2371 }
2372
VisitArrayInitLoopExpr__anon413222f00211::CounterCoverageMappingBuilder2373 void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *AILE) {
2374 Visit(AILE->getCommonExpr()->getSourceExpr());
2375 }
2376
VisitPseudoObjectExpr__anon413222f00211::CounterCoverageMappingBuilder2377 void VisitPseudoObjectExpr(const PseudoObjectExpr *POE) {
2378 // Just visit syntatic expression as this is what users actually write.
2379 VisitStmt(POE->getSyntacticForm());
2380 }
2381
VisitOpaqueValueExpr__anon413222f00211::CounterCoverageMappingBuilder2382 void VisitOpaqueValueExpr(const OpaqueValueExpr* OVE) {
2383 if (OVE->isUnique())
2384 Visit(OVE->getSourceExpr());
2385 }
2386 };
2387
2388 } // end anonymous namespace
2389
dump(llvm::raw_ostream & OS,StringRef FunctionName,ArrayRef<CounterExpression> Expressions,ArrayRef<CounterMappingRegion> Regions)2390 static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
2391 ArrayRef<CounterExpression> Expressions,
2392 ArrayRef<CounterMappingRegion> Regions) {
2393 OS << FunctionName << ":\n";
2394 CounterMappingContext Ctx(Expressions);
2395 for (const auto &R : Regions) {
2396 OS.indent(2);
2397 switch (R.Kind) {
2398 case CounterMappingRegion::CodeRegion:
2399 break;
2400 case CounterMappingRegion::ExpansionRegion:
2401 OS << "Expansion,";
2402 break;
2403 case CounterMappingRegion::SkippedRegion:
2404 OS << "Skipped,";
2405 break;
2406 case CounterMappingRegion::GapRegion:
2407 OS << "Gap,";
2408 break;
2409 case CounterMappingRegion::BranchRegion:
2410 case CounterMappingRegion::MCDCBranchRegion:
2411 OS << "Branch,";
2412 break;
2413 case CounterMappingRegion::MCDCDecisionRegion:
2414 OS << "Decision,";
2415 break;
2416 }
2417
2418 OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
2419 << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
2420
2421 if (const auto *DecisionParams =
2422 std::get_if<mcdc::DecisionParameters>(&R.MCDCParams)) {
2423 OS << "M:" << DecisionParams->BitmapIdx;
2424 OS << ", C:" << DecisionParams->NumConditions;
2425 } else {
2426 Ctx.dump(R.Count, OS);
2427
2428 if (R.isBranch()) {
2429 OS << ", ";
2430 Ctx.dump(R.FalseCount, OS);
2431 }
2432 }
2433
2434 if (const auto *BranchParams =
2435 std::get_if<mcdc::BranchParameters>(&R.MCDCParams)) {
2436 OS << " [" << BranchParams->ID + 1 << ","
2437 << BranchParams->Conds[true] + 1;
2438 OS << "," << BranchParams->Conds[false] + 1 << "] ";
2439 }
2440
2441 if (R.Kind == CounterMappingRegion::ExpansionRegion)
2442 OS << " (Expanded file = " << R.ExpandedFileID << ")";
2443 OS << "\n";
2444 }
2445 }
2446
CoverageMappingModuleGen(CodeGenModule & CGM,CoverageSourceInfo & SourceInfo)2447 CoverageMappingModuleGen::CoverageMappingModuleGen(
2448 CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
2449 : CGM(CGM), SourceInfo(SourceInfo) {}
2450
getCurrentDirname()2451 std::string CoverageMappingModuleGen::getCurrentDirname() {
2452 if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
2453 return CGM.getCodeGenOpts().CoverageCompilationDir;
2454
2455 SmallString<256> CWD;
2456 llvm::sys::fs::current_path(CWD);
2457 return CWD.str().str();
2458 }
2459
normalizeFilename(StringRef Filename)2460 std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
2461 llvm::SmallString<256> Path(Filename);
2462 llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
2463
2464 /// Traverse coverage prefix map in reverse order because prefix replacements
2465 /// are applied in reverse order starting from the last one when multiple
2466 /// prefix replacement options are provided.
2467 for (const auto &[From, To] :
2468 llvm::reverse(CGM.getCodeGenOpts().CoveragePrefixMap)) {
2469 if (llvm::sys::path::replace_path_prefix(Path, From, To))
2470 break;
2471 }
2472 return Path.str().str();
2473 }
2474
getInstrProfSection(const CodeGenModule & CGM,llvm::InstrProfSectKind SK)2475 static std::string getInstrProfSection(const CodeGenModule &CGM,
2476 llvm::InstrProfSectKind SK) {
2477 return llvm::getInstrProfSectionName(
2478 SK, CGM.getContext().getTargetInfo().getTriple().getObjectFormat());
2479 }
2480
emitFunctionMappingRecord(const FunctionInfo & Info,uint64_t FilenamesRef)2481 void CoverageMappingModuleGen::emitFunctionMappingRecord(
2482 const FunctionInfo &Info, uint64_t FilenamesRef) {
2483 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
2484
2485 // Assign a name to the function record. This is used to merge duplicates.
2486 std::string FuncRecordName = "__covrec_" + llvm::utohexstr(Info.NameHash);
2487
2488 // A dummy description for a function included-but-not-used in a TU can be
2489 // replaced by full description provided by a different TU. The two kinds of
2490 // descriptions play distinct roles: therefore, assign them different names
2491 // to prevent `linkonce_odr` merging.
2492 if (Info.IsUsed)
2493 FuncRecordName += "u";
2494
2495 // Create the function record type.
2496 const uint64_t NameHash = Info.NameHash;
2497 const uint64_t FuncHash = Info.FuncHash;
2498 const std::string &CoverageMapping = Info.CoverageMapping;
2499 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
2500 llvm::Type *FunctionRecordTypes[] = {
2501 #include "llvm/ProfileData/InstrProfData.inc"
2502 };
2503 auto *FunctionRecordTy =
2504 llvm::StructType::get(Ctx, ArrayRef(FunctionRecordTypes),
2505 /*isPacked=*/true);
2506
2507 // Create the function record constant.
2508 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
2509 llvm::Constant *FunctionRecordVals[] = {
2510 #include "llvm/ProfileData/InstrProfData.inc"
2511 };
2512 auto *FuncRecordConstant =
2513 llvm::ConstantStruct::get(FunctionRecordTy, ArrayRef(FunctionRecordVals));
2514
2515 // Create the function record global.
2516 auto *FuncRecord = new llvm::GlobalVariable(
2517 CGM.getModule(), FunctionRecordTy, /*isConstant=*/true,
2518 llvm::GlobalValue::LinkOnceODRLinkage, FuncRecordConstant,
2519 FuncRecordName);
2520 FuncRecord->setVisibility(llvm::GlobalValue::HiddenVisibility);
2521 FuncRecord->setSection(getInstrProfSection(CGM, llvm::IPSK_covfun));
2522 FuncRecord->setAlignment(llvm::Align(8));
2523 if (CGM.supportsCOMDAT())
2524 FuncRecord->setComdat(CGM.getModule().getOrInsertComdat(FuncRecordName));
2525
2526 // Make sure the data doesn't get deleted.
2527 CGM.addUsedGlobal(FuncRecord);
2528 }
2529
addFunctionMappingRecord(llvm::GlobalVariable * NamePtr,StringRef NameValue,uint64_t FuncHash,const std::string & CoverageMapping,bool IsUsed)2530 void CoverageMappingModuleGen::addFunctionMappingRecord(
2531 llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
2532 const std::string &CoverageMapping, bool IsUsed) {
2533 const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue);
2534 FunctionRecords.push_back({NameHash, FuncHash, CoverageMapping, IsUsed});
2535
2536 if (!IsUsed)
2537 FunctionNames.push_back(NamePtr);
2538
2539 if (CGM.getCodeGenOpts().DumpCoverageMapping) {
2540 // Dump the coverage mapping data for this function by decoding the
2541 // encoded data. This allows us to dump the mapping regions which were
2542 // also processed by the CoverageMappingWriter which performs
2543 // additional minimization operations such as reducing the number of
2544 // expressions.
2545 llvm::SmallVector<std::string, 16> FilenameStrs;
2546 std::vector<StringRef> Filenames;
2547 std::vector<CounterExpression> Expressions;
2548 std::vector<CounterMappingRegion> Regions;
2549 FilenameStrs.resize(FileEntries.size() + 1);
2550 FilenameStrs[0] = normalizeFilename(getCurrentDirname());
2551 for (const auto &Entry : FileEntries) {
2552 auto I = Entry.second;
2553 FilenameStrs[I] = normalizeFilename(Entry.first.getName());
2554 }
2555 ArrayRef<std::string> FilenameRefs = llvm::ArrayRef(FilenameStrs);
2556 RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
2557 Expressions, Regions);
2558 if (Reader.read())
2559 return;
2560 dump(llvm::outs(), NameValue, Expressions, Regions);
2561 }
2562 }
2563
emit()2564 void CoverageMappingModuleGen::emit() {
2565 if (FunctionRecords.empty())
2566 return;
2567 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
2568 auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
2569
2570 // Create the filenames and merge them with coverage mappings
2571 llvm::SmallVector<std::string, 16> FilenameStrs;
2572 FilenameStrs.resize(FileEntries.size() + 1);
2573 // The first filename is the current working directory.
2574 FilenameStrs[0] = normalizeFilename(getCurrentDirname());
2575 for (const auto &Entry : FileEntries) {
2576 auto I = Entry.second;
2577 FilenameStrs[I] = normalizeFilename(Entry.first.getName());
2578 }
2579
2580 std::string Filenames;
2581 {
2582 llvm::raw_string_ostream OS(Filenames);
2583 CoverageFilenamesSectionWriter(FilenameStrs).write(OS);
2584 }
2585 auto *FilenamesVal =
2586 llvm::ConstantDataArray::getString(Ctx, Filenames, false);
2587 const int64_t FilenamesRef = llvm::IndexedInstrProf::ComputeHash(Filenames);
2588
2589 // Emit the function records.
2590 for (const FunctionInfo &Info : FunctionRecords)
2591 emitFunctionMappingRecord(Info, FilenamesRef);
2592
2593 const unsigned NRecords = 0;
2594 const size_t FilenamesSize = Filenames.size();
2595 const unsigned CoverageMappingSize = 0;
2596 llvm::Type *CovDataHeaderTypes[] = {
2597 #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
2598 #include "llvm/ProfileData/InstrProfData.inc"
2599 };
2600 auto CovDataHeaderTy =
2601 llvm::StructType::get(Ctx, ArrayRef(CovDataHeaderTypes));
2602 llvm::Constant *CovDataHeaderVals[] = {
2603 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
2604 #include "llvm/ProfileData/InstrProfData.inc"
2605 };
2606 auto CovDataHeaderVal =
2607 llvm::ConstantStruct::get(CovDataHeaderTy, ArrayRef(CovDataHeaderVals));
2608
2609 // Create the coverage data record
2610 llvm::Type *CovDataTypes[] = {CovDataHeaderTy, FilenamesVal->getType()};
2611 auto CovDataTy = llvm::StructType::get(Ctx, ArrayRef(CovDataTypes));
2612 llvm::Constant *TUDataVals[] = {CovDataHeaderVal, FilenamesVal};
2613 auto CovDataVal = llvm::ConstantStruct::get(CovDataTy, ArrayRef(TUDataVals));
2614 auto CovData = new llvm::GlobalVariable(
2615 CGM.getModule(), CovDataTy, true, llvm::GlobalValue::PrivateLinkage,
2616 CovDataVal, llvm::getCoverageMappingVarName());
2617
2618 CovData->setSection(getInstrProfSection(CGM, llvm::IPSK_covmap));
2619 CovData->setAlignment(llvm::Align(8));
2620
2621 // Make sure the data doesn't get deleted.
2622 CGM.addUsedGlobal(CovData);
2623 // Create the deferred function records array
2624 if (!FunctionNames.empty()) {
2625 auto AddrSpace = FunctionNames.front()->getType()->getPointerAddressSpace();
2626 auto NamesArrTy = llvm::ArrayType::get(
2627 llvm::PointerType::get(Ctx, AddrSpace), FunctionNames.size());
2628 auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
2629 // This variable will *NOT* be emitted to the object file. It is used
2630 // to pass the list of names referenced to codegen.
2631 new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
2632 llvm::GlobalValue::InternalLinkage, NamesArrVal,
2633 llvm::getCoverageUnusedNamesVarName());
2634 }
2635 }
2636
getFileID(FileEntryRef File)2637 unsigned CoverageMappingModuleGen::getFileID(FileEntryRef File) {
2638 return FileEntries.try_emplace(File, FileEntries.size() + 1).first->second;
2639 }
2640
emitCounterMapping(const Decl * D,llvm::raw_ostream & OS)2641 void CoverageMappingGen::emitCounterMapping(const Decl *D,
2642 llvm::raw_ostream &OS) {
2643 assert(CounterMap && MCDCState);
2644 CounterCoverageMappingBuilder Walker(CVM, *CounterMap, *MCDCState, SM,
2645 LangOpts);
2646 Walker.VisitDecl(D);
2647 Walker.write(OS);
2648 }
2649
emitEmptyMapping(const Decl * D,llvm::raw_ostream & OS)2650 void CoverageMappingGen::emitEmptyMapping(const Decl *D,
2651 llvm::raw_ostream &OS) {
2652 EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
2653 Walker.VisitDecl(D);
2654 Walker.write(OS);
2655 }
2656