1 //===- SourceCoverageDataManager.cpp - Manager for source file coverage
4 // The LLVM Compiler Infrastructure
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 // This class separates and merges mapping regions for a specific source file.
13 //===----------------------------------------------------------------------===//
15 #include "SourceCoverageDataManager.h"
18 using namespace coverage;
20 void SourceCoverageDataManager::insert(const CountedRegion &CR) {
21 Regions.push_back(CR);
26 class SegmentBuilder {
27 std::vector<CoverageSegment> Segments;
28 SmallVector<const CountedRegion *, 8> ActiveRegions;
30 /// Start a segment with no count specified.
31 void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry) {
32 Segments.emplace_back(Line, Col, IsRegionEntry);
35 /// Start a segment with the given Region's count.
36 void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
37 const CountedRegion &Region) {
39 Segments.emplace_back(Line, Col, IsRegionEntry);
40 CoverageSegment S = Segments.back();
41 // Avoid creating empty regions.
42 if (S.Line != Line || S.Col != Col) {
43 Segments.emplace_back(Line, Col, IsRegionEntry);
46 // Set this region's count.
47 if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion)
48 Segments.back().setCount(Region.ExecutionCount);
51 /// Start a segment for the given region.
52 void startSegment(const CountedRegion &Region) {
53 startSegment(Region.LineStart, Region.ColumnStart, true, Region);
56 /// Pop the top region off of the active stack, starting a new segment with
57 /// the containing Region's count.
59 const CountedRegion *Active = ActiveRegions.back();
60 unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
61 ActiveRegions.pop_back();
62 if (ActiveRegions.empty())
63 startSegment(Line, Col, /*IsRegionEntry=*/false);
65 startSegment(Line, Col, /*IsRegionEntry=*/false, *ActiveRegions.back());
69 /// Build a list of CoverageSegments from a sorted list of Regions.
70 std::vector<CoverageSegment>
71 buildSegments(ArrayRef<CountedRegion> Regions) {
72 for (const auto &Region : Regions) {
73 // Pop any regions that end before this one starts.
74 while (!ActiveRegions.empty() &&
75 ActiveRegions.back()->endLoc() <= Region.startLoc())
77 // Add this region to the stack.
78 ActiveRegions.push_back(&Region);
81 // Pop any regions that are left in the stack.
82 while (!ActiveRegions.empty())
89 ArrayRef<CoverageSegment> SourceCoverageDataManager::getCoverageSegments() {
90 if (Segments.empty()) {
91 // Sort the regions given that they're all in the same file at this point.
92 std::sort(Regions.begin(), Regions.end(),
93 [](const CountedRegion &LHS, const CountedRegion &RHS) {
94 if (LHS.startLoc() == RHS.startLoc())
95 // When LHS completely contains RHS, we sort LHS first.
96 return RHS.endLoc() < LHS.endLoc();
97 return LHS.startLoc() < RHS.startLoc();
100 Segments = SegmentBuilder().buildSegments(Regions);