xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CoverageMappingGen.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===---- CoverageMappingGen.h - Coverage mapping generation ----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Instrumentation-based code coverage mapping generator
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H
140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
170b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
180b57cec5SDimitry Andric #include "clang/Lex/PPCallbacks.h"
19e8d8bef9SDimitry Andric #include "clang/Lex/Preprocessor.h"
200b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
210b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
22*0fca6ea1SDimitry Andric #include "llvm/Support/CommandLine.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric 
25*0fca6ea1SDimitry Andric namespace llvm::coverage {
26*0fca6ea1SDimitry Andric extern cl::opt<bool> SystemHeadersCoverage;
27*0fca6ea1SDimitry Andric }
28*0fca6ea1SDimitry Andric 
290b57cec5SDimitry Andric namespace clang {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class LangOptions;
320b57cec5SDimitry Andric class SourceManager;
330b57cec5SDimitry Andric class FileEntry;
340b57cec5SDimitry Andric class Preprocessor;
350b57cec5SDimitry Andric class Decl;
360b57cec5SDimitry Andric class Stmt;
370b57cec5SDimitry Andric 
38e8d8bef9SDimitry Andric struct SkippedRange {
3981ad6265SDimitry Andric   enum Kind {
4081ad6265SDimitry Andric     PPIfElse, // Preprocessor #if/#else ...
4181ad6265SDimitry Andric     EmptyLine,
4281ad6265SDimitry Andric     Comment,
4381ad6265SDimitry Andric   };
4481ad6265SDimitry Andric 
45e8d8bef9SDimitry Andric   SourceRange Range;
46e8d8bef9SDimitry Andric   // The location of token before the skipped source range.
47e8d8bef9SDimitry Andric   SourceLocation PrevTokLoc;
48e8d8bef9SDimitry Andric   // The location of token after the skipped source range.
49e8d8bef9SDimitry Andric   SourceLocation NextTokLoc;
5081ad6265SDimitry Andric   // The nature of this skipped range
5181ad6265SDimitry Andric   Kind RangeKind;
52e8d8bef9SDimitry Andric 
isCommentSkippedRange5381ad6265SDimitry Andric   bool isComment() { return RangeKind == Comment; }
isEmptyLineSkippedRange5481ad6265SDimitry Andric   bool isEmptyLine() { return RangeKind == EmptyLine; }
isPPIfElseSkippedRange5581ad6265SDimitry Andric   bool isPPIfElse() { return RangeKind == PPIfElse; }
5681ad6265SDimitry Andric 
5781ad6265SDimitry Andric   SkippedRange(SourceRange Range, Kind K,
5881ad6265SDimitry Andric                SourceLocation PrevTokLoc = SourceLocation(),
59e8d8bef9SDimitry Andric                SourceLocation NextTokLoc = SourceLocation())
RangeSkippedRange6081ad6265SDimitry Andric       : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc),
6181ad6265SDimitry Andric         RangeKind(K) {}
62e8d8bef9SDimitry Andric };
63e8d8bef9SDimitry Andric 
640b57cec5SDimitry Andric /// Stores additional source code information like skipped ranges which
650b57cec5SDimitry Andric /// is required by the coverage mapping generator and is obtained from
660b57cec5SDimitry Andric /// the preprocessor.
67e8d8bef9SDimitry Andric class CoverageSourceInfo : public PPCallbacks,
68e8d8bef9SDimitry Andric                            public CommentHandler,
69e8d8bef9SDimitry Andric                            public EmptylineHandler {
70e8d8bef9SDimitry Andric   // A vector of skipped source ranges and PrevTokLoc with NextTokLoc.
71e8d8bef9SDimitry Andric   std::vector<SkippedRange> SkippedRanges;
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric   SourceManager &SourceMgr;
74e8d8bef9SDimitry Andric 
750b57cec5SDimitry Andric public:
76e8d8bef9SDimitry Andric   // Location of the token parsed before HandleComment is called. This is
77e8d8bef9SDimitry Andric   // updated every time Preprocessor::Lex lexes a new token.
78e8d8bef9SDimitry Andric   SourceLocation PrevTokLoc;
79e8d8bef9SDimitry Andric 
CoverageSourceInfo(SourceManager & SourceMgr)80e8d8bef9SDimitry Andric   CoverageSourceInfo(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
81e8d8bef9SDimitry Andric 
getSkippedRanges()82e8d8bef9SDimitry Andric   std::vector<SkippedRange> &getSkippedRanges() { return SkippedRanges; }
83e8d8bef9SDimitry Andric 
8481ad6265SDimitry Andric   void AddSkippedRange(SourceRange Range, SkippedRange::Kind RangeKind);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
87e8d8bef9SDimitry Andric 
88e8d8bef9SDimitry Andric   void HandleEmptyline(SourceRange Range) override;
89e8d8bef9SDimitry Andric 
90e8d8bef9SDimitry Andric   bool HandleComment(Preprocessor &PP, SourceRange Range) override;
91e8d8bef9SDimitry Andric 
92e8d8bef9SDimitry Andric   void updateNextTokLoc(SourceLocation Loc);
930b57cec5SDimitry Andric };
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric namespace CodeGen {
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric class CodeGenModule;
980b57cec5SDimitry Andric 
99*0fca6ea1SDimitry Andric namespace MCDC {
100*0fca6ea1SDimitry Andric struct State;
101*0fca6ea1SDimitry Andric }
102*0fca6ea1SDimitry Andric 
1030b57cec5SDimitry Andric /// Organizes the cross-function state that is used while generating
1040b57cec5SDimitry Andric /// code coverage mapping data.
1050b57cec5SDimitry Andric class CoverageMappingModuleGen {
1065ffd83dbSDimitry Andric   /// Information needed to emit a coverage record for a function.
1075ffd83dbSDimitry Andric   struct FunctionInfo {
1085ffd83dbSDimitry Andric     uint64_t NameHash;
1095ffd83dbSDimitry Andric     uint64_t FuncHash;
1105ffd83dbSDimitry Andric     std::string CoverageMapping;
1115ffd83dbSDimitry Andric     bool IsUsed;
1125ffd83dbSDimitry Andric   };
1135ffd83dbSDimitry Andric 
1140b57cec5SDimitry Andric   CodeGenModule &CGM;
1150b57cec5SDimitry Andric   CoverageSourceInfo &SourceInfo;
1165f757f3fSDimitry Andric   llvm::SmallDenseMap<FileEntryRef, unsigned, 8> FileEntries;
1170b57cec5SDimitry Andric   std::vector<llvm::Constant *> FunctionNames;
1185ffd83dbSDimitry Andric   std::vector<FunctionInfo> FunctionRecords;
119e8d8bef9SDimitry Andric 
120fe6060f1SDimitry Andric   std::string getCurrentDirname();
121e8d8bef9SDimitry Andric   std::string normalizeFilename(StringRef Filename);
1225ffd83dbSDimitry Andric 
1235ffd83dbSDimitry Andric   /// Emit a function record.
1245ffd83dbSDimitry Andric   void emitFunctionMappingRecord(const FunctionInfo &Info,
1255ffd83dbSDimitry Andric                                  uint64_t FilenamesRef);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric public:
128e8d8bef9SDimitry Andric   static CoverageSourceInfo *setUpCoverageCallbacks(Preprocessor &PP);
129e8d8bef9SDimitry Andric 
130e8d8bef9SDimitry Andric   CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo);
1310b57cec5SDimitry Andric 
getSourceInfo()1320b57cec5SDimitry Andric   CoverageSourceInfo &getSourceInfo() const {
1330b57cec5SDimitry Andric     return SourceInfo;
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   /// Add a function's coverage mapping record to the collection of the
1370b57cec5SDimitry Andric   /// function mapping records.
1380b57cec5SDimitry Andric   void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
1390b57cec5SDimitry Andric                                 StringRef FunctionNameValue,
1400b57cec5SDimitry Andric                                 uint64_t FunctionHash,
1410b57cec5SDimitry Andric                                 const std::string &CoverageMapping,
1420b57cec5SDimitry Andric                                 bool IsUsed = true);
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   /// Emit the coverage mapping data for a translation unit.
1450b57cec5SDimitry Andric   void emit();
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   /// Return the coverage mapping translation unit file id
1480b57cec5SDimitry Andric   /// for the given file.
1495f757f3fSDimitry Andric   unsigned getFileID(FileEntryRef File);
150e8d8bef9SDimitry Andric 
151e8d8bef9SDimitry Andric   /// Return an interface into CodeGenModule.
getCodeGenModule()152e8d8bef9SDimitry Andric   CodeGenModule &getCodeGenModule() { return CGM; }
1530b57cec5SDimitry Andric };
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric /// Organizes the per-function state that is used while generating
1560b57cec5SDimitry Andric /// code coverage mapping data.
1570b57cec5SDimitry Andric class CoverageMappingGen {
1580b57cec5SDimitry Andric   CoverageMappingModuleGen &CVM;
1590b57cec5SDimitry Andric   SourceManager &SM;
1600b57cec5SDimitry Andric   const LangOptions &LangOpts;
1610b57cec5SDimitry Andric   llvm::DenseMap<const Stmt *, unsigned> *CounterMap;
162*0fca6ea1SDimitry Andric   MCDC::State *MCDCState;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric public:
CoverageMappingGen(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts)1650b57cec5SDimitry Andric   CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
1660b57cec5SDimitry Andric                      const LangOptions &LangOpts)
1671db9f3b2SDimitry Andric       : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr),
168*0fca6ea1SDimitry Andric         MCDCState(nullptr) {}
1690b57cec5SDimitry Andric 
CoverageMappingGen(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts,llvm::DenseMap<const Stmt *,unsigned> * CounterMap,MCDC::State * MCDCState)1700b57cec5SDimitry Andric   CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
1710b57cec5SDimitry Andric                      const LangOptions &LangOpts,
1721db9f3b2SDimitry Andric                      llvm::DenseMap<const Stmt *, unsigned> *CounterMap,
173*0fca6ea1SDimitry Andric                      MCDC::State *MCDCState)
1741db9f3b2SDimitry Andric       : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap),
175*0fca6ea1SDimitry Andric         MCDCState(MCDCState) {}
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   /// Emit the coverage mapping data which maps the regions of
1780b57cec5SDimitry Andric   /// code to counters that will be used to find the execution
1790b57cec5SDimitry Andric   /// counts for those regions.
1800b57cec5SDimitry Andric   void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS);
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   /// Emit the coverage mapping data for an unused function.
1830b57cec5SDimitry Andric   /// It creates mapping regions with the counter of zero.
1840b57cec5SDimitry Andric   void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS);
1850b57cec5SDimitry Andric };
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric } // end namespace CodeGen
1880b57cec5SDimitry Andric } // end namespace clang
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric #endif
191