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