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