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