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