1*0a6a1f1dSLionel Sambuc //===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc // The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // Instrumentation-based code coverage mapping generator
11*0a6a1f1dSLionel Sambuc //
12*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
13*0a6a1f1dSLionel Sambuc
14*0a6a1f1dSLionel Sambuc #include "CoverageMappingGen.h"
15*0a6a1f1dSLionel Sambuc #include "CodeGenFunction.h"
16*0a6a1f1dSLionel Sambuc #include "clang/AST/StmtVisitor.h"
17*0a6a1f1dSLionel Sambuc #include "clang/Lex/Lexer.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/ProfileData/CoverageMapping.h"
19*0a6a1f1dSLionel Sambuc #include "llvm/ProfileData/CoverageMappingReader.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/ProfileData/CoverageMappingWriter.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/ProfileData/InstrProfReader.h"
22*0a6a1f1dSLionel Sambuc #include "llvm/Support/FileSystem.h"
23*0a6a1f1dSLionel Sambuc
24*0a6a1f1dSLionel Sambuc using namespace clang;
25*0a6a1f1dSLionel Sambuc using namespace CodeGen;
26*0a6a1f1dSLionel Sambuc using namespace llvm::coverage;
27*0a6a1f1dSLionel Sambuc
SourceRangeSkipped(SourceRange Range)28*0a6a1f1dSLionel Sambuc void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range) {
29*0a6a1f1dSLionel Sambuc SkippedRanges.push_back(Range);
30*0a6a1f1dSLionel Sambuc }
31*0a6a1f1dSLionel Sambuc
32*0a6a1f1dSLionel Sambuc namespace {
33*0a6a1f1dSLionel Sambuc
34*0a6a1f1dSLionel Sambuc /// \brief A region of source code that can be mapped to a counter.
35*0a6a1f1dSLionel Sambuc class SourceMappingRegion {
36*0a6a1f1dSLionel Sambuc public:
37*0a6a1f1dSLionel Sambuc enum RegionFlags {
38*0a6a1f1dSLionel Sambuc /// \brief This region won't be emitted if it wasn't extended.
39*0a6a1f1dSLionel Sambuc /// This is useful so that we won't emit source ranges for single tokens
40*0a6a1f1dSLionel Sambuc /// that we don't really care that much about, like:
41*0a6a1f1dSLionel Sambuc /// the '(' token in #define MACRO (
42*0a6a1f1dSLionel Sambuc IgnoreIfNotExtended = 0x0001,
43*0a6a1f1dSLionel Sambuc };
44*0a6a1f1dSLionel Sambuc
45*0a6a1f1dSLionel Sambuc private:
46*0a6a1f1dSLionel Sambuc FileID File, MacroArgumentFile;
47*0a6a1f1dSLionel Sambuc
48*0a6a1f1dSLionel Sambuc Counter Count;
49*0a6a1f1dSLionel Sambuc
50*0a6a1f1dSLionel Sambuc /// \brief A statement that initiated the count of Zero.
51*0a6a1f1dSLionel Sambuc ///
52*0a6a1f1dSLionel Sambuc /// This initiator statement is useful to prevent merging of unreachable
53*0a6a1f1dSLionel Sambuc /// regions with different statements that caused the counter to become
54*0a6a1f1dSLionel Sambuc /// unreachable.
55*0a6a1f1dSLionel Sambuc const Stmt *UnreachableInitiator;
56*0a6a1f1dSLionel Sambuc
57*0a6a1f1dSLionel Sambuc /// \brief A statement that separates certain mapping regions into groups.
58*0a6a1f1dSLionel Sambuc ///
59*0a6a1f1dSLionel Sambuc /// The group statement is sometimes useful when we are emitting the source
60*0a6a1f1dSLionel Sambuc /// regions not in their correct lexical order, e.g. the regions for the
61*0a6a1f1dSLionel Sambuc /// incrementation expression in the 'for' construct. By marking the regions
62*0a6a1f1dSLionel Sambuc /// in the incrementation expression with the group statement, we avoid the
63*0a6a1f1dSLionel Sambuc /// merging of the regions from the incrementation expression and the loop's
64*0a6a1f1dSLionel Sambuc /// body.
65*0a6a1f1dSLionel Sambuc const Stmt *Group;
66*0a6a1f1dSLionel Sambuc
67*0a6a1f1dSLionel Sambuc /// \brief The region's starting location.
68*0a6a1f1dSLionel Sambuc SourceLocation LocStart;
69*0a6a1f1dSLionel Sambuc
70*0a6a1f1dSLionel Sambuc /// \brief The region's ending location.
71*0a6a1f1dSLionel Sambuc SourceLocation LocEnd, AlternativeLocEnd;
72*0a6a1f1dSLionel Sambuc unsigned Flags;
73*0a6a1f1dSLionel Sambuc
74*0a6a1f1dSLionel Sambuc public:
SourceMappingRegion(FileID File,FileID MacroArgumentFile,Counter Count,const Stmt * UnreachableInitiator,const Stmt * Group,SourceLocation LocStart,SourceLocation LocEnd,unsigned Flags=0)75*0a6a1f1dSLionel Sambuc SourceMappingRegion(FileID File, FileID MacroArgumentFile, Counter Count,
76*0a6a1f1dSLionel Sambuc const Stmt *UnreachableInitiator, const Stmt *Group,
77*0a6a1f1dSLionel Sambuc SourceLocation LocStart, SourceLocation LocEnd,
78*0a6a1f1dSLionel Sambuc unsigned Flags = 0)
79*0a6a1f1dSLionel Sambuc : File(File), MacroArgumentFile(MacroArgumentFile), Count(Count),
80*0a6a1f1dSLionel Sambuc UnreachableInitiator(UnreachableInitiator), Group(Group),
81*0a6a1f1dSLionel Sambuc LocStart(LocStart), LocEnd(LocEnd), AlternativeLocEnd(LocStart),
82*0a6a1f1dSLionel Sambuc Flags(Flags) {}
83*0a6a1f1dSLionel Sambuc
getFile() const84*0a6a1f1dSLionel Sambuc const FileID &getFile() const { return File; }
85*0a6a1f1dSLionel Sambuc
getCounter() const86*0a6a1f1dSLionel Sambuc const Counter &getCounter() const { return Count; }
87*0a6a1f1dSLionel Sambuc
getStartLoc() const88*0a6a1f1dSLionel Sambuc const SourceLocation &getStartLoc() const { return LocStart; }
89*0a6a1f1dSLionel Sambuc
getEndLoc(const SourceManager & SM) const90*0a6a1f1dSLionel Sambuc const SourceLocation &getEndLoc(const SourceManager &SM) const {
91*0a6a1f1dSLionel Sambuc if (SM.getFileID(LocEnd) != File)
92*0a6a1f1dSLionel Sambuc return AlternativeLocEnd;
93*0a6a1f1dSLionel Sambuc return LocEnd;
94*0a6a1f1dSLionel Sambuc }
95*0a6a1f1dSLionel Sambuc
hasFlag(RegionFlags Flag) const96*0a6a1f1dSLionel Sambuc bool hasFlag(RegionFlags Flag) const { return (Flags & Flag) != 0; }
97*0a6a1f1dSLionel Sambuc
setFlag(RegionFlags Flag)98*0a6a1f1dSLionel Sambuc void setFlag(RegionFlags Flag) { Flags |= Flag; }
99*0a6a1f1dSLionel Sambuc
clearFlag(RegionFlags Flag)100*0a6a1f1dSLionel Sambuc void clearFlag(RegionFlags Flag) { Flags &= ~Flag; }
101*0a6a1f1dSLionel Sambuc
102*0a6a1f1dSLionel Sambuc /// \brief Return true if two regions can be merged together.
isMergeable(SourceMappingRegion & R)103*0a6a1f1dSLionel Sambuc bool isMergeable(SourceMappingRegion &R) {
104*0a6a1f1dSLionel Sambuc // FIXME: We allow merging regions with a gap in between them. Should we?
105*0a6a1f1dSLionel Sambuc return File == R.File && MacroArgumentFile == R.MacroArgumentFile &&
106*0a6a1f1dSLionel Sambuc Count == R.Count && UnreachableInitiator == R.UnreachableInitiator &&
107*0a6a1f1dSLionel Sambuc Group == R.Group;
108*0a6a1f1dSLionel Sambuc }
109*0a6a1f1dSLionel Sambuc
110*0a6a1f1dSLionel Sambuc /// \brief A comparison that sorts such that mergeable regions are adjacent.
operator <(const SourceMappingRegion & LHS,const SourceMappingRegion & RHS)111*0a6a1f1dSLionel Sambuc friend bool operator<(const SourceMappingRegion &LHS,
112*0a6a1f1dSLionel Sambuc const SourceMappingRegion &RHS) {
113*0a6a1f1dSLionel Sambuc return std::tie(LHS.File, LHS.MacroArgumentFile, LHS.Count,
114*0a6a1f1dSLionel Sambuc LHS.UnreachableInitiator, LHS.Group) <
115*0a6a1f1dSLionel Sambuc std::tie(RHS.File, RHS.MacroArgumentFile, RHS.Count,
116*0a6a1f1dSLionel Sambuc RHS.UnreachableInitiator, RHS.Group);
117*0a6a1f1dSLionel Sambuc }
118*0a6a1f1dSLionel Sambuc };
119*0a6a1f1dSLionel Sambuc
120*0a6a1f1dSLionel Sambuc /// \brief Provides the common functionality for the different
121*0a6a1f1dSLionel Sambuc /// coverage mapping region builders.
122*0a6a1f1dSLionel Sambuc class CoverageMappingBuilder {
123*0a6a1f1dSLionel Sambuc public:
124*0a6a1f1dSLionel Sambuc CoverageMappingModuleGen &CVM;
125*0a6a1f1dSLionel Sambuc SourceManager &SM;
126*0a6a1f1dSLionel Sambuc const LangOptions &LangOpts;
127*0a6a1f1dSLionel Sambuc
128*0a6a1f1dSLionel Sambuc private:
129*0a6a1f1dSLionel Sambuc struct FileInfo {
130*0a6a1f1dSLionel Sambuc /// \brief The file id that will be used by the coverage mapping system.
131*0a6a1f1dSLionel Sambuc unsigned CovMappingFileID;
132*0a6a1f1dSLionel Sambuc const FileEntry *Entry;
133*0a6a1f1dSLionel Sambuc
FileInfo__anon3616bdc30111::CoverageMappingBuilder::FileInfo134*0a6a1f1dSLionel Sambuc FileInfo(unsigned CovMappingFileID, const FileEntry *Entry)
135*0a6a1f1dSLionel Sambuc : CovMappingFileID(CovMappingFileID), Entry(Entry) {}
136*0a6a1f1dSLionel Sambuc };
137*0a6a1f1dSLionel Sambuc
138*0a6a1f1dSLionel Sambuc /// \brief This mapping maps clang's FileIDs to file ids used
139*0a6a1f1dSLionel Sambuc /// by the coverage mapping system and clang's file entries.
140*0a6a1f1dSLionel Sambuc llvm::SmallDenseMap<FileID, FileInfo, 8> FileIDMapping;
141*0a6a1f1dSLionel Sambuc
142*0a6a1f1dSLionel Sambuc public:
143*0a6a1f1dSLionel Sambuc /// \brief The statement that corresponds to the current source group.
144*0a6a1f1dSLionel Sambuc const Stmt *CurrentSourceGroup;
145*0a6a1f1dSLionel Sambuc
146*0a6a1f1dSLionel Sambuc /// \brief The statement the initiated the current unreachable region.
147*0a6a1f1dSLionel Sambuc const Stmt *CurrentUnreachableRegionInitiator;
148*0a6a1f1dSLionel Sambuc
149*0a6a1f1dSLionel Sambuc /// \brief The coverage mapping regions for this function
150*0a6a1f1dSLionel Sambuc llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
151*0a6a1f1dSLionel Sambuc /// \brief The source mapping regions for this function.
152*0a6a1f1dSLionel Sambuc std::vector<SourceMappingRegion> SourceRegions;
153*0a6a1f1dSLionel Sambuc
CoverageMappingBuilder(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts)154*0a6a1f1dSLionel Sambuc CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
155*0a6a1f1dSLionel Sambuc const LangOptions &LangOpts)
156*0a6a1f1dSLionel Sambuc : CVM(CVM), SM(SM), LangOpts(LangOpts),
157*0a6a1f1dSLionel Sambuc CurrentSourceGroup(nullptr),
158*0a6a1f1dSLionel Sambuc CurrentUnreachableRegionInitiator(nullptr) {}
159*0a6a1f1dSLionel Sambuc
160*0a6a1f1dSLionel Sambuc /// \brief Return the precise end location for the given token.
getPreciseTokenLocEnd(SourceLocation Loc)161*0a6a1f1dSLionel Sambuc SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
162*0a6a1f1dSLionel Sambuc return Lexer::getLocForEndOfToken(SM.getSpellingLoc(Loc), 0, SM, LangOpts);
163*0a6a1f1dSLionel Sambuc }
164*0a6a1f1dSLionel Sambuc
165*0a6a1f1dSLionel Sambuc /// \brief Create the mapping that maps from the function's file ids to
166*0a6a1f1dSLionel Sambuc /// the indices for the translation unit's filenames.
createFileIDMapping(SmallVectorImpl<unsigned> & Mapping)167*0a6a1f1dSLionel Sambuc void createFileIDMapping(SmallVectorImpl<unsigned> &Mapping) {
168*0a6a1f1dSLionel Sambuc Mapping.resize(FileIDMapping.size(), 0);
169*0a6a1f1dSLionel Sambuc for (const auto &I : FileIDMapping)
170*0a6a1f1dSLionel Sambuc Mapping[I.second.CovMappingFileID] = CVM.getFileID(I.second.Entry);
171*0a6a1f1dSLionel Sambuc }
172*0a6a1f1dSLionel Sambuc
173*0a6a1f1dSLionel Sambuc /// \brief Get the coverage mapping file id that corresponds to the given
174*0a6a1f1dSLionel Sambuc /// clang file id. If such file id doesn't exist, it gets added to the
175*0a6a1f1dSLionel Sambuc /// mapping that maps from clang's file ids to coverage mapping file ids.
176*0a6a1f1dSLionel Sambuc /// Return true if there was an error getting the coverage mapping file id.
177*0a6a1f1dSLionel Sambuc /// An example of an when this function fails is when the region tries
178*0a6a1f1dSLionel Sambuc /// to get a coverage file id for a location in a built-in macro.
getCoverageFileID(SourceLocation LocStart,FileID File,FileID SpellingFile,unsigned & Result)179*0a6a1f1dSLionel Sambuc bool getCoverageFileID(SourceLocation LocStart, FileID File,
180*0a6a1f1dSLionel Sambuc FileID SpellingFile, unsigned &Result) {
181*0a6a1f1dSLionel Sambuc auto Mapping = FileIDMapping.find(File);
182*0a6a1f1dSLionel Sambuc if (Mapping != FileIDMapping.end()) {
183*0a6a1f1dSLionel Sambuc Result = Mapping->second.CovMappingFileID;
184*0a6a1f1dSLionel Sambuc return false;
185*0a6a1f1dSLionel Sambuc }
186*0a6a1f1dSLionel Sambuc
187*0a6a1f1dSLionel Sambuc auto Entry = SM.getFileEntryForID(SpellingFile);
188*0a6a1f1dSLionel Sambuc if (!Entry)
189*0a6a1f1dSLionel Sambuc return true;
190*0a6a1f1dSLionel Sambuc
191*0a6a1f1dSLionel Sambuc Result = FileIDMapping.size();
192*0a6a1f1dSLionel Sambuc FileIDMapping.insert(std::make_pair(File, FileInfo(Result, Entry)));
193*0a6a1f1dSLionel Sambuc createFileExpansionRegion(LocStart, File);
194*0a6a1f1dSLionel Sambuc return false;
195*0a6a1f1dSLionel Sambuc }
196*0a6a1f1dSLionel Sambuc
197*0a6a1f1dSLionel Sambuc /// \brief Get the coverage mapping file id that corresponds to the given
198*0a6a1f1dSLionel Sambuc /// clang file id.
199*0a6a1f1dSLionel Sambuc /// Return true if there was an error getting the coverage mapping file id.
getExistingCoverageFileID(FileID File,unsigned & Result)200*0a6a1f1dSLionel Sambuc bool getExistingCoverageFileID(FileID File, unsigned &Result) {
201*0a6a1f1dSLionel Sambuc // Make sure that the file is valid.
202*0a6a1f1dSLionel Sambuc if (File.isInvalid())
203*0a6a1f1dSLionel Sambuc return true;
204*0a6a1f1dSLionel Sambuc auto Mapping = FileIDMapping.find(File);
205*0a6a1f1dSLionel Sambuc if (Mapping != FileIDMapping.end()) {
206*0a6a1f1dSLionel Sambuc Result = Mapping->second.CovMappingFileID;
207*0a6a1f1dSLionel Sambuc return false;
208*0a6a1f1dSLionel Sambuc }
209*0a6a1f1dSLionel Sambuc return true;
210*0a6a1f1dSLionel Sambuc }
211*0a6a1f1dSLionel Sambuc
212*0a6a1f1dSLionel Sambuc /// \brief Return true if the given clang's file id has a corresponding
213*0a6a1f1dSLionel Sambuc /// coverage file id.
hasExistingCoverageFileID(FileID File) const214*0a6a1f1dSLionel Sambuc bool hasExistingCoverageFileID(FileID File) const {
215*0a6a1f1dSLionel Sambuc return FileIDMapping.count(File);
216*0a6a1f1dSLionel Sambuc }
217*0a6a1f1dSLionel Sambuc
218*0a6a1f1dSLionel Sambuc /// \brief Gather all the regions that were skipped by the preprocessor
219*0a6a1f1dSLionel Sambuc /// using the constructs like #if.
gatherSkippedRegions()220*0a6a1f1dSLionel Sambuc void gatherSkippedRegions() {
221*0a6a1f1dSLionel Sambuc /// An array of the minimum lineStarts and the maximum lineEnds
222*0a6a1f1dSLionel Sambuc /// for mapping regions from the appropriate source files.
223*0a6a1f1dSLionel Sambuc llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
224*0a6a1f1dSLionel Sambuc FileLineRanges.resize(
225*0a6a1f1dSLionel Sambuc FileIDMapping.size(),
226*0a6a1f1dSLionel Sambuc std::make_pair(std::numeric_limits<unsigned>::max(), 0));
227*0a6a1f1dSLionel Sambuc for (const auto &R : MappingRegions) {
228*0a6a1f1dSLionel Sambuc FileLineRanges[R.FileID].first =
229*0a6a1f1dSLionel Sambuc std::min(FileLineRanges[R.FileID].first, R.LineStart);
230*0a6a1f1dSLionel Sambuc FileLineRanges[R.FileID].second =
231*0a6a1f1dSLionel Sambuc std::max(FileLineRanges[R.FileID].second, R.LineEnd);
232*0a6a1f1dSLionel Sambuc }
233*0a6a1f1dSLionel Sambuc
234*0a6a1f1dSLionel Sambuc auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
235*0a6a1f1dSLionel Sambuc for (const auto &I : SkippedRanges) {
236*0a6a1f1dSLionel Sambuc auto LocStart = I.getBegin();
237*0a6a1f1dSLionel Sambuc auto LocEnd = I.getEnd();
238*0a6a1f1dSLionel Sambuc auto FileStart = SM.getFileID(LocStart);
239*0a6a1f1dSLionel Sambuc if (!hasExistingCoverageFileID(FileStart))
240*0a6a1f1dSLionel Sambuc continue;
241*0a6a1f1dSLionel Sambuc auto ActualFileStart = SM.getDecomposedSpellingLoc(LocStart).first;
242*0a6a1f1dSLionel Sambuc if (ActualFileStart != SM.getDecomposedSpellingLoc(LocEnd).first)
243*0a6a1f1dSLionel Sambuc // Ignore regions that span across multiple files.
244*0a6a1f1dSLionel Sambuc continue;
245*0a6a1f1dSLionel Sambuc
246*0a6a1f1dSLionel Sambuc unsigned CovFileID;
247*0a6a1f1dSLionel Sambuc if (getCoverageFileID(LocStart, FileStart, ActualFileStart, CovFileID))
248*0a6a1f1dSLionel Sambuc continue;
249*0a6a1f1dSLionel Sambuc unsigned LineStart = SM.getSpellingLineNumber(LocStart);
250*0a6a1f1dSLionel Sambuc unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
251*0a6a1f1dSLionel Sambuc unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
252*0a6a1f1dSLionel Sambuc unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
253*0a6a1f1dSLionel Sambuc CounterMappingRegion Region(Counter(), CovFileID, LineStart, ColumnStart,
254*0a6a1f1dSLionel Sambuc LineEnd, ColumnEnd, false,
255*0a6a1f1dSLionel Sambuc CounterMappingRegion::SkippedRegion);
256*0a6a1f1dSLionel Sambuc // Make sure that we only collect the regions that are inside
257*0a6a1f1dSLionel Sambuc // the souce code of this function.
258*0a6a1f1dSLionel Sambuc if (Region.LineStart >= FileLineRanges[CovFileID].first &&
259*0a6a1f1dSLionel Sambuc Region.LineEnd <= FileLineRanges[CovFileID].second)
260*0a6a1f1dSLionel Sambuc MappingRegions.push_back(Region);
261*0a6a1f1dSLionel Sambuc }
262*0a6a1f1dSLionel Sambuc }
263*0a6a1f1dSLionel Sambuc
264*0a6a1f1dSLionel Sambuc /// \brief Create a mapping region that correponds to an expansion of
265*0a6a1f1dSLionel Sambuc /// a macro or an embedded include.
createFileExpansionRegion(SourceLocation Loc,FileID ExpandedFile)266*0a6a1f1dSLionel Sambuc void createFileExpansionRegion(SourceLocation Loc, FileID ExpandedFile) {
267*0a6a1f1dSLionel Sambuc SourceLocation LocStart;
268*0a6a1f1dSLionel Sambuc if (Loc.isMacroID())
269*0a6a1f1dSLionel Sambuc LocStart = SM.getImmediateExpansionRange(Loc).first;
270*0a6a1f1dSLionel Sambuc else {
271*0a6a1f1dSLionel Sambuc LocStart = SM.getIncludeLoc(ExpandedFile);
272*0a6a1f1dSLionel Sambuc if (LocStart.isInvalid())
273*0a6a1f1dSLionel Sambuc return; // This file has no expansion region.
274*0a6a1f1dSLionel Sambuc }
275*0a6a1f1dSLionel Sambuc
276*0a6a1f1dSLionel Sambuc auto File = SM.getFileID(LocStart);
277*0a6a1f1dSLionel Sambuc auto SpellingFile = SM.getDecomposedSpellingLoc(LocStart).first;
278*0a6a1f1dSLionel Sambuc unsigned CovFileID, ExpandedFileID;
279*0a6a1f1dSLionel Sambuc if (getExistingCoverageFileID(ExpandedFile, ExpandedFileID))
280*0a6a1f1dSLionel Sambuc return;
281*0a6a1f1dSLionel Sambuc if (getCoverageFileID(LocStart, File, SpellingFile, CovFileID))
282*0a6a1f1dSLionel Sambuc return;
283*0a6a1f1dSLionel Sambuc unsigned LineStart = SM.getSpellingLineNumber(LocStart);
284*0a6a1f1dSLionel Sambuc unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
285*0a6a1f1dSLionel Sambuc unsigned LineEnd = LineStart;
286*0a6a1f1dSLionel Sambuc // Compute the end column manually as Lexer::getLocForEndOfToken doesn't
287*0a6a1f1dSLionel Sambuc // give the correct result in all cases.
288*0a6a1f1dSLionel Sambuc unsigned ColumnEnd =
289*0a6a1f1dSLionel Sambuc ColumnStart +
290*0a6a1f1dSLionel Sambuc Lexer::MeasureTokenLength(SM.getSpellingLoc(LocStart), SM, LangOpts);
291*0a6a1f1dSLionel Sambuc
292*0a6a1f1dSLionel Sambuc MappingRegions.push_back(CounterMappingRegion(
293*0a6a1f1dSLionel Sambuc Counter(), CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd,
294*0a6a1f1dSLionel Sambuc false, CounterMappingRegion::ExpansionRegion));
295*0a6a1f1dSLionel Sambuc MappingRegions.back().ExpandedFileID = ExpandedFileID;
296*0a6a1f1dSLionel Sambuc }
297*0a6a1f1dSLionel Sambuc
298*0a6a1f1dSLionel Sambuc /// \brief Enter a source region group that is identified by the given
299*0a6a1f1dSLionel Sambuc /// statement.
300*0a6a1f1dSLionel Sambuc /// It's not possible to enter a group when there is already
301*0a6a1f1dSLionel Sambuc /// another group present.
beginSourceRegionGroup(const Stmt * Group)302*0a6a1f1dSLionel Sambuc void beginSourceRegionGroup(const Stmt *Group) {
303*0a6a1f1dSLionel Sambuc assert(!CurrentSourceGroup);
304*0a6a1f1dSLionel Sambuc CurrentSourceGroup = Group;
305*0a6a1f1dSLionel Sambuc }
306*0a6a1f1dSLionel Sambuc
307*0a6a1f1dSLionel Sambuc /// \brief Exit the current source region group.
endSourceRegionGroup()308*0a6a1f1dSLionel Sambuc void endSourceRegionGroup() { CurrentSourceGroup = nullptr; }
309*0a6a1f1dSLionel Sambuc
310*0a6a1f1dSLionel Sambuc /// \brief Associate a counter with a given source code range.
mapSourceCodeRange(SourceLocation LocStart,SourceLocation LocEnd,Counter Count,const Stmt * UnreachableInitiator,const Stmt * SourceGroup,unsigned Flags=0,FileID MacroArgumentFile=FileID ())311*0a6a1f1dSLionel Sambuc void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
312*0a6a1f1dSLionel Sambuc Counter Count, const Stmt *UnreachableInitiator,
313*0a6a1f1dSLionel Sambuc const Stmt *SourceGroup, unsigned Flags = 0,
314*0a6a1f1dSLionel Sambuc FileID MacroArgumentFile = FileID()) {
315*0a6a1f1dSLionel Sambuc if (SM.isMacroArgExpansion(LocStart)) {
316*0a6a1f1dSLionel Sambuc // Map the code range with the macro argument's value.
317*0a6a1f1dSLionel Sambuc mapSourceCodeRange(SM.getImmediateSpellingLoc(LocStart),
318*0a6a1f1dSLionel Sambuc SM.getImmediateSpellingLoc(LocEnd), Count,
319*0a6a1f1dSLionel Sambuc UnreachableInitiator, SourceGroup, Flags,
320*0a6a1f1dSLionel Sambuc SM.getFileID(LocStart));
321*0a6a1f1dSLionel Sambuc // Map the code range where the macro argument is referenced.
322*0a6a1f1dSLionel Sambuc SourceLocation RefLocStart(SM.getImmediateExpansionRange(LocStart).first);
323*0a6a1f1dSLionel Sambuc SourceLocation RefLocEnd(RefLocStart);
324*0a6a1f1dSLionel Sambuc if (SM.isMacroArgExpansion(RefLocStart))
325*0a6a1f1dSLionel Sambuc mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
326*0a6a1f1dSLionel Sambuc SourceGroup, 0, SM.getFileID(RefLocStart));
327*0a6a1f1dSLionel Sambuc else
328*0a6a1f1dSLionel Sambuc mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
329*0a6a1f1dSLionel Sambuc SourceGroup);
330*0a6a1f1dSLionel Sambuc return;
331*0a6a1f1dSLionel Sambuc }
332*0a6a1f1dSLionel Sambuc auto File = SM.getFileID(LocStart);
333*0a6a1f1dSLionel Sambuc // Make sure that the file id is valid.
334*0a6a1f1dSLionel Sambuc if (File.isInvalid())
335*0a6a1f1dSLionel Sambuc return;
336*0a6a1f1dSLionel Sambuc SourceRegions.emplace_back(File, MacroArgumentFile, Count,
337*0a6a1f1dSLionel Sambuc UnreachableInitiator, SourceGroup, LocStart,
338*0a6a1f1dSLionel Sambuc LocEnd, Flags);
339*0a6a1f1dSLionel Sambuc }
340*0a6a1f1dSLionel Sambuc
mapSourceCodeRange(SourceLocation LocStart,SourceLocation LocEnd,Counter Count,unsigned Flags=0)341*0a6a1f1dSLionel Sambuc void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
342*0a6a1f1dSLionel Sambuc Counter Count, unsigned Flags = 0) {
343*0a6a1f1dSLionel Sambuc mapSourceCodeRange(LocStart, LocEnd, Count,
344*0a6a1f1dSLionel Sambuc CurrentUnreachableRegionInitiator, CurrentSourceGroup,
345*0a6a1f1dSLionel Sambuc Flags);
346*0a6a1f1dSLionel Sambuc }
347*0a6a1f1dSLionel Sambuc
348*0a6a1f1dSLionel Sambuc /// \brief Generate the coverage counter mapping regions from collected
349*0a6a1f1dSLionel Sambuc /// source regions.
emitSourceRegions()350*0a6a1f1dSLionel Sambuc void emitSourceRegions() {
351*0a6a1f1dSLionel Sambuc std::sort(SourceRegions.begin(), SourceRegions.end());
352*0a6a1f1dSLionel Sambuc
353*0a6a1f1dSLionel Sambuc for (auto I = SourceRegions.begin(), E = SourceRegions.end(); I != E; ++I) {
354*0a6a1f1dSLionel Sambuc // Keep the original start location of this region.
355*0a6a1f1dSLionel Sambuc SourceLocation LocStart = I->getStartLoc();
356*0a6a1f1dSLionel Sambuc SourceLocation LocEnd = I->getEndLoc(SM);
357*0a6a1f1dSLionel Sambuc
358*0a6a1f1dSLionel Sambuc bool Ignore = I->hasFlag(SourceMappingRegion::IgnoreIfNotExtended);
359*0a6a1f1dSLionel Sambuc // We need to handle mergeable regions together.
360*0a6a1f1dSLionel Sambuc for (auto Next = I + 1; Next != E && Next->isMergeable(*I); ++Next) {
361*0a6a1f1dSLionel Sambuc ++I;
362*0a6a1f1dSLionel Sambuc LocStart = std::min(LocStart, I->getStartLoc());
363*0a6a1f1dSLionel Sambuc LocEnd = std::max(LocEnd, I->getEndLoc(SM));
364*0a6a1f1dSLionel Sambuc // FIXME: Should we && together the Ignore flag of multiple regions?
365*0a6a1f1dSLionel Sambuc Ignore = false;
366*0a6a1f1dSLionel Sambuc }
367*0a6a1f1dSLionel Sambuc if (Ignore)
368*0a6a1f1dSLionel Sambuc continue;
369*0a6a1f1dSLionel Sambuc
370*0a6a1f1dSLionel Sambuc // Find the spilling locations for the mapping region.
371*0a6a1f1dSLionel Sambuc LocEnd = getPreciseTokenLocEnd(LocEnd);
372*0a6a1f1dSLionel Sambuc unsigned LineStart = SM.getSpellingLineNumber(LocStart);
373*0a6a1f1dSLionel Sambuc unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
374*0a6a1f1dSLionel Sambuc unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
375*0a6a1f1dSLionel Sambuc unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
376*0a6a1f1dSLionel Sambuc
377*0a6a1f1dSLionel Sambuc auto SpellingFile = SM.getDecomposedSpellingLoc(LocStart).first;
378*0a6a1f1dSLionel Sambuc unsigned CovFileID;
379*0a6a1f1dSLionel Sambuc if (getCoverageFileID(LocStart, I->getFile(), SpellingFile, CovFileID))
380*0a6a1f1dSLionel Sambuc continue;
381*0a6a1f1dSLionel Sambuc
382*0a6a1f1dSLionel Sambuc assert(LineStart <= LineEnd);
383*0a6a1f1dSLionel Sambuc MappingRegions.push_back(CounterMappingRegion(
384*0a6a1f1dSLionel Sambuc I->getCounter(), CovFileID, LineStart, ColumnStart, LineEnd,
385*0a6a1f1dSLionel Sambuc ColumnEnd, false, CounterMappingRegion::CodeRegion));
386*0a6a1f1dSLionel Sambuc }
387*0a6a1f1dSLionel Sambuc }
388*0a6a1f1dSLionel Sambuc };
389*0a6a1f1dSLionel Sambuc
390*0a6a1f1dSLionel Sambuc /// \brief Creates unreachable coverage regions for the functions that
391*0a6a1f1dSLionel Sambuc /// are not emitted.
392*0a6a1f1dSLionel Sambuc struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
EmptyCoverageMappingBuilder__anon3616bdc30111::EmptyCoverageMappingBuilder393*0a6a1f1dSLionel Sambuc EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
394*0a6a1f1dSLionel Sambuc const LangOptions &LangOpts)
395*0a6a1f1dSLionel Sambuc : CoverageMappingBuilder(CVM, SM, LangOpts) {}
396*0a6a1f1dSLionel Sambuc
VisitDecl__anon3616bdc30111::EmptyCoverageMappingBuilder397*0a6a1f1dSLionel Sambuc void VisitDecl(const Decl *D) {
398*0a6a1f1dSLionel Sambuc if (!D->hasBody())
399*0a6a1f1dSLionel Sambuc return;
400*0a6a1f1dSLionel Sambuc auto Body = D->getBody();
401*0a6a1f1dSLionel Sambuc mapSourceCodeRange(Body->getLocStart(), Body->getLocEnd(), Counter());
402*0a6a1f1dSLionel Sambuc }
403*0a6a1f1dSLionel Sambuc
404*0a6a1f1dSLionel Sambuc /// \brief Write the mapping data to the output stream
write__anon3616bdc30111::EmptyCoverageMappingBuilder405*0a6a1f1dSLionel Sambuc void write(llvm::raw_ostream &OS) {
406*0a6a1f1dSLionel Sambuc emitSourceRegions();
407*0a6a1f1dSLionel Sambuc SmallVector<unsigned, 16> FileIDMapping;
408*0a6a1f1dSLionel Sambuc createFileIDMapping(FileIDMapping);
409*0a6a1f1dSLionel Sambuc
410*0a6a1f1dSLionel Sambuc CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
411*0a6a1f1dSLionel Sambuc Writer.write(OS);
412*0a6a1f1dSLionel Sambuc }
413*0a6a1f1dSLionel Sambuc };
414*0a6a1f1dSLionel Sambuc
415*0a6a1f1dSLionel Sambuc /// \brief A StmtVisitor that creates coverage mapping regions which map
416*0a6a1f1dSLionel Sambuc /// from the source code locations to the PGO counters.
417*0a6a1f1dSLionel Sambuc struct CounterCoverageMappingBuilder
418*0a6a1f1dSLionel Sambuc : public CoverageMappingBuilder,
419*0a6a1f1dSLionel Sambuc public ConstStmtVisitor<CounterCoverageMappingBuilder> {
420*0a6a1f1dSLionel Sambuc /// \brief The map of statements to count values.
421*0a6a1f1dSLionel Sambuc llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
422*0a6a1f1dSLionel Sambuc
423*0a6a1f1dSLionel Sambuc Counter CurrentRegionCount;
424*0a6a1f1dSLionel Sambuc
425*0a6a1f1dSLionel Sambuc CounterExpressionBuilder Builder;
426*0a6a1f1dSLionel Sambuc
427*0a6a1f1dSLionel Sambuc /// \brief Return a counter that represents the
428*0a6a1f1dSLionel Sambuc /// expression that subracts rhs from lhs.
subtractCounters__anon3616bdc30111::CounterCoverageMappingBuilder429*0a6a1f1dSLionel Sambuc Counter subtractCounters(Counter LHS, Counter RHS) {
430*0a6a1f1dSLionel Sambuc return Builder.subtract(LHS, RHS);
431*0a6a1f1dSLionel Sambuc }
432*0a6a1f1dSLionel Sambuc
433*0a6a1f1dSLionel Sambuc /// \brief Return a counter that represents the
434*0a6a1f1dSLionel Sambuc /// the exression that adds lhs and rhs.
addCounters__anon3616bdc30111::CounterCoverageMappingBuilder435*0a6a1f1dSLionel Sambuc Counter addCounters(Counter LHS, Counter RHS) {
436*0a6a1f1dSLionel Sambuc return Builder.add(LHS, RHS);
437*0a6a1f1dSLionel Sambuc }
438*0a6a1f1dSLionel Sambuc
439*0a6a1f1dSLionel Sambuc /// \brief Return the region counter for the given statement.
440*0a6a1f1dSLionel Sambuc /// This should only be called on statements that have a dedicated counter.
getRegionCounter__anon3616bdc30111::CounterCoverageMappingBuilder441*0a6a1f1dSLionel Sambuc unsigned getRegionCounter(const Stmt *S) { return CounterMap[S]; }
442*0a6a1f1dSLionel Sambuc
443*0a6a1f1dSLionel Sambuc /// \brief Return the region count for the counter at the given index.
getRegionCount__anon3616bdc30111::CounterCoverageMappingBuilder444*0a6a1f1dSLionel Sambuc Counter getRegionCount(unsigned CounterId) {
445*0a6a1f1dSLionel Sambuc return Counter::getCounter(CounterId);
446*0a6a1f1dSLionel Sambuc }
447*0a6a1f1dSLionel Sambuc
448*0a6a1f1dSLionel Sambuc /// \brief Return the counter value of the current region.
getCurrentRegionCount__anon3616bdc30111::CounterCoverageMappingBuilder449*0a6a1f1dSLionel Sambuc Counter getCurrentRegionCount() { return CurrentRegionCount; }
450*0a6a1f1dSLionel Sambuc
451*0a6a1f1dSLionel Sambuc /// \brief Set the counter value for the current region.
452*0a6a1f1dSLionel Sambuc /// This is used to keep track of changes to the most recent counter
453*0a6a1f1dSLionel Sambuc /// from control flow and non-local exits.
setCurrentRegionCount__anon3616bdc30111::CounterCoverageMappingBuilder454*0a6a1f1dSLionel Sambuc void setCurrentRegionCount(Counter Count) {
455*0a6a1f1dSLionel Sambuc CurrentRegionCount = Count;
456*0a6a1f1dSLionel Sambuc CurrentUnreachableRegionInitiator = nullptr;
457*0a6a1f1dSLionel Sambuc }
458*0a6a1f1dSLionel Sambuc
459*0a6a1f1dSLionel Sambuc /// \brief Indicate that the current region is never reached,
460*0a6a1f1dSLionel Sambuc /// and thus should have a counter value of zero.
461*0a6a1f1dSLionel Sambuc /// This is important so that subsequent regions can correctly track
462*0a6a1f1dSLionel Sambuc /// their parent counts.
setCurrentRegionUnreachable__anon3616bdc30111::CounterCoverageMappingBuilder463*0a6a1f1dSLionel Sambuc void setCurrentRegionUnreachable(const Stmt *Initiator) {
464*0a6a1f1dSLionel Sambuc CurrentRegionCount = Counter::getZero();
465*0a6a1f1dSLionel Sambuc CurrentUnreachableRegionInitiator = Initiator;
466*0a6a1f1dSLionel Sambuc }
467*0a6a1f1dSLionel Sambuc
468*0a6a1f1dSLionel Sambuc /// \brief A counter for a particular region.
469*0a6a1f1dSLionel Sambuc /// This is the primary interface through
470*0a6a1f1dSLionel Sambuc /// which the coverage mapping builder manages counters and their values.
471*0a6a1f1dSLionel Sambuc class RegionMapper {
472*0a6a1f1dSLionel Sambuc CounterCoverageMappingBuilder &Mapping;
473*0a6a1f1dSLionel Sambuc Counter Count;
474*0a6a1f1dSLionel Sambuc Counter ParentCount;
475*0a6a1f1dSLionel Sambuc Counter RegionCount;
476*0a6a1f1dSLionel Sambuc Counter Adjust;
477*0a6a1f1dSLionel Sambuc
478*0a6a1f1dSLionel Sambuc public:
RegionMapper(CounterCoverageMappingBuilder * Mapper,const Stmt * S)479*0a6a1f1dSLionel Sambuc RegionMapper(CounterCoverageMappingBuilder *Mapper, const Stmt *S)
480*0a6a1f1dSLionel Sambuc : Mapping(*Mapper),
481*0a6a1f1dSLionel Sambuc Count(Mapper->getRegionCount(Mapper->getRegionCounter(S))),
482*0a6a1f1dSLionel Sambuc ParentCount(Mapper->getCurrentRegionCount()) {}
483*0a6a1f1dSLionel Sambuc
484*0a6a1f1dSLionel Sambuc /// Get the value of the counter. In most cases this is the number of times
485*0a6a1f1dSLionel Sambuc /// the region of the counter was entered, but for switch labels it's the
486*0a6a1f1dSLionel Sambuc /// number of direct jumps to that label.
getCount() const487*0a6a1f1dSLionel Sambuc Counter getCount() const { return Count; }
488*0a6a1f1dSLionel Sambuc
489*0a6a1f1dSLionel Sambuc /// Get the value of the counter with adjustments applied. Adjustments occur
490*0a6a1f1dSLionel Sambuc /// when control enters or leaves the region abnormally; i.e., if there is a
491*0a6a1f1dSLionel Sambuc /// jump to a label within the region, or if the function can return from
492*0a6a1f1dSLionel Sambuc /// within the region. The adjusted count, then, is the value of the counter
493*0a6a1f1dSLionel Sambuc /// at the end of the region.
getAdjustedCount() const494*0a6a1f1dSLionel Sambuc Counter getAdjustedCount() const {
495*0a6a1f1dSLionel Sambuc return Mapping.addCounters(Count, Adjust);
496*0a6a1f1dSLionel Sambuc }
497*0a6a1f1dSLionel Sambuc
498*0a6a1f1dSLionel Sambuc /// Get the value of the counter in this region's parent, i.e., the region
499*0a6a1f1dSLionel Sambuc /// that was active when this region began. This is useful for deriving
500*0a6a1f1dSLionel Sambuc /// counts in implicitly counted regions, like the false case of a condition
501*0a6a1f1dSLionel Sambuc /// or the normal exits of a loop.
getParentCount() const502*0a6a1f1dSLionel Sambuc Counter getParentCount() const { return ParentCount; }
503*0a6a1f1dSLionel Sambuc
504*0a6a1f1dSLionel Sambuc /// Activate the counter by emitting an increment and starting to track
505*0a6a1f1dSLionel Sambuc /// adjustments. If AddIncomingFallThrough is true, the current region count
506*0a6a1f1dSLionel Sambuc /// will be added to the counter for the purposes of tracking the region.
beginRegion(bool AddIncomingFallThrough=false)507*0a6a1f1dSLionel Sambuc void beginRegion(bool AddIncomingFallThrough = false) {
508*0a6a1f1dSLionel Sambuc RegionCount = Count;
509*0a6a1f1dSLionel Sambuc if (AddIncomingFallThrough)
510*0a6a1f1dSLionel Sambuc RegionCount =
511*0a6a1f1dSLionel Sambuc Mapping.addCounters(RegionCount, Mapping.getCurrentRegionCount());
512*0a6a1f1dSLionel Sambuc Mapping.setCurrentRegionCount(RegionCount);
513*0a6a1f1dSLionel Sambuc }
514*0a6a1f1dSLionel Sambuc
515*0a6a1f1dSLionel Sambuc /// For counters on boolean branches, begins tracking adjustments for the
516*0a6a1f1dSLionel Sambuc /// uncounted path.
beginElseRegion()517*0a6a1f1dSLionel Sambuc void beginElseRegion() {
518*0a6a1f1dSLionel Sambuc RegionCount = Mapping.subtractCounters(ParentCount, Count);
519*0a6a1f1dSLionel Sambuc Mapping.setCurrentRegionCount(RegionCount);
520*0a6a1f1dSLionel Sambuc }
521*0a6a1f1dSLionel Sambuc
522*0a6a1f1dSLionel Sambuc /// Reset the current region count.
setCurrentRegionCount(Counter CurrentCount)523*0a6a1f1dSLionel Sambuc void setCurrentRegionCount(Counter CurrentCount) {
524*0a6a1f1dSLionel Sambuc RegionCount = CurrentCount;
525*0a6a1f1dSLionel Sambuc Mapping.setCurrentRegionCount(RegionCount);
526*0a6a1f1dSLionel Sambuc }
527*0a6a1f1dSLionel Sambuc
528*0a6a1f1dSLionel Sambuc /// Adjust for non-local control flow after emitting a subexpression or
529*0a6a1f1dSLionel Sambuc /// substatement. This must be called to account for constructs such as
530*0a6a1f1dSLionel Sambuc /// gotos,
531*0a6a1f1dSLionel Sambuc /// labels, and returns, so that we can ensure that our region's count is
532*0a6a1f1dSLionel Sambuc /// correct in the code that follows.
adjustForControlFlow()533*0a6a1f1dSLionel Sambuc void adjustForControlFlow() {
534*0a6a1f1dSLionel Sambuc Adjust = Mapping.addCounters(
535*0a6a1f1dSLionel Sambuc Adjust, Mapping.subtractCounters(Mapping.getCurrentRegionCount(),
536*0a6a1f1dSLionel Sambuc RegionCount));
537*0a6a1f1dSLionel Sambuc // Reset the region count in case this is called again later.
538*0a6a1f1dSLionel Sambuc RegionCount = Mapping.getCurrentRegionCount();
539*0a6a1f1dSLionel Sambuc }
540*0a6a1f1dSLionel Sambuc
541*0a6a1f1dSLionel Sambuc /// Commit all adjustments to the current region. If the region is a loop,
542*0a6a1f1dSLionel Sambuc /// the LoopAdjust value should be the count of all the breaks and continues
543*0a6a1f1dSLionel Sambuc /// from the loop, to compensate for those counts being deducted from the
544*0a6a1f1dSLionel Sambuc /// adjustments for the body of the loop.
applyAdjustmentsToRegion()545*0a6a1f1dSLionel Sambuc void applyAdjustmentsToRegion() {
546*0a6a1f1dSLionel Sambuc Mapping.setCurrentRegionCount(Mapping.addCounters(ParentCount, Adjust));
547*0a6a1f1dSLionel Sambuc }
applyAdjustmentsToRegion(Counter LoopAdjust)548*0a6a1f1dSLionel Sambuc void applyAdjustmentsToRegion(Counter LoopAdjust) {
549*0a6a1f1dSLionel Sambuc Mapping.setCurrentRegionCount(Mapping.addCounters(
550*0a6a1f1dSLionel Sambuc Mapping.addCounters(ParentCount, Adjust), LoopAdjust));
551*0a6a1f1dSLionel Sambuc }
552*0a6a1f1dSLionel Sambuc };
553*0a6a1f1dSLionel Sambuc
554*0a6a1f1dSLionel Sambuc /// \brief Keep counts of breaks and continues inside loops.
555*0a6a1f1dSLionel Sambuc struct BreakContinue {
556*0a6a1f1dSLionel Sambuc Counter BreakCount;
557*0a6a1f1dSLionel Sambuc Counter ContinueCount;
558*0a6a1f1dSLionel Sambuc };
559*0a6a1f1dSLionel Sambuc SmallVector<BreakContinue, 8> BreakContinueStack;
560*0a6a1f1dSLionel Sambuc
CounterCoverageMappingBuilder__anon3616bdc30111::CounterCoverageMappingBuilder561*0a6a1f1dSLionel Sambuc CounterCoverageMappingBuilder(
562*0a6a1f1dSLionel Sambuc CoverageMappingModuleGen &CVM,
563*0a6a1f1dSLionel Sambuc llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
564*0a6a1f1dSLionel Sambuc const LangOptions &LangOpts)
565*0a6a1f1dSLionel Sambuc : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap) {}
566*0a6a1f1dSLionel Sambuc
567*0a6a1f1dSLionel Sambuc /// \brief Write the mapping data to the output stream
write__anon3616bdc30111::CounterCoverageMappingBuilder568*0a6a1f1dSLionel Sambuc void write(llvm::raw_ostream &OS) {
569*0a6a1f1dSLionel Sambuc emitSourceRegions();
570*0a6a1f1dSLionel Sambuc llvm::SmallVector<unsigned, 8> VirtualFileMapping;
571*0a6a1f1dSLionel Sambuc createFileIDMapping(VirtualFileMapping);
572*0a6a1f1dSLionel Sambuc gatherSkippedRegions();
573*0a6a1f1dSLionel Sambuc
574*0a6a1f1dSLionel Sambuc CoverageMappingWriter Writer(
575*0a6a1f1dSLionel Sambuc VirtualFileMapping, Builder.getExpressions(), MappingRegions);
576*0a6a1f1dSLionel Sambuc Writer.write(OS);
577*0a6a1f1dSLionel Sambuc }
578*0a6a1f1dSLionel Sambuc
579*0a6a1f1dSLionel Sambuc /// \brief Associate the source code range with the current region count.
mapSourceCodeRange__anon3616bdc30111::CounterCoverageMappingBuilder580*0a6a1f1dSLionel Sambuc void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
581*0a6a1f1dSLionel Sambuc unsigned Flags = 0) {
582*0a6a1f1dSLionel Sambuc CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocEnd,
583*0a6a1f1dSLionel Sambuc CurrentRegionCount, Flags);
584*0a6a1f1dSLionel Sambuc }
585*0a6a1f1dSLionel Sambuc
mapSourceCodeRange__anon3616bdc30111::CounterCoverageMappingBuilder586*0a6a1f1dSLionel Sambuc void mapSourceCodeRange(SourceLocation LocStart) {
587*0a6a1f1dSLionel Sambuc CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocStart,
588*0a6a1f1dSLionel Sambuc CurrentRegionCount);
589*0a6a1f1dSLionel Sambuc }
590*0a6a1f1dSLionel Sambuc
591*0a6a1f1dSLionel Sambuc /// \brief Associate the source range of a token with the current region
592*0a6a1f1dSLionel Sambuc /// count.
593*0a6a1f1dSLionel Sambuc /// Ignore the source range for this token if it produces a distinct
594*0a6a1f1dSLionel Sambuc /// mapping region with no other source ranges.
mapToken__anon3616bdc30111::CounterCoverageMappingBuilder595*0a6a1f1dSLionel Sambuc void mapToken(SourceLocation LocStart) {
596*0a6a1f1dSLionel Sambuc CoverageMappingBuilder::mapSourceCodeRange(
597*0a6a1f1dSLionel Sambuc LocStart, LocStart, CurrentRegionCount,
598*0a6a1f1dSLionel Sambuc SourceMappingRegion::IgnoreIfNotExtended);
599*0a6a1f1dSLionel Sambuc }
600*0a6a1f1dSLionel Sambuc
VisitStmt__anon3616bdc30111::CounterCoverageMappingBuilder601*0a6a1f1dSLionel Sambuc void VisitStmt(const Stmt *S) {
602*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
603*0a6a1f1dSLionel Sambuc for (Stmt::const_child_range I = S->children(); I; ++I) {
604*0a6a1f1dSLionel Sambuc if (*I)
605*0a6a1f1dSLionel Sambuc this->Visit(*I);
606*0a6a1f1dSLionel Sambuc }
607*0a6a1f1dSLionel Sambuc }
608*0a6a1f1dSLionel Sambuc
VisitDecl__anon3616bdc30111::CounterCoverageMappingBuilder609*0a6a1f1dSLionel Sambuc void VisitDecl(const Decl *D) {
610*0a6a1f1dSLionel Sambuc if (!D->hasBody())
611*0a6a1f1dSLionel Sambuc return;
612*0a6a1f1dSLionel Sambuc // Counter tracks entry to the function body.
613*0a6a1f1dSLionel Sambuc auto Body = D->getBody();
614*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, Body);
615*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
616*0a6a1f1dSLionel Sambuc Visit(Body);
617*0a6a1f1dSLionel Sambuc }
618*0a6a1f1dSLionel Sambuc
VisitDeclStmt__anon3616bdc30111::CounterCoverageMappingBuilder619*0a6a1f1dSLionel Sambuc void VisitDeclStmt(const DeclStmt *S) {
620*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
621*0a6a1f1dSLionel Sambuc for (Stmt::const_child_range I = static_cast<const Stmt *>(S)->children();
622*0a6a1f1dSLionel Sambuc I; ++I) {
623*0a6a1f1dSLionel Sambuc if (*I)
624*0a6a1f1dSLionel Sambuc this->Visit(*I);
625*0a6a1f1dSLionel Sambuc }
626*0a6a1f1dSLionel Sambuc }
627*0a6a1f1dSLionel Sambuc
VisitCompoundStmt__anon3616bdc30111::CounterCoverageMappingBuilder628*0a6a1f1dSLionel Sambuc void VisitCompoundStmt(const CompoundStmt *S) {
629*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLBracLoc());
630*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getRBracLoc());
631*0a6a1f1dSLionel Sambuc for (Stmt::const_child_range I = S->children(); I; ++I) {
632*0a6a1f1dSLionel Sambuc if (*I)
633*0a6a1f1dSLionel Sambuc this->Visit(*I);
634*0a6a1f1dSLionel Sambuc }
635*0a6a1f1dSLionel Sambuc }
636*0a6a1f1dSLionel Sambuc
VisitReturnStmt__anon3616bdc30111::CounterCoverageMappingBuilder637*0a6a1f1dSLionel Sambuc void VisitReturnStmt(const ReturnStmt *S) {
638*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
639*0a6a1f1dSLionel Sambuc if (S->getRetValue())
640*0a6a1f1dSLionel Sambuc Visit(S->getRetValue());
641*0a6a1f1dSLionel Sambuc setCurrentRegionUnreachable(S);
642*0a6a1f1dSLionel Sambuc }
643*0a6a1f1dSLionel Sambuc
VisitGotoStmt__anon3616bdc30111::CounterCoverageMappingBuilder644*0a6a1f1dSLionel Sambuc void VisitGotoStmt(const GotoStmt *S) {
645*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
646*0a6a1f1dSLionel Sambuc mapToken(S->getLabelLoc());
647*0a6a1f1dSLionel Sambuc setCurrentRegionUnreachable(S);
648*0a6a1f1dSLionel Sambuc }
649*0a6a1f1dSLionel Sambuc
VisitLabelStmt__anon3616bdc30111::CounterCoverageMappingBuilder650*0a6a1f1dSLionel Sambuc void VisitLabelStmt(const LabelStmt *S) {
651*0a6a1f1dSLionel Sambuc // Counter tracks the block following the label.
652*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
653*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
654*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
655*0a6a1f1dSLionel Sambuc // Can't map the ':' token as its location isn't known.
656*0a6a1f1dSLionel Sambuc Visit(S->getSubStmt());
657*0a6a1f1dSLionel Sambuc }
658*0a6a1f1dSLionel Sambuc
VisitBreakStmt__anon3616bdc30111::CounterCoverageMappingBuilder659*0a6a1f1dSLionel Sambuc void VisitBreakStmt(const BreakStmt *S) {
660*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
661*0a6a1f1dSLionel Sambuc assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
662*0a6a1f1dSLionel Sambuc BreakContinueStack.back().BreakCount = addCounters(
663*0a6a1f1dSLionel Sambuc BreakContinueStack.back().BreakCount, getCurrentRegionCount());
664*0a6a1f1dSLionel Sambuc setCurrentRegionUnreachable(S);
665*0a6a1f1dSLionel Sambuc }
666*0a6a1f1dSLionel Sambuc
VisitContinueStmt__anon3616bdc30111::CounterCoverageMappingBuilder667*0a6a1f1dSLionel Sambuc void VisitContinueStmt(const ContinueStmt *S) {
668*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
669*0a6a1f1dSLionel Sambuc assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
670*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount = addCounters(
671*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount, getCurrentRegionCount());
672*0a6a1f1dSLionel Sambuc setCurrentRegionUnreachable(S);
673*0a6a1f1dSLionel Sambuc }
674*0a6a1f1dSLionel Sambuc
VisitWhileStmt__anon3616bdc30111::CounterCoverageMappingBuilder675*0a6a1f1dSLionel Sambuc void VisitWhileStmt(const WhileStmt *S) {
676*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
677*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
678*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
679*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
680*0a6a1f1dSLionel Sambuc // Visit the body region first so the break/continue adjustments can be
681*0a6a1f1dSLionel Sambuc // included when visiting the condition.
682*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
683*0a6a1f1dSLionel Sambuc Visit(S->getBody());
684*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
685*0a6a1f1dSLionel Sambuc
686*0a6a1f1dSLionel Sambuc // ...then go back and propagate counts through the condition. The count
687*0a6a1f1dSLionel Sambuc // at the start of the condition is the sum of the incoming edges,
688*0a6a1f1dSLionel Sambuc // the backedge from the end of the loop body, and the edges from
689*0a6a1f1dSLionel Sambuc // continue statements.
690*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
691*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(
692*0a6a1f1dSLionel Sambuc addCounters(Cnt.getParentCount(),
693*0a6a1f1dSLionel Sambuc addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
694*0a6a1f1dSLionel Sambuc beginSourceRegionGroup(S->getCond());
695*0a6a1f1dSLionel Sambuc Visit(S->getCond());
696*0a6a1f1dSLionel Sambuc endSourceRegionGroup();
697*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
698*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
699*0a6a1f1dSLionel Sambuc }
700*0a6a1f1dSLionel Sambuc
VisitDoStmt__anon3616bdc30111::CounterCoverageMappingBuilder701*0a6a1f1dSLionel Sambuc void VisitDoStmt(const DoStmt *S) {
702*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
703*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
704*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
705*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
706*0a6a1f1dSLionel Sambuc Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
707*0a6a1f1dSLionel Sambuc Visit(S->getBody());
708*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
709*0a6a1f1dSLionel Sambuc
710*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
711*0a6a1f1dSLionel Sambuc // The count at the start of the condition is equal to the count at the
712*0a6a1f1dSLionel Sambuc // end of the body. The adjusted count does not include either the
713*0a6a1f1dSLionel Sambuc // fall-through count coming into the loop or the continue count, so add
714*0a6a1f1dSLionel Sambuc // both of those separately. This is coincidentally the same equation as
715*0a6a1f1dSLionel Sambuc // with while loops but for different reasons.
716*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(
717*0a6a1f1dSLionel Sambuc addCounters(Cnt.getParentCount(),
718*0a6a1f1dSLionel Sambuc addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
719*0a6a1f1dSLionel Sambuc Visit(S->getCond());
720*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
721*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
722*0a6a1f1dSLionel Sambuc }
723*0a6a1f1dSLionel Sambuc
VisitForStmt__anon3616bdc30111::CounterCoverageMappingBuilder724*0a6a1f1dSLionel Sambuc void VisitForStmt(const ForStmt *S) {
725*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
726*0a6a1f1dSLionel Sambuc if (S->getInit())
727*0a6a1f1dSLionel Sambuc Visit(S->getInit());
728*0a6a1f1dSLionel Sambuc
729*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
730*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
731*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
732*0a6a1f1dSLionel Sambuc // Visit the body region first. (This is basically the same as a while
733*0a6a1f1dSLionel Sambuc // loop; see further comments in VisitWhileStmt.)
734*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
735*0a6a1f1dSLionel Sambuc Visit(S->getBody());
736*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
737*0a6a1f1dSLionel Sambuc
738*0a6a1f1dSLionel Sambuc // The increment is essentially part of the body but it needs to include
739*0a6a1f1dSLionel Sambuc // the count for all the continue statements.
740*0a6a1f1dSLionel Sambuc if (S->getInc()) {
741*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(addCounters(
742*0a6a1f1dSLionel Sambuc getCurrentRegionCount(), BreakContinueStack.back().ContinueCount));
743*0a6a1f1dSLionel Sambuc beginSourceRegionGroup(S->getInc());
744*0a6a1f1dSLionel Sambuc Visit(S->getInc());
745*0a6a1f1dSLionel Sambuc endSourceRegionGroup();
746*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
747*0a6a1f1dSLionel Sambuc }
748*0a6a1f1dSLionel Sambuc
749*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
750*0a6a1f1dSLionel Sambuc
751*0a6a1f1dSLionel Sambuc // ...then go back and propagate counts through the condition.
752*0a6a1f1dSLionel Sambuc if (S->getCond()) {
753*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(
754*0a6a1f1dSLionel Sambuc addCounters(addCounters(Cnt.getParentCount(), Cnt.getAdjustedCount()),
755*0a6a1f1dSLionel Sambuc BC.ContinueCount));
756*0a6a1f1dSLionel Sambuc beginSourceRegionGroup(S->getCond());
757*0a6a1f1dSLionel Sambuc Visit(S->getCond());
758*0a6a1f1dSLionel Sambuc endSourceRegionGroup();
759*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
760*0a6a1f1dSLionel Sambuc }
761*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
762*0a6a1f1dSLionel Sambuc }
763*0a6a1f1dSLionel Sambuc
VisitCXXForRangeStmt__anon3616bdc30111::CounterCoverageMappingBuilder764*0a6a1f1dSLionel Sambuc void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
765*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
766*0a6a1f1dSLionel Sambuc Visit(S->getRangeStmt());
767*0a6a1f1dSLionel Sambuc Visit(S->getBeginEndStmt());
768*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
769*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
770*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
771*0a6a1f1dSLionel Sambuc // Visit the body region first. (This is basically the same as a while
772*0a6a1f1dSLionel Sambuc // loop; see further comments in VisitWhileStmt.)
773*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
774*0a6a1f1dSLionel Sambuc Visit(S->getBody());
775*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
776*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
777*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
778*0a6a1f1dSLionel Sambuc }
779*0a6a1f1dSLionel Sambuc
VisitObjCForCollectionStmt__anon3616bdc30111::CounterCoverageMappingBuilder780*0a6a1f1dSLionel Sambuc void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
781*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
782*0a6a1f1dSLionel Sambuc Visit(S->getElement());
783*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
784*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
785*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
786*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
787*0a6a1f1dSLionel Sambuc Visit(S->getBody());
788*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
789*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
790*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
791*0a6a1f1dSLionel Sambuc }
792*0a6a1f1dSLionel Sambuc
VisitSwitchStmt__anon3616bdc30111::CounterCoverageMappingBuilder793*0a6a1f1dSLionel Sambuc void VisitSwitchStmt(const SwitchStmt *S) {
794*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
795*0a6a1f1dSLionel Sambuc Visit(S->getCond());
796*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
797*0a6a1f1dSLionel Sambuc // Map the '}' for the body to have the same count as the regions after
798*0a6a1f1dSLionel Sambuc // the switch.
799*0a6a1f1dSLionel Sambuc SourceLocation RBracLoc;
800*0a6a1f1dSLionel Sambuc if (const auto *CS = dyn_cast<CompoundStmt>(S->getBody())) {
801*0a6a1f1dSLionel Sambuc mapSourceCodeRange(CS->getLBracLoc());
802*0a6a1f1dSLionel Sambuc setCurrentRegionUnreachable(S);
803*0a6a1f1dSLionel Sambuc for (Stmt::const_child_range I = CS->children(); I; ++I) {
804*0a6a1f1dSLionel Sambuc if (*I)
805*0a6a1f1dSLionel Sambuc this->Visit(*I);
806*0a6a1f1dSLionel Sambuc }
807*0a6a1f1dSLionel Sambuc RBracLoc = CS->getRBracLoc();
808*0a6a1f1dSLionel Sambuc } else {
809*0a6a1f1dSLionel Sambuc setCurrentRegionUnreachable(S);
810*0a6a1f1dSLionel Sambuc Visit(S->getBody());
811*0a6a1f1dSLionel Sambuc }
812*0a6a1f1dSLionel Sambuc // If the switch is inside a loop, add the continue counts.
813*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
814*0a6a1f1dSLionel Sambuc if (!BreakContinueStack.empty())
815*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount = addCounters(
816*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount, BC.ContinueCount);
817*0a6a1f1dSLionel Sambuc // Counter tracks the exit block of the switch.
818*0a6a1f1dSLionel Sambuc RegionMapper ExitCnt(this, S);
819*0a6a1f1dSLionel Sambuc ExitCnt.beginRegion();
820*0a6a1f1dSLionel Sambuc if (RBracLoc.isValid())
821*0a6a1f1dSLionel Sambuc mapSourceCodeRange(RBracLoc);
822*0a6a1f1dSLionel Sambuc }
823*0a6a1f1dSLionel Sambuc
VisitCaseStmt__anon3616bdc30111::CounterCoverageMappingBuilder824*0a6a1f1dSLionel Sambuc void VisitCaseStmt(const CaseStmt *S) {
825*0a6a1f1dSLionel Sambuc // Counter for this particular case. This counts only jumps from the
826*0a6a1f1dSLionel Sambuc // switch header and does not include fallthrough from the case before
827*0a6a1f1dSLionel Sambuc // this one.
828*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
829*0a6a1f1dSLionel Sambuc Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
830*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
831*0a6a1f1dSLionel Sambuc mapToken(S->getColonLoc());
832*0a6a1f1dSLionel Sambuc Visit(S->getSubStmt());
833*0a6a1f1dSLionel Sambuc }
834*0a6a1f1dSLionel Sambuc
VisitDefaultStmt__anon3616bdc30111::CounterCoverageMappingBuilder835*0a6a1f1dSLionel Sambuc void VisitDefaultStmt(const DefaultStmt *S) {
836*0a6a1f1dSLionel Sambuc // Counter for this default case. This does not include fallthrough from
837*0a6a1f1dSLionel Sambuc // the previous case.
838*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
839*0a6a1f1dSLionel Sambuc Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
840*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
841*0a6a1f1dSLionel Sambuc mapToken(S->getColonLoc());
842*0a6a1f1dSLionel Sambuc Visit(S->getSubStmt());
843*0a6a1f1dSLionel Sambuc }
844*0a6a1f1dSLionel Sambuc
VisitIfStmt__anon3616bdc30111::CounterCoverageMappingBuilder845*0a6a1f1dSLionel Sambuc void VisitIfStmt(const IfStmt *S) {
846*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
847*0a6a1f1dSLionel Sambuc Visit(S->getCond());
848*0a6a1f1dSLionel Sambuc mapToken(S->getElseLoc());
849*0a6a1f1dSLionel Sambuc
850*0a6a1f1dSLionel Sambuc // Counter tracks the "then" part of an if statement. The count for
851*0a6a1f1dSLionel Sambuc // the "else" part, if it exists, will be calculated from this counter.
852*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
853*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
854*0a6a1f1dSLionel Sambuc Visit(S->getThen());
855*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
856*0a6a1f1dSLionel Sambuc
857*0a6a1f1dSLionel Sambuc if (S->getElse()) {
858*0a6a1f1dSLionel Sambuc Cnt.beginElseRegion();
859*0a6a1f1dSLionel Sambuc Visit(S->getElse());
860*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
861*0a6a1f1dSLionel Sambuc }
862*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion();
863*0a6a1f1dSLionel Sambuc }
864*0a6a1f1dSLionel Sambuc
VisitCXXTryStmt__anon3616bdc30111::CounterCoverageMappingBuilder865*0a6a1f1dSLionel Sambuc void VisitCXXTryStmt(const CXXTryStmt *S) {
866*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
867*0a6a1f1dSLionel Sambuc Visit(S->getTryBlock());
868*0a6a1f1dSLionel Sambuc for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
869*0a6a1f1dSLionel Sambuc Visit(S->getHandler(I));
870*0a6a1f1dSLionel Sambuc // Counter tracks the continuation block of the try statement.
871*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
872*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
873*0a6a1f1dSLionel Sambuc }
874*0a6a1f1dSLionel Sambuc
VisitCXXCatchStmt__anon3616bdc30111::CounterCoverageMappingBuilder875*0a6a1f1dSLionel Sambuc void VisitCXXCatchStmt(const CXXCatchStmt *S) {
876*0a6a1f1dSLionel Sambuc mapSourceCodeRange(S->getLocStart());
877*0a6a1f1dSLionel Sambuc // Counter tracks the catch statement's handler block.
878*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, S);
879*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
880*0a6a1f1dSLionel Sambuc Visit(S->getHandlerBlock());
881*0a6a1f1dSLionel Sambuc }
882*0a6a1f1dSLionel Sambuc
VisitAbstractConditionalOperator__anon3616bdc30111::CounterCoverageMappingBuilder883*0a6a1f1dSLionel Sambuc void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
884*0a6a1f1dSLionel Sambuc Visit(E->getCond());
885*0a6a1f1dSLionel Sambuc mapToken(E->getQuestionLoc());
886*0a6a1f1dSLionel Sambuc mapToken(E->getColonLoc());
887*0a6a1f1dSLionel Sambuc
888*0a6a1f1dSLionel Sambuc // Counter tracks the "true" part of a conditional operator. The
889*0a6a1f1dSLionel Sambuc // count in the "false" part will be calculated from this counter.
890*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, E);
891*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
892*0a6a1f1dSLionel Sambuc Visit(E->getTrueExpr());
893*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
894*0a6a1f1dSLionel Sambuc
895*0a6a1f1dSLionel Sambuc Cnt.beginElseRegion();
896*0a6a1f1dSLionel Sambuc Visit(E->getFalseExpr());
897*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
898*0a6a1f1dSLionel Sambuc
899*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion();
900*0a6a1f1dSLionel Sambuc }
901*0a6a1f1dSLionel Sambuc
VisitBinLAnd__anon3616bdc30111::CounterCoverageMappingBuilder902*0a6a1f1dSLionel Sambuc void VisitBinLAnd(const BinaryOperator *E) {
903*0a6a1f1dSLionel Sambuc Visit(E->getLHS());
904*0a6a1f1dSLionel Sambuc mapToken(E->getOperatorLoc());
905*0a6a1f1dSLionel Sambuc // Counter tracks the right hand side of a logical and operator.
906*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, E);
907*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
908*0a6a1f1dSLionel Sambuc Visit(E->getRHS());
909*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
910*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion();
911*0a6a1f1dSLionel Sambuc }
912*0a6a1f1dSLionel Sambuc
VisitBinLOr__anon3616bdc30111::CounterCoverageMappingBuilder913*0a6a1f1dSLionel Sambuc void VisitBinLOr(const BinaryOperator *E) {
914*0a6a1f1dSLionel Sambuc Visit(E->getLHS());
915*0a6a1f1dSLionel Sambuc mapToken(E->getOperatorLoc());
916*0a6a1f1dSLionel Sambuc // Counter tracks the right hand side of a logical or operator.
917*0a6a1f1dSLionel Sambuc RegionMapper Cnt(this, E);
918*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
919*0a6a1f1dSLionel Sambuc Visit(E->getRHS());
920*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
921*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion();
922*0a6a1f1dSLionel Sambuc }
923*0a6a1f1dSLionel Sambuc
VisitParenExpr__anon3616bdc30111::CounterCoverageMappingBuilder924*0a6a1f1dSLionel Sambuc void VisitParenExpr(const ParenExpr *E) {
925*0a6a1f1dSLionel Sambuc mapToken(E->getLParen());
926*0a6a1f1dSLionel Sambuc Visit(E->getSubExpr());
927*0a6a1f1dSLionel Sambuc mapToken(E->getRParen());
928*0a6a1f1dSLionel Sambuc }
929*0a6a1f1dSLionel Sambuc
VisitBinaryOperator__anon3616bdc30111::CounterCoverageMappingBuilder930*0a6a1f1dSLionel Sambuc void VisitBinaryOperator(const BinaryOperator *E) {
931*0a6a1f1dSLionel Sambuc Visit(E->getLHS());
932*0a6a1f1dSLionel Sambuc mapToken(E->getOperatorLoc());
933*0a6a1f1dSLionel Sambuc Visit(E->getRHS());
934*0a6a1f1dSLionel Sambuc }
935*0a6a1f1dSLionel Sambuc
VisitUnaryOperator__anon3616bdc30111::CounterCoverageMappingBuilder936*0a6a1f1dSLionel Sambuc void VisitUnaryOperator(const UnaryOperator *E) {
937*0a6a1f1dSLionel Sambuc bool Postfix = E->isPostfix();
938*0a6a1f1dSLionel Sambuc if (!Postfix)
939*0a6a1f1dSLionel Sambuc mapToken(E->getOperatorLoc());
940*0a6a1f1dSLionel Sambuc Visit(E->getSubExpr());
941*0a6a1f1dSLionel Sambuc if (Postfix)
942*0a6a1f1dSLionel Sambuc mapToken(E->getOperatorLoc());
943*0a6a1f1dSLionel Sambuc }
944*0a6a1f1dSLionel Sambuc
VisitMemberExpr__anon3616bdc30111::CounterCoverageMappingBuilder945*0a6a1f1dSLionel Sambuc void VisitMemberExpr(const MemberExpr *E) {
946*0a6a1f1dSLionel Sambuc Visit(E->getBase());
947*0a6a1f1dSLionel Sambuc mapToken(E->getMemberLoc());
948*0a6a1f1dSLionel Sambuc }
949*0a6a1f1dSLionel Sambuc
VisitCallExpr__anon3616bdc30111::CounterCoverageMappingBuilder950*0a6a1f1dSLionel Sambuc void VisitCallExpr(const CallExpr *E) {
951*0a6a1f1dSLionel Sambuc Visit(E->getCallee());
952*0a6a1f1dSLionel Sambuc for (const auto &Arg : E->arguments())
953*0a6a1f1dSLionel Sambuc Visit(Arg);
954*0a6a1f1dSLionel Sambuc mapToken(E->getRParenLoc());
955*0a6a1f1dSLionel Sambuc }
956*0a6a1f1dSLionel Sambuc
VisitArraySubscriptExpr__anon3616bdc30111::CounterCoverageMappingBuilder957*0a6a1f1dSLionel Sambuc void VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
958*0a6a1f1dSLionel Sambuc Visit(E->getLHS());
959*0a6a1f1dSLionel Sambuc Visit(E->getRHS());
960*0a6a1f1dSLionel Sambuc mapToken(E->getRBracketLoc());
961*0a6a1f1dSLionel Sambuc }
962*0a6a1f1dSLionel Sambuc
VisitCStyleCastExpr__anon3616bdc30111::CounterCoverageMappingBuilder963*0a6a1f1dSLionel Sambuc void VisitCStyleCastExpr(const CStyleCastExpr *E) {
964*0a6a1f1dSLionel Sambuc mapToken(E->getLParenLoc());
965*0a6a1f1dSLionel Sambuc mapToken(E->getRParenLoc());
966*0a6a1f1dSLionel Sambuc Visit(E->getSubExpr());
967*0a6a1f1dSLionel Sambuc }
968*0a6a1f1dSLionel Sambuc
969*0a6a1f1dSLionel Sambuc // Map literals as tokens so that the macros like #define PI 3.14
970*0a6a1f1dSLionel Sambuc // won't generate coverage mapping regions.
971*0a6a1f1dSLionel Sambuc
VisitIntegerLiteral__anon3616bdc30111::CounterCoverageMappingBuilder972*0a6a1f1dSLionel Sambuc void VisitIntegerLiteral(const IntegerLiteral *E) {
973*0a6a1f1dSLionel Sambuc mapToken(E->getLocStart());
974*0a6a1f1dSLionel Sambuc }
975*0a6a1f1dSLionel Sambuc
VisitFloatingLiteral__anon3616bdc30111::CounterCoverageMappingBuilder976*0a6a1f1dSLionel Sambuc void VisitFloatingLiteral(const FloatingLiteral *E) {
977*0a6a1f1dSLionel Sambuc mapToken(E->getLocStart());
978*0a6a1f1dSLionel Sambuc }
979*0a6a1f1dSLionel Sambuc
VisitCharacterLiteral__anon3616bdc30111::CounterCoverageMappingBuilder980*0a6a1f1dSLionel Sambuc void VisitCharacterLiteral(const CharacterLiteral *E) {
981*0a6a1f1dSLionel Sambuc mapToken(E->getLocStart());
982*0a6a1f1dSLionel Sambuc }
983*0a6a1f1dSLionel Sambuc
VisitStringLiteral__anon3616bdc30111::CounterCoverageMappingBuilder984*0a6a1f1dSLionel Sambuc void VisitStringLiteral(const StringLiteral *E) {
985*0a6a1f1dSLionel Sambuc mapToken(E->getLocStart());
986*0a6a1f1dSLionel Sambuc }
987*0a6a1f1dSLionel Sambuc
VisitImaginaryLiteral__anon3616bdc30111::CounterCoverageMappingBuilder988*0a6a1f1dSLionel Sambuc void VisitImaginaryLiteral(const ImaginaryLiteral *E) {
989*0a6a1f1dSLionel Sambuc mapToken(E->getLocStart());
990*0a6a1f1dSLionel Sambuc }
991*0a6a1f1dSLionel Sambuc
VisitObjCMessageExpr__anon3616bdc30111::CounterCoverageMappingBuilder992*0a6a1f1dSLionel Sambuc void VisitObjCMessageExpr(const ObjCMessageExpr *E) {
993*0a6a1f1dSLionel Sambuc mapToken(E->getLeftLoc());
994*0a6a1f1dSLionel Sambuc for (Stmt::const_child_range I = static_cast<const Stmt*>(E)->children(); I;
995*0a6a1f1dSLionel Sambuc ++I) {
996*0a6a1f1dSLionel Sambuc if (*I)
997*0a6a1f1dSLionel Sambuc this->Visit(*I);
998*0a6a1f1dSLionel Sambuc }
999*0a6a1f1dSLionel Sambuc mapToken(E->getRightLoc());
1000*0a6a1f1dSLionel Sambuc }
1001*0a6a1f1dSLionel Sambuc };
1002*0a6a1f1dSLionel Sambuc }
1003*0a6a1f1dSLionel Sambuc
isMachO(const CodeGenModule & CGM)1004*0a6a1f1dSLionel Sambuc static bool isMachO(const CodeGenModule &CGM) {
1005*0a6a1f1dSLionel Sambuc return CGM.getTarget().getTriple().isOSBinFormatMachO();
1006*0a6a1f1dSLionel Sambuc }
1007*0a6a1f1dSLionel Sambuc
getCoverageSection(const CodeGenModule & CGM)1008*0a6a1f1dSLionel Sambuc static StringRef getCoverageSection(const CodeGenModule &CGM) {
1009*0a6a1f1dSLionel Sambuc return isMachO(CGM) ? "__DATA,__llvm_covmap" : "__llvm_covmap";
1010*0a6a1f1dSLionel Sambuc }
1011*0a6a1f1dSLionel Sambuc
dump(llvm::raw_ostream & OS,const CoverageMappingRecord & Function)1012*0a6a1f1dSLionel Sambuc static void dump(llvm::raw_ostream &OS, const CoverageMappingRecord &Function) {
1013*0a6a1f1dSLionel Sambuc OS << Function.FunctionName << ":\n";
1014*0a6a1f1dSLionel Sambuc CounterMappingContext Ctx(Function.Expressions);
1015*0a6a1f1dSLionel Sambuc for (const auto &R : Function.MappingRegions) {
1016*0a6a1f1dSLionel Sambuc OS.indent(2);
1017*0a6a1f1dSLionel Sambuc switch (R.Kind) {
1018*0a6a1f1dSLionel Sambuc case CounterMappingRegion::CodeRegion:
1019*0a6a1f1dSLionel Sambuc break;
1020*0a6a1f1dSLionel Sambuc case CounterMappingRegion::ExpansionRegion:
1021*0a6a1f1dSLionel Sambuc OS << "Expansion,";
1022*0a6a1f1dSLionel Sambuc break;
1023*0a6a1f1dSLionel Sambuc case CounterMappingRegion::SkippedRegion:
1024*0a6a1f1dSLionel Sambuc OS << "Skipped,";
1025*0a6a1f1dSLionel Sambuc break;
1026*0a6a1f1dSLionel Sambuc }
1027*0a6a1f1dSLionel Sambuc
1028*0a6a1f1dSLionel Sambuc OS << "File " << R.FileID << ", " << R.LineStart << ":"
1029*0a6a1f1dSLionel Sambuc << R.ColumnStart << " -> " << R.LineEnd << ":" << R.ColumnEnd
1030*0a6a1f1dSLionel Sambuc << " = ";
1031*0a6a1f1dSLionel Sambuc Ctx.dump(R.Count);
1032*0a6a1f1dSLionel Sambuc OS << " (HasCodeBefore = " << R.HasCodeBefore;
1033*0a6a1f1dSLionel Sambuc if (R.Kind == CounterMappingRegion::ExpansionRegion)
1034*0a6a1f1dSLionel Sambuc OS << ", Expanded file = " << R.ExpandedFileID;
1035*0a6a1f1dSLionel Sambuc
1036*0a6a1f1dSLionel Sambuc OS << ")\n";
1037*0a6a1f1dSLionel Sambuc }
1038*0a6a1f1dSLionel Sambuc }
1039*0a6a1f1dSLionel Sambuc
addFunctionMappingRecord(llvm::GlobalVariable * FunctionName,StringRef FunctionNameValue,uint64_t FunctionHash,const std::string & CoverageMapping)1040*0a6a1f1dSLionel Sambuc void CoverageMappingModuleGen::addFunctionMappingRecord(
1041*0a6a1f1dSLionel Sambuc llvm::GlobalVariable *FunctionName, StringRef FunctionNameValue,
1042*0a6a1f1dSLionel Sambuc uint64_t FunctionHash, const std::string &CoverageMapping) {
1043*0a6a1f1dSLionel Sambuc llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1044*0a6a1f1dSLionel Sambuc auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
1045*0a6a1f1dSLionel Sambuc auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
1046*0a6a1f1dSLionel Sambuc auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
1047*0a6a1f1dSLionel Sambuc if (!FunctionRecordTy) {
1048*0a6a1f1dSLionel Sambuc llvm::Type *FunctionRecordTypes[] = {Int8PtrTy, Int32Ty, Int32Ty, Int64Ty};
1049*0a6a1f1dSLionel Sambuc FunctionRecordTy =
1050*0a6a1f1dSLionel Sambuc llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes));
1051*0a6a1f1dSLionel Sambuc }
1052*0a6a1f1dSLionel Sambuc
1053*0a6a1f1dSLionel Sambuc llvm::Constant *FunctionRecordVals[] = {
1054*0a6a1f1dSLionel Sambuc llvm::ConstantExpr::getBitCast(FunctionName, Int8PtrTy),
1055*0a6a1f1dSLionel Sambuc llvm::ConstantInt::get(Int32Ty, FunctionNameValue.size()),
1056*0a6a1f1dSLionel Sambuc llvm::ConstantInt::get(Int32Ty, CoverageMapping.size()),
1057*0a6a1f1dSLionel Sambuc llvm::ConstantInt::get(Int64Ty, FunctionHash)};
1058*0a6a1f1dSLionel Sambuc FunctionRecords.push_back(llvm::ConstantStruct::get(
1059*0a6a1f1dSLionel Sambuc FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
1060*0a6a1f1dSLionel Sambuc CoverageMappings += CoverageMapping;
1061*0a6a1f1dSLionel Sambuc
1062*0a6a1f1dSLionel Sambuc if (CGM.getCodeGenOpts().DumpCoverageMapping) {
1063*0a6a1f1dSLionel Sambuc // Dump the coverage mapping data for this function by decoding the
1064*0a6a1f1dSLionel Sambuc // encoded data. This allows us to dump the mapping regions which were
1065*0a6a1f1dSLionel Sambuc // also processed by the CoverageMappingWriter which performs
1066*0a6a1f1dSLionel Sambuc // additional minimization operations such as reducing the number of
1067*0a6a1f1dSLionel Sambuc // expressions.
1068*0a6a1f1dSLionel Sambuc std::vector<StringRef> Filenames;
1069*0a6a1f1dSLionel Sambuc std::vector<CounterExpression> Expressions;
1070*0a6a1f1dSLionel Sambuc std::vector<CounterMappingRegion> Regions;
1071*0a6a1f1dSLionel Sambuc llvm::SmallVector<StringRef, 16> FilenameRefs;
1072*0a6a1f1dSLionel Sambuc FilenameRefs.resize(FileEntries.size());
1073*0a6a1f1dSLionel Sambuc for (const auto &Entry : FileEntries)
1074*0a6a1f1dSLionel Sambuc FilenameRefs[Entry.second] = Entry.first->getName();
1075*0a6a1f1dSLionel Sambuc RawCoverageMappingReader Reader(FunctionNameValue, CoverageMapping,
1076*0a6a1f1dSLionel Sambuc FilenameRefs,
1077*0a6a1f1dSLionel Sambuc Filenames, Expressions, Regions);
1078*0a6a1f1dSLionel Sambuc CoverageMappingRecord FunctionRecord;
1079*0a6a1f1dSLionel Sambuc if (Reader.read(FunctionRecord))
1080*0a6a1f1dSLionel Sambuc return;
1081*0a6a1f1dSLionel Sambuc dump(llvm::outs(), FunctionRecord);
1082*0a6a1f1dSLionel Sambuc }
1083*0a6a1f1dSLionel Sambuc }
1084*0a6a1f1dSLionel Sambuc
emit()1085*0a6a1f1dSLionel Sambuc void CoverageMappingModuleGen::emit() {
1086*0a6a1f1dSLionel Sambuc if (FunctionRecords.empty())
1087*0a6a1f1dSLionel Sambuc return;
1088*0a6a1f1dSLionel Sambuc llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1089*0a6a1f1dSLionel Sambuc auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
1090*0a6a1f1dSLionel Sambuc
1091*0a6a1f1dSLionel Sambuc // Create the filenames and merge them with coverage mappings
1092*0a6a1f1dSLionel Sambuc llvm::SmallVector<std::string, 16> FilenameStrs;
1093*0a6a1f1dSLionel Sambuc llvm::SmallVector<StringRef, 16> FilenameRefs;
1094*0a6a1f1dSLionel Sambuc FilenameStrs.resize(FileEntries.size());
1095*0a6a1f1dSLionel Sambuc FilenameRefs.resize(FileEntries.size());
1096*0a6a1f1dSLionel Sambuc for (const auto &Entry : FileEntries) {
1097*0a6a1f1dSLionel Sambuc llvm::SmallString<256> Path(Entry.first->getName());
1098*0a6a1f1dSLionel Sambuc llvm::sys::fs::make_absolute(Path);
1099*0a6a1f1dSLionel Sambuc
1100*0a6a1f1dSLionel Sambuc auto I = Entry.second;
1101*0a6a1f1dSLionel Sambuc FilenameStrs[I] = std::move(std::string(Path.begin(), Path.end()));
1102*0a6a1f1dSLionel Sambuc FilenameRefs[I] = FilenameStrs[I];
1103*0a6a1f1dSLionel Sambuc }
1104*0a6a1f1dSLionel Sambuc
1105*0a6a1f1dSLionel Sambuc std::string FilenamesAndCoverageMappings;
1106*0a6a1f1dSLionel Sambuc llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
1107*0a6a1f1dSLionel Sambuc CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
1108*0a6a1f1dSLionel Sambuc OS << CoverageMappings;
1109*0a6a1f1dSLionel Sambuc size_t CoverageMappingSize = CoverageMappings.size();
1110*0a6a1f1dSLionel Sambuc size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
1111*0a6a1f1dSLionel Sambuc // Append extra zeroes if necessary to ensure that the size of the filenames
1112*0a6a1f1dSLionel Sambuc // and coverage mappings is a multiple of 8.
1113*0a6a1f1dSLionel Sambuc if (size_t Rem = OS.str().size() % 8) {
1114*0a6a1f1dSLionel Sambuc CoverageMappingSize += 8 - Rem;
1115*0a6a1f1dSLionel Sambuc for (size_t I = 0, S = 8 - Rem; I < S; ++I)
1116*0a6a1f1dSLionel Sambuc OS << '\0';
1117*0a6a1f1dSLionel Sambuc }
1118*0a6a1f1dSLionel Sambuc auto *FilenamesAndMappingsVal =
1119*0a6a1f1dSLionel Sambuc llvm::ConstantDataArray::getString(Ctx, OS.str(), false);
1120*0a6a1f1dSLionel Sambuc
1121*0a6a1f1dSLionel Sambuc // Create the deferred function records array
1122*0a6a1f1dSLionel Sambuc auto RecordsTy =
1123*0a6a1f1dSLionel Sambuc llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
1124*0a6a1f1dSLionel Sambuc auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
1125*0a6a1f1dSLionel Sambuc
1126*0a6a1f1dSLionel Sambuc // Create the coverage data record
1127*0a6a1f1dSLionel Sambuc llvm::Type *CovDataTypes[] = {Int32Ty, Int32Ty,
1128*0a6a1f1dSLionel Sambuc Int32Ty, Int32Ty,
1129*0a6a1f1dSLionel Sambuc RecordsTy, FilenamesAndMappingsVal->getType()};
1130*0a6a1f1dSLionel Sambuc auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
1131*0a6a1f1dSLionel Sambuc llvm::Constant *TUDataVals[] = {
1132*0a6a1f1dSLionel Sambuc llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
1133*0a6a1f1dSLionel Sambuc llvm::ConstantInt::get(Int32Ty, FilenamesSize),
1134*0a6a1f1dSLionel Sambuc llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
1135*0a6a1f1dSLionel Sambuc llvm::ConstantInt::get(Int32Ty,
1136*0a6a1f1dSLionel Sambuc /*Version=*/CoverageMappingVersion1),
1137*0a6a1f1dSLionel Sambuc RecordsVal, FilenamesAndMappingsVal};
1138*0a6a1f1dSLionel Sambuc auto CovDataVal =
1139*0a6a1f1dSLionel Sambuc llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
1140*0a6a1f1dSLionel Sambuc auto CovData = new llvm::GlobalVariable(CGM.getModule(), CovDataTy, true,
1141*0a6a1f1dSLionel Sambuc llvm::GlobalValue::InternalLinkage,
1142*0a6a1f1dSLionel Sambuc CovDataVal,
1143*0a6a1f1dSLionel Sambuc "__llvm_coverage_mapping");
1144*0a6a1f1dSLionel Sambuc
1145*0a6a1f1dSLionel Sambuc CovData->setSection(getCoverageSection(CGM));
1146*0a6a1f1dSLionel Sambuc CovData->setAlignment(8);
1147*0a6a1f1dSLionel Sambuc
1148*0a6a1f1dSLionel Sambuc // Make sure the data doesn't get deleted.
1149*0a6a1f1dSLionel Sambuc CGM.addUsedGlobal(CovData);
1150*0a6a1f1dSLionel Sambuc }
1151*0a6a1f1dSLionel Sambuc
getFileID(const FileEntry * File)1152*0a6a1f1dSLionel Sambuc unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
1153*0a6a1f1dSLionel Sambuc auto It = FileEntries.find(File);
1154*0a6a1f1dSLionel Sambuc if (It != FileEntries.end())
1155*0a6a1f1dSLionel Sambuc return It->second;
1156*0a6a1f1dSLionel Sambuc unsigned FileID = FileEntries.size();
1157*0a6a1f1dSLionel Sambuc FileEntries.insert(std::make_pair(File, FileID));
1158*0a6a1f1dSLionel Sambuc return FileID;
1159*0a6a1f1dSLionel Sambuc }
1160*0a6a1f1dSLionel Sambuc
emitCounterMapping(const Decl * D,llvm::raw_ostream & OS)1161*0a6a1f1dSLionel Sambuc void CoverageMappingGen::emitCounterMapping(const Decl *D,
1162*0a6a1f1dSLionel Sambuc llvm::raw_ostream &OS) {
1163*0a6a1f1dSLionel Sambuc assert(CounterMap);
1164*0a6a1f1dSLionel Sambuc CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts);
1165*0a6a1f1dSLionel Sambuc Walker.VisitDecl(D);
1166*0a6a1f1dSLionel Sambuc Walker.write(OS);
1167*0a6a1f1dSLionel Sambuc }
1168*0a6a1f1dSLionel Sambuc
emitEmptyMapping(const Decl * D,llvm::raw_ostream & OS)1169*0a6a1f1dSLionel Sambuc void CoverageMappingGen::emitEmptyMapping(const Decl *D,
1170*0a6a1f1dSLionel Sambuc llvm::raw_ostream &OS) {
1171*0a6a1f1dSLionel Sambuc EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
1172*0a6a1f1dSLionel Sambuc Walker.VisitDecl(D);
1173*0a6a1f1dSLionel Sambuc Walker.write(OS);
1174*0a6a1f1dSLionel Sambuc }
1175