diff options
Diffstat (limited to 'lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r-- | lib/CodeGen/CoverageMappingGen.cpp | 153 |
1 files changed, 72 insertions, 81 deletions
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 89a30dc7040c..2d8446463594 100644 --- a/lib/CodeGen/CoverageMappingGen.cpp +++ b/lib/CodeGen/CoverageMappingGen.cpp @@ -35,14 +35,14 @@ void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) { namespace { -/// \brief A region of source code that can be mapped to a counter. +/// A region of source code that can be mapped to a counter. class SourceMappingRegion { Counter Count; - /// \brief The region's starting location. + /// The region's starting location. Optional<SourceLocation> LocStart; - /// \brief The region's ending location. + /// The region's ending location. Optional<SourceLocation> LocEnd; /// Whether this region should be emitted after its parent is emitted. @@ -74,7 +74,10 @@ public: bool hasEndLoc() const { return LocEnd.hasValue(); } - void setEndLoc(SourceLocation Loc) { LocEnd = Loc; } + void setEndLoc(SourceLocation Loc) { + assert(Loc.isValid() && "Setting an invalid end location"); + LocEnd = Loc; + } SourceLocation getEndLoc() const { assert(LocEnd && "Region has no end location"); @@ -123,7 +126,7 @@ struct SpellingRegion { } }; -/// \brief Provides the common functionality for the different +/// Provides the common functionality for the different /// coverage mapping region builders. class CoverageMappingBuilder { public: @@ -132,17 +135,17 @@ public: const LangOptions &LangOpts; private: - /// \brief Map of clang's FileIDs to IDs used for coverage mapping. + /// Map of clang's FileIDs to IDs used for coverage mapping. llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8> FileIDMapping; public: - /// \brief The coverage mapping regions for this function + /// The coverage mapping regions for this function llvm::SmallVector<CounterMappingRegion, 32> MappingRegions; - /// \brief The source mapping regions for this function. + /// The source mapping regions for this function. std::vector<SourceMappingRegion> SourceRegions; - /// \brief A set of regions which can be used as a filter. + /// A set of regions which can be used as a filter. /// /// It is produced by emitExpansionRegions() and is used in /// emitSourceRegions() to suppress producing code regions if @@ -154,7 +157,7 @@ public: const LangOptions &LangOpts) : CVM(CVM), SM(SM), LangOpts(LangOpts) {} - /// \brief Return the precise end location for the given token. + /// Return the precise end location for the given token. SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) { // We avoid getLocForEndOfToken here, because it doesn't do what we want for // macro locations, which we just treat as expanded files. @@ -163,14 +166,14 @@ public: return Loc.getLocWithOffset(TokLen); } - /// \brief Return the start location of an included file or expanded macro. + /// Return the start location of an included file or expanded macro. SourceLocation getStartOfFileOrMacro(SourceLocation Loc) { if (Loc.isMacroID()) return Loc.getLocWithOffset(-SM.getFileOffset(Loc)); return SM.getLocForStartOfFile(SM.getFileID(Loc)); } - /// \brief Return the end location of an included file or expanded macro. + /// Return the end location of an included file or expanded macro. SourceLocation getEndOfFileOrMacro(SourceLocation Loc) { if (Loc.isMacroID()) return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) - @@ -178,18 +181,18 @@ public: return SM.getLocForEndOfFile(SM.getFileID(Loc)); } - /// \brief Find out where the current file is included or macro is expanded. + /// Find out where the current file is included or macro is expanded. SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) { - return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).first + return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin() : SM.getIncludeLoc(SM.getFileID(Loc)); } - /// \brief Return true if \c Loc is a location in a built-in macro. + /// Return true if \c Loc is a location in a built-in macro. bool isInBuiltin(SourceLocation Loc) { return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>"; } - /// \brief Check whether \c Loc is included or expanded from \c Parent. + /// Check whether \c Loc is included or expanded from \c Parent. bool isNestedIn(SourceLocation Loc, FileID Parent) { do { Loc = getIncludeOrExpansionLoc(Loc); @@ -199,23 +202,23 @@ public: return true; } - /// \brief Get the start of \c S ignoring macro arguments and builtin macros. + /// Get the start of \c S ignoring macro arguments and builtin macros. SourceLocation getStart(const Stmt *S) { SourceLocation Loc = S->getLocStart(); while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc)) - Loc = SM.getImmediateExpansionRange(Loc).first; + Loc = SM.getImmediateExpansionRange(Loc).getBegin(); return Loc; } - /// \brief Get the end of \c S ignoring macro arguments and builtin macros. + /// Get the end of \c S ignoring macro arguments and builtin macros. SourceLocation getEnd(const Stmt *S) { SourceLocation Loc = S->getLocEnd(); while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc)) - Loc = SM.getImmediateExpansionRange(Loc).first; + Loc = SM.getImmediateExpansionRange(Loc).getBegin(); return getPreciseTokenLocEnd(Loc); } - /// \brief Find the set of files we have regions for and assign IDs + /// Find the set of files we have regions for and assign IDs /// /// Fills \c Mapping with the virtual file mapping needed to write out /// coverage and collects the necessary file information to emit source and @@ -255,7 +258,7 @@ public: } } - /// \brief Get the coverage mapping file ID for \c Loc. + /// Get the coverage mapping file ID for \c Loc. /// /// If such file id doesn't exist, return None. Optional<unsigned> getCoverageFileID(SourceLocation Loc) { @@ -265,7 +268,7 @@ public: return None; } - /// \brief Gather all the regions that were skipped by the preprocessor + /// Gather all the regions that were skipped by the preprocessor /// using the constructs like #if. void gatherSkippedRegions() { /// An array of the minimum lineStarts and the maximum lineEnds @@ -295,14 +298,14 @@ public: auto Region = CounterMappingRegion::makeSkipped( *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd); // Make sure that we only collect the regions that are inside - // the souce code of this function. + // the source code of this function. if (Region.LineStart >= FileLineRanges[*CovFileID].first && Region.LineEnd <= FileLineRanges[*CovFileID].second) MappingRegions.push_back(Region); } } - /// \brief Generate the coverage counter mapping regions from collected + /// Generate the coverage counter mapping regions from collected /// source regions. void emitSourceRegions(const SourceRegionFilter &Filter) { for (const auto &Region : SourceRegions) { @@ -347,7 +350,7 @@ public: } } - /// \brief Generate expansion regions for each virtual file we've seen. + /// Generate expansion regions for each virtual file we've seen. SourceRegionFilter emitExpansionRegions() { SourceRegionFilter Filter; for (const auto &FM : FileIDMapping) { @@ -377,7 +380,7 @@ public: } }; -/// \brief Creates unreachable coverage regions for the functions that +/// Creates unreachable coverage regions for the functions that /// are not emitted. struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder { EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM, @@ -411,7 +414,7 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder { SourceRegions.emplace_back(Counter(), Start, End); } - /// \brief Write the mapping data to the output stream + /// Write the mapping data to the output stream void write(llvm::raw_ostream &OS) { SmallVector<unsigned, 16> FileIDMapping; gatherFileIDs(FileIDMapping); @@ -425,15 +428,15 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder { } }; -/// \brief A StmtVisitor that creates coverage mapping regions which map +/// A StmtVisitor that creates coverage mapping regions which map /// from the source code locations to the PGO counters. struct CounterCoverageMappingBuilder : public CoverageMappingBuilder, public ConstStmtVisitor<CounterCoverageMappingBuilder> { - /// \brief The map of statements to count values. + /// The map of statements to count values. llvm::DenseMap<const Stmt *, unsigned> &CounterMap; - /// \brief A stack of currently live regions. + /// A stack of currently live regions. std::vector<SourceMappingRegion> RegionStack; /// The currently deferred region: its end location and count can be set once @@ -442,7 +445,7 @@ struct CounterCoverageMappingBuilder CounterExpressionBuilder Builder; - /// \brief A location in the most recently visited file or macro. + /// A location in the most recently visited file or macro. /// /// This is used to adjust the active source regions appropriately when /// expressions cross file or macro boundaries. @@ -451,12 +454,12 @@ struct CounterCoverageMappingBuilder /// Location of the last terminated region. Optional<std::pair<SourceLocation, size_t>> LastTerminatedRegion; - /// \brief Return a counter for the subtraction of \c RHS from \c LHS + /// Return a counter for the subtraction of \c RHS from \c LHS Counter subtractCounters(Counter LHS, Counter RHS) { return Builder.subtract(LHS, RHS); } - /// \brief Return a counter for the sum of \c LHS and \c RHS. + /// Return a counter for the sum of \c LHS and \c RHS. Counter addCounters(Counter LHS, Counter RHS) { return Builder.add(LHS, RHS); } @@ -465,14 +468,14 @@ struct CounterCoverageMappingBuilder return addCounters(addCounters(C1, C2), C3); } - /// \brief Return the region counter for the given statement. + /// Return the region counter for the given statement. /// /// This should only be called on statements that have a dedicated counter. Counter getRegionCounter(const Stmt *S) { return Counter::getCounter(CounterMap[S]); } - /// \brief Push a region onto the stack. + /// Push a region onto the stack. /// /// Returns the index on the stack where the region was pushed. This can be /// used with popRegions to exit a "scope", ending the region that was pushed. @@ -549,7 +552,7 @@ struct CounterCoverageMappingBuilder completeDeferred(Count, DeferredEndLoc); } - /// \brief Pop regions from the stack into the function's list of regions. + /// Pop regions from the stack into the function's list of regions. /// /// Adds all regions from \c ParentIndex to the top of the stack to the /// function's \c SourceRegions. @@ -616,13 +619,13 @@ struct CounterCoverageMappingBuilder assert(!ParentOfDeferredRegion && "Deferred region with no parent"); } - /// \brief Return the currently active region. + /// Return the currently active region. SourceMappingRegion &getRegion() { assert(!RegionStack.empty() && "statement has no region"); return RegionStack.back(); } - /// \brief Propagate counts through the children of \c S. + /// Propagate counts through the children of \c S. Counter propagateCounts(Counter TopCount, const Stmt *S) { SourceLocation StartLoc = getStart(S); SourceLocation EndLoc = getEnd(S); @@ -639,7 +642,7 @@ struct CounterCoverageMappingBuilder return ExitCount; } - /// \brief Check whether a region with bounds \c StartLoc and \c EndLoc + /// Check whether a region with bounds \c StartLoc and \c EndLoc /// is already added to \c SourceRegions. bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc) { return SourceRegions.rend() != @@ -650,7 +653,7 @@ struct CounterCoverageMappingBuilder }); } - /// \brief Adjust the most recently visited location to \c EndLoc. + /// Adjust the most recently visited location to \c EndLoc. /// /// This should be used after visiting any statements in non-source order. void adjustForOutOfOrderTraversal(SourceLocation EndLoc) { @@ -667,7 +670,7 @@ struct CounterCoverageMappingBuilder MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation); } - /// \brief Adjust regions and state when \c NewLoc exits a file. + /// Adjust regions and state when \c NewLoc exits a file. /// /// If moving from our most recently tracked location to \c NewLoc exits any /// files, this adjusts our current region stack and creates the file regions @@ -734,7 +737,7 @@ struct CounterCoverageMappingBuilder MostRecentLocation = NewLoc; } - /// \brief Ensure that \c S is included in the current region. + /// Ensure that \c S is included in the current region. void extendRegion(const Stmt *S) { SourceMappingRegion &Region = getRegion(); SourceLocation StartLoc = getStart(S); @@ -746,7 +749,7 @@ struct CounterCoverageMappingBuilder completeDeferred(Region.getCounter(), StartLoc); } - /// \brief Mark \c S as a terminator, starting a zero region. + /// Mark \c S as a terminator, starting a zero region. void terminateRegion(const Stmt *S) { extendRegion(S); SourceMappingRegion &Region = getRegion(); @@ -791,7 +794,7 @@ struct CounterCoverageMappingBuilder popRegions(Index); } - /// \brief Keep counts of breaks and continues inside loops. + /// Keep counts of breaks and continues inside loops. struct BreakContinue { Counter BreakCount; Counter ContinueCount; @@ -805,7 +808,7 @@ struct CounterCoverageMappingBuilder : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap), DeferredRegion(None) {} - /// \brief Write the mapping data to the output stream + /// Write the mapping data to the output stream void write(llvm::raw_ostream &OS) { llvm::SmallVector<unsigned, 8> VirtualFileMapping; gatherFileIDs(VirtualFileMapping); @@ -831,22 +834,6 @@ struct CounterCoverageMappingBuilder handleFileExit(getEnd(S)); } - /// Determine whether the final deferred region emitted in \p Body should be - /// discarded. - static bool discardFinalDeferredRegionInDecl(Stmt *Body) { - if (auto *CS = dyn_cast<CompoundStmt>(Body)) { - Stmt *LastStmt = CS->body_back(); - if (auto *IfElse = dyn_cast<IfStmt>(LastStmt)) { - if (auto *Else = dyn_cast_or_null<CompoundStmt>(IfElse->getElse())) - LastStmt = Else->body_back(); - else - LastStmt = IfElse->getElse(); - } - return dyn_cast_or_null<ReturnStmt>(LastStmt); - } - return false; - } - void VisitDecl(const Decl *D) { assert(!DeferredRegion && "Deferred region never completed"); @@ -856,17 +843,13 @@ struct CounterCoverageMappingBuilder if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body)))) return; - Counter ExitCount = propagateCounts(getRegionCounter(Body), Body); + propagateCounts(getRegionCounter(Body), Body); assert(RegionStack.empty() && "Regions entered but never exited"); - if (DeferredRegion) { - // Complete (or discard) any deferred regions introduced by the last - // statement. - if (discardFinalDeferredRegionInDecl(Body)) - DeferredRegion = None; - else - popRegions(completeDeferred(ExitCount, getEnd(Body))); - } + // Discard the last uncompleted deferred region in a decl, if one exists. + // This prevents lines at the end of a function containing only whitespace + // or closing braces from being marked as uncovered. + DeferredRegion = None; } void VisitReturnStmt(const ReturnStmt *S) { @@ -889,6 +872,7 @@ struct CounterCoverageMappingBuilder Counter LabelCount = getRegionCounter(S); SourceLocation Start = getStart(S); completeTopLevelDeferredRegion(LabelCount, Start); + completeDeferred(LabelCount, Start); // We can't extendRegion here or we risk overlapping with our new region. handleFileExit(Start); pushRegion(LabelCount, Start); @@ -979,20 +963,28 @@ struct CounterCoverageMappingBuilder Counter ParentCount = getRegion().getCounter(); Counter BodyCount = getRegionCounter(S); + // The loop increment may contain a break or continue. + if (S->getInc()) + BreakContinueStack.emplace_back(); + // Handle the body first so that we can get the backedge count. - BreakContinueStack.push_back(BreakContinue()); + BreakContinueStack.emplace_back(); extendRegion(S->getBody()); Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); - BreakContinue BC = BreakContinueStack.pop_back_val(); + BreakContinue BodyBC = BreakContinueStack.pop_back_val(); // The increment is essentially part of the body but it needs to include // the count for all the continue statements. - if (const Stmt *Inc = S->getInc()) - propagateCounts(addCounters(BackedgeCount, BC.ContinueCount), Inc); + BreakContinue IncrementBC; + if (const Stmt *Inc = S->getInc()) { + propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc); + IncrementBC = BreakContinueStack.pop_back_val(); + } // Go back to handle the condition. - Counter CondCount = - addCounters(ParentCount, BackedgeCount, BC.ContinueCount); + Counter CondCount = addCounters( + addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount), + IncrementBC.ContinueCount); if (const Expr *Cond = S->getCond()) { propagateCounts(CondCount, Cond); adjustForOutOfOrderTraversal(getEnd(S)); @@ -1004,8 +996,8 @@ struct CounterCoverageMappingBuilder if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); - Counter OutCount = - addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount)); + Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, + subtractCounters(CondCount, BodyCount)); if (OutCount != ParentCount) pushRegion(OutCount); } @@ -1361,8 +1353,7 @@ void CoverageMappingModuleGen::emit() { // and coverage mappings is a multiple of 8. if (size_t Rem = OS.str().size() % 8) { CoverageMappingSize += 8 - Rem; - for (size_t I = 0, S = 8 - Rem; I < S; ++I) - OS << '\0'; + OS.write_zeros(8 - Rem); } auto *FilenamesAndMappingsVal = llvm::ConstantDataArray::getString(Ctx, OS.str(), false); |