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> SystemHeadersCoverage; 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 Comment, 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 isCommentSkippedRange53 bool isComment() { return RangeKind == Comment; } isEmptyLineSkippedRange54 bool isEmptyLine() { return RangeKind == EmptyLine; } isPPIfElseSkippedRange55 bool isPPIfElse() { return RangeKind == PPIfElse; } 56 57 SkippedRange(SourceRange Range, Kind K, 58 SourceLocation PrevTokLoc = SourceLocation(), 59 SourceLocation NextTokLoc = SourceLocation()) RangeSkippedRange60 : 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 CoverageSourceInfo(SourceManager & SourceMgr)80 CoverageSourceInfo(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {} 81 getSkippedRanges()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 getSourceInfo()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. getCodeGenModule()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: CoverageMappingGen(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts)165 CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM, 166 const LangOptions &LangOpts) 167 : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr), 168 MCDCState(nullptr) {} 169 CoverageMappingGen(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts,llvm::DenseMap<const Stmt *,unsigned> * CounterMap,MCDC::State * MCDCState)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