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 Comment, 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 isComment() { 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 /// Organizes the cross-function state that is used while generating 95 /// code coverage mapping data. 96 class CoverageMappingModuleGen { 97 /// Information needed to emit a coverage record for a function. 98 struct FunctionInfo { 99 uint64_t NameHash; 100 uint64_t FuncHash; 101 std::string CoverageMapping; 102 bool IsUsed; 103 }; 104 105 CodeGenModule &CGM; 106 CoverageSourceInfo &SourceInfo; 107 llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries; 108 std::vector<llvm::Constant *> FunctionNames; 109 std::vector<FunctionInfo> FunctionRecords; 110 std::map<std::string, std::string> CoveragePrefixMap; 111 112 std::string getCurrentDirname(); 113 std::string normalizeFilename(StringRef Filename); 114 115 /// Emit a function record. 116 void emitFunctionMappingRecord(const FunctionInfo &Info, 117 uint64_t FilenamesRef); 118 119 public: 120 static CoverageSourceInfo *setUpCoverageCallbacks(Preprocessor &PP); 121 122 CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo); 123 124 CoverageSourceInfo &getSourceInfo() const { 125 return SourceInfo; 126 } 127 128 /// Add a function's coverage mapping record to the collection of the 129 /// function mapping records. 130 void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, 131 StringRef FunctionNameValue, 132 uint64_t FunctionHash, 133 const std::string &CoverageMapping, 134 bool IsUsed = true); 135 136 /// Emit the coverage mapping data for a translation unit. 137 void emit(); 138 139 /// Return the coverage mapping translation unit file id 140 /// for the given file. 141 unsigned getFileID(const FileEntry *File); 142 143 /// Return an interface into CodeGenModule. 144 CodeGenModule &getCodeGenModule() { return CGM; } 145 }; 146 147 /// Organizes the per-function state that is used while generating 148 /// code coverage mapping data. 149 class CoverageMappingGen { 150 CoverageMappingModuleGen &CVM; 151 SourceManager &SM; 152 const LangOptions &LangOpts; 153 llvm::DenseMap<const Stmt *, unsigned> *CounterMap; 154 155 public: 156 CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM, 157 const LangOptions &LangOpts) 158 : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr) {} 159 160 CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM, 161 const LangOptions &LangOpts, 162 llvm::DenseMap<const Stmt *, unsigned> *CounterMap) 163 : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap) {} 164 165 /// Emit the coverage mapping data which maps the regions of 166 /// code to counters that will be used to find the execution 167 /// counts for those regions. 168 void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS); 169 170 /// Emit the coverage mapping data for an unused function. 171 /// It creates mapping regions with the counter of zero. 172 void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS); 173 }; 174 175 } // end namespace CodeGen 176 } // end namespace clang 177 178 #endif 179