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