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