1 | //===---- CoverageMappingGen.h - Coverage mapping generation ----*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Instrumentation-based code coverage mapping generator |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H |
14 | #define LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H |
15 | |
16 | #include "clang/Basic/LLVM.h" |
17 | #include "clang/Basic/SourceLocation.h" |
18 | #include "clang/Lex/PPCallbacks.h" |
19 | #include "clang/Lex/Preprocessor.h" |
20 | #include "llvm/ADT/DenseMap.h" |
21 | #include "llvm/IR/GlobalValue.h" |
22 | #include "llvm/Support/CommandLine.h" |
23 | #include "llvm/Support/raw_ostream.h" |
24 | |
25 | namespace llvm::coverage { |
26 | extern cl::opt<bool> ; |
27 | } |
28 | |
29 | namespace clang { |
30 | |
31 | class LangOptions; |
32 | class SourceManager; |
33 | class FileEntry; |
34 | class Preprocessor; |
35 | class Decl; |
36 | class Stmt; |
37 | |
38 | struct SkippedRange { |
39 | enum Kind { |
40 | PPIfElse, // Preprocessor #if/#else ... |
41 | EmptyLine, |
42 | , |
43 | }; |
44 | |
45 | SourceRange Range; |
46 | // The location of token before the skipped source range. |
47 | SourceLocation PrevTokLoc; |
48 | // The location of token after the skipped source range. |
49 | SourceLocation NextTokLoc; |
50 | // The nature of this skipped range |
51 | Kind RangeKind; |
52 | |
53 | bool () { return RangeKind == Comment; } |
54 | bool isEmptyLine() { return RangeKind == EmptyLine; } |
55 | bool isPPIfElse() { return RangeKind == PPIfElse; } |
56 | |
57 | SkippedRange(SourceRange Range, Kind K, |
58 | SourceLocation PrevTokLoc = SourceLocation(), |
59 | SourceLocation NextTokLoc = SourceLocation()) |
60 | : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc), |
61 | RangeKind(K) {} |
62 | }; |
63 | |
64 | /// Stores additional source code information like skipped ranges which |
65 | /// is required by the coverage mapping generator and is obtained from |
66 | /// the preprocessor. |
67 | class CoverageSourceInfo : public PPCallbacks, |
68 | public CommentHandler, |
69 | public EmptylineHandler { |
70 | // A vector of skipped source ranges and PrevTokLoc with NextTokLoc. |
71 | std::vector<SkippedRange> SkippedRanges; |
72 | |
73 | SourceManager &SourceMgr; |
74 | |
75 | public: |
76 | // Location of the token parsed before HandleComment is called. This is |
77 | // updated every time Preprocessor::Lex lexes a new token. |
78 | SourceLocation PrevTokLoc; |
79 | |
80 | CoverageSourceInfo(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {} |
81 | |
82 | std::vector<SkippedRange> &getSkippedRanges() { return SkippedRanges; } |
83 | |
84 | void AddSkippedRange(SourceRange Range, SkippedRange::Kind RangeKind); |
85 | |
86 | void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override; |
87 | |
88 | void HandleEmptyline(SourceRange Range) override; |
89 | |
90 | bool HandleComment(Preprocessor &PP, SourceRange Range) override; |
91 | |
92 | void updateNextTokLoc(SourceLocation Loc); |
93 | }; |
94 | |
95 | namespace CodeGen { |
96 | |
97 | class CodeGenModule; |
98 | |
99 | namespace MCDC { |
100 | struct State; |
101 | } |
102 | |
103 | /// Organizes the cross-function state that is used while generating |
104 | /// code coverage mapping data. |
105 | class CoverageMappingModuleGen { |
106 | /// Information needed to emit a coverage record for a function. |
107 | struct FunctionInfo { |
108 | uint64_t NameHash; |
109 | uint64_t FuncHash; |
110 | std::string CoverageMapping; |
111 | bool IsUsed; |
112 | }; |
113 | |
114 | CodeGenModule &CGM; |
115 | CoverageSourceInfo &SourceInfo; |
116 | llvm::SmallDenseMap<FileEntryRef, unsigned, 8> FileEntries; |
117 | std::vector<llvm::Constant *> FunctionNames; |
118 | std::vector<FunctionInfo> FunctionRecords; |
119 | |
120 | std::string getCurrentDirname(); |
121 | std::string normalizeFilename(StringRef Filename); |
122 | |
123 | /// Emit a function record. |
124 | void emitFunctionMappingRecord(const FunctionInfo &Info, |
125 | uint64_t FilenamesRef); |
126 | |
127 | public: |
128 | static CoverageSourceInfo *setUpCoverageCallbacks(Preprocessor &PP); |
129 | |
130 | CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo); |
131 | |
132 | CoverageSourceInfo &getSourceInfo() const { |
133 | return SourceInfo; |
134 | } |
135 | |
136 | /// Add a function's coverage mapping record to the collection of the |
137 | /// function mapping records. |
138 | void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, |
139 | StringRef FunctionNameValue, |
140 | uint64_t FunctionHash, |
141 | const std::string &CoverageMapping, |
142 | bool IsUsed = true); |
143 | |
144 | /// Emit the coverage mapping data for a translation unit. |
145 | void emit(); |
146 | |
147 | /// Return the coverage mapping translation unit file id |
148 | /// for the given file. |
149 | unsigned getFileID(FileEntryRef File); |
150 | |
151 | /// Return an interface into CodeGenModule. |
152 | CodeGenModule &getCodeGenModule() { return CGM; } |
153 | }; |
154 | |
155 | /// Organizes the per-function state that is used while generating |
156 | /// code coverage mapping data. |
157 | class CoverageMappingGen { |
158 | CoverageMappingModuleGen &CVM; |
159 | SourceManager &SM; |
160 | const LangOptions &LangOpts; |
161 | llvm::DenseMap<const Stmt *, unsigned> *CounterMap; |
162 | MCDC::State *MCDCState; |
163 | |
164 | public: |
165 | CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM, |
166 | const LangOptions &LangOpts) |
167 | : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr), |
168 | MCDCState(nullptr) {} |
169 | |
170 | CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM, |
171 | const LangOptions &LangOpts, |
172 | llvm::DenseMap<const Stmt *, unsigned> *CounterMap, |
173 | MCDC::State *MCDCState) |
174 | : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap), |
175 | MCDCState(MCDCState) {} |
176 | |
177 | /// Emit the coverage mapping data which maps the regions of |
178 | /// code to counters that will be used to find the execution |
179 | /// counts for those regions. |
180 | void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS); |
181 | |
182 | /// Emit the coverage mapping data for an unused function. |
183 | /// It creates mapping regions with the counter of zero. |
184 | void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS); |
185 | }; |
186 | |
187 | } // end namespace CodeGen |
188 | } // end namespace clang |
189 | |
190 | #endif |
191 | |