Home | History | Annotate | Line # | Download | only in CodeGen
      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   SourceRange Range;
     35   // The location of token before the skipped source range.
     36   SourceLocation PrevTokLoc;
     37   // The location of token after the skipped source range.
     38   SourceLocation NextTokLoc;
     39 
     40   SkippedRange(SourceRange Range, SourceLocation PrevTokLoc = SourceLocation(),
     41                SourceLocation NextTokLoc = SourceLocation())
     42       : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc) {}
     43 };
     44 
     45 /// Stores additional source code information like skipped ranges which
     46 /// is required by the coverage mapping generator and is obtained from
     47 /// the preprocessor.
     48 class CoverageSourceInfo : public PPCallbacks,
     49                            public CommentHandler,
     50                            public EmptylineHandler {
     51   // A vector of skipped source ranges and PrevTokLoc with NextTokLoc.
     52   std::vector<SkippedRange> SkippedRanges;
     53 
     54   SourceManager &SourceMgr;
     55 
     56 public:
     57   // Location of the token parsed before HandleComment is called. This is
     58   // updated every time Preprocessor::Lex lexes a new token.
     59   SourceLocation PrevTokLoc;
     60 
     61   CoverageSourceInfo(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
     62 
     63   std::vector<SkippedRange> &getSkippedRanges() { return SkippedRanges; }
     64 
     65   void AddSkippedRange(SourceRange Range);
     66 
     67   void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
     68 
     69   void HandleEmptyline(SourceRange Range) override;
     70 
     71   bool HandleComment(Preprocessor &PP, SourceRange Range) override;
     72 
     73   void updateNextTokLoc(SourceLocation Loc);
     74 };
     75 
     76 namespace CodeGen {
     77 
     78 class CodeGenModule;
     79 
     80 /// Organizes the cross-function state that is used while generating
     81 /// code coverage mapping data.
     82 class CoverageMappingModuleGen {
     83   /// Information needed to emit a coverage record for a function.
     84   struct FunctionInfo {
     85     uint64_t NameHash;
     86     uint64_t FuncHash;
     87     std::string CoverageMapping;
     88     bool IsUsed;
     89   };
     90 
     91   CodeGenModule &CGM;
     92   CoverageSourceInfo &SourceInfo;
     93   llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
     94   std::vector<llvm::Constant *> FunctionNames;
     95   std::vector<FunctionInfo> FunctionRecords;
     96   std::map<std::string, std::string> CoveragePrefixMap;
     97 
     98   std::string getCurrentDirname();
     99   std::string normalizeFilename(StringRef Filename);
    100 
    101   /// Emit a function record.
    102   void emitFunctionMappingRecord(const FunctionInfo &Info,
    103                                  uint64_t FilenamesRef);
    104 
    105 public:
    106   static CoverageSourceInfo *setUpCoverageCallbacks(Preprocessor &PP);
    107 
    108   CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo);
    109 
    110   CoverageSourceInfo &getSourceInfo() const {
    111     return SourceInfo;
    112   }
    113 
    114   /// Add a function's coverage mapping record to the collection of the
    115   /// function mapping records.
    116   void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
    117                                 StringRef FunctionNameValue,
    118                                 uint64_t FunctionHash,
    119                                 const std::string &CoverageMapping,
    120                                 bool IsUsed = true);
    121 
    122   /// Emit the coverage mapping data for a translation unit.
    123   void emit();
    124 
    125   /// Return the coverage mapping translation unit file id
    126   /// for the given file.
    127   unsigned getFileID(const FileEntry *File);
    128 
    129   /// Return an interface into CodeGenModule.
    130   CodeGenModule &getCodeGenModule() { return CGM; }
    131 };
    132 
    133 /// Organizes the per-function state that is used while generating
    134 /// code coverage mapping data.
    135 class CoverageMappingGen {
    136   CoverageMappingModuleGen &CVM;
    137   SourceManager &SM;
    138   const LangOptions &LangOpts;
    139   llvm::DenseMap<const Stmt *, unsigned> *CounterMap;
    140 
    141 public:
    142   CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
    143                      const LangOptions &LangOpts)
    144       : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr) {}
    145 
    146   CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
    147                      const LangOptions &LangOpts,
    148                      llvm::DenseMap<const Stmt *, unsigned> *CounterMap)
    149       : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap) {}
    150 
    151   /// Emit the coverage mapping data which maps the regions of
    152   /// code to counters that will be used to find the execution
    153   /// counts for those regions.
    154   void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS);
    155 
    156   /// Emit the coverage mapping data for an unused function.
    157   /// It creates mapping regions with the counter of zero.
    158   void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS);
    159 };
    160 
    161 } // end namespace CodeGen
    162 } // end namespace clang
    163 
    164 #endif
    165