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