192 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Instrumentation-based code coverage mapping generator10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H14#define LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H15 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 25namespace llvm::coverage {26extern cl::opt<bool> SystemHeadersCoverage;27}28 29namespace clang {30 31class LangOptions;32class SourceManager;33class FileEntry;34class Preprocessor;35class Decl;36class Stmt;37 38struct 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 range51 Kind RangeKind;52 53 bool isComment() { return RangeKind == Comment; }54 bool isEmptyLine() { return RangeKind == EmptyLine; }55 bool isPPIfElse() { return RangeKind == PPIfElse; }56 57 SkippedRange(SourceRange Range, Kind K,58 SourceLocation PrevTokLoc = SourceLocation(),59 SourceLocation NextTokLoc = SourceLocation())60 : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc),61 RangeKind(K) {}62};63 64/// Stores additional source code information like skipped ranges which65/// is required by the coverage mapping generator and is obtained from66/// the preprocessor.67class 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 75public:76 // Location of the token parsed before HandleComment is called. This is77 // updated every time Preprocessor::Lex lexes a new token.78 SourceLocation PrevTokLoc;79 80 CoverageSourceInfo(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}81 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 95namespace CodeGen {96 97class CodeGenModule;98class CounterPair;99 100namespace MCDC {101struct State;102}103 104/// Organizes the cross-function state that is used while generating105/// code coverage mapping data.106class CoverageMappingModuleGen {107 /// Information needed to emit a coverage record for a function.108 struct FunctionInfo {109 uint64_t NameHash;110 uint64_t FuncHash;111 std::string CoverageMapping;112 bool IsUsed;113 };114 115 CodeGenModule &CGM;116 CoverageSourceInfo &SourceInfo;117 llvm::SmallDenseMap<FileEntryRef, unsigned, 8> FileEntries;118 std::vector<llvm::Constant *> FunctionNames;119 std::vector<FunctionInfo> FunctionRecords;120 121 std::string getCurrentDirname();122 std::string normalizeFilename(StringRef Filename);123 124 /// Emit a function record.125 void emitFunctionMappingRecord(const FunctionInfo &Info,126 uint64_t FilenamesRef);127 128public:129 static CoverageSourceInfo *setUpCoverageCallbacks(Preprocessor &PP);130 131 CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo);132 133 CoverageSourceInfo &getSourceInfo() const {134 return SourceInfo;135 }136 137 /// Add a function's coverage mapping record to the collection of the138 /// function mapping records.139 void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,140 StringRef FunctionNameValue,141 uint64_t FunctionHash,142 const std::string &CoverageMapping,143 bool IsUsed = true);144 145 /// Emit the coverage mapping data for a translation unit.146 void emit();147 148 /// Return the coverage mapping translation unit file id149 /// for the given file.150 unsigned getFileID(FileEntryRef File);151 152 /// Return an interface into CodeGenModule.153 CodeGenModule &getCodeGenModule() { return CGM; }154};155 156/// Organizes the per-function state that is used while generating157/// code coverage mapping data.158class CoverageMappingGen {159 CoverageMappingModuleGen &CVM;160 SourceManager &SM;161 const LangOptions &LangOpts;162 llvm::DenseMap<const Stmt *, CounterPair> *CounterMap;163 MCDC::State *MCDCState;164 165public:166 CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,167 const LangOptions &LangOpts)168 : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr),169 MCDCState(nullptr) {}170 171 CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,172 const LangOptions &LangOpts,173 llvm::DenseMap<const Stmt *, CounterPair> *CounterMap,174 MCDC::State *MCDCState)175 : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap),176 MCDCState(MCDCState) {}177 178 /// Emit the coverage mapping data which maps the regions of179 /// code to counters that will be used to find the execution180 /// counts for those regions.181 void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS);182 183 /// Emit the coverage mapping data for an unused function.184 /// It creates mapping regions with the counter of zero.185 void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS);186};187 188} // end namespace CodeGen189} // end namespace clang190 191#endif192